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