azurelinuxagent/common/singletonperthread.py (12 lines of code) (raw):
from threading import Lock, current_thread
class _SingletonPerThreadMetaClass(type):
""" A metaclass that creates a SingletonPerThread base class when called. """
_instances = {}
_lock = Lock()
def __call__(cls, *args, **kwargs):
with cls._lock:
# Object Name = className__threadName
obj_name = "%s__%s" % (cls.__name__, current_thread().name)
if obj_name not in cls._instances:
cls._instances[obj_name] = super(_SingletonPerThreadMetaClass, cls).__call__(*args, **kwargs)
return cls._instances[obj_name]
class SingletonPerThread(_SingletonPerThreadMetaClass('SingleObjectPerThreadMetaClass', (object,), {})):
# This base class calls the metaclass above to create the singleton per thread object. This class provides an
# abstraction over how to invoke the Metaclass so just inheriting this class makes the
# child class a singleton per thread (As opposed to invoking the Metaclass separately for each derived classes)
# More info here - https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python
#
# Usage:
# Inheriting this class will create a Singleton per thread for that class
# To delete the cached object of a class, call DerivedClassName.clear() to delete the object per thread
# Note: If the thread dies and is recreated with the same thread name, the existing object would be reused
# and no new object for the derived class would be created unless DerivedClassName.clear() is called explicitly to
# delete the cache
pass