Coverage for src\zapy\utils\singleton.py: 100%

1 from threading import Lock

2

3

4 class SingletonMeta(type):

5 """

6 This is a thread-safe implementation of Singleton.

7 """

8

9 _instances = {}

10

11 _lock: Lock = Lock()

12 """

13 We now have a lock object that will be used to synchronize threads during

14 first access to the Singleton.

15 """

16

17 def __call__(cls, *args, **kwargs):

18 """

19 Possible changes to the value of the `__init__` argument do not affect

20 the returned instance.

21 """

22 # Now, imagine that the program has just been launched. Since there's no

23 # Singleton instance yet, multiple threads can simultaneously pass the

24 # previous conditional and reach this point almost at the same time. The

25 # first of them will acquire lock and will proceed further, while the

26 # rest will wait here.

27 with cls._lock:

28 # The first thread to acquire the lock, reaches this conditional,

29 # goes inside and creates the Singleton instance. Once it leaves the

30 # lock block, a thread that might have been waiting for the lock

31 # release may then enter this section. But since the Singleton field

32 # is already initialized, the thread won't create a new object.

33 if cls not in cls._instances:

34 instance = super().__call__(*args, **kwargs)

35 cls._instances[cls] = instance

36 return cls._instances[cls]