From a49b6d737b6b0abcc2e81d1af890d701b5bbf735 Mon Sep 17 00:00:00 2001 From: Robom Date: Sun, 16 Nov 2025 12:26:17 +0530 Subject: [PATCH] Fix thread-safety issue in SingletonBase metaclass - Added threading.Lock to prevent race conditions during instance creation - Implemented double-checked locking pattern for optimal performance - Updated docstring to reflect thread-safety guarantee - Removed TODO comment as the issue is now resolved This fix ensures that the singleton pattern works correctly in parallel execution contexts, preventing potential issues where multiple threads could create multiple instances simultaneously. --- WeatherRoutingTool/algorithms/genetic/patcher.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/WeatherRoutingTool/algorithms/genetic/patcher.py b/WeatherRoutingTool/algorithms/genetic/patcher.py index c196a01..26dfe67 100644 --- a/WeatherRoutingTool/algorithms/genetic/patcher.py +++ b/WeatherRoutingTool/algorithms/genetic/patcher.py @@ -2,6 +2,7 @@ import logging import math import os +import threading from datetime import datetime from pathlib import Path @@ -41,18 +42,22 @@ def patch(self, src: tuple, dst: tuple): class SingletonBase(type): """ - TODO: make this thread-safe - Base class for Singleton implementation of patcher methods. + Thread-safe base class for Singleton implementation of patcher methods. This is the implementation of a metaclass for those classes for which only a single instance shall be available - during runtime. + during runtime. Uses a lock to ensure thread-safety during instance creation. """ _instances = {} + _lock = threading.Lock() def __call__(cls, *args, **kwargs): + # Double-checked locking pattern for thread-safety if cls not in cls._instances: - instance = super().__call__(*args, **kwargs) - cls._instances[cls] = instance + with cls._lock: + # Check again after acquiring the lock + if cls not in cls._instances: + instance = super().__call__(*args, **kwargs) + cls._instances[cls] = instance return cls._instances[cls]