Skip to content

Instantly share code, notes, and snippets.

@wys1203
Forked from sodastsai/singleton.py
Created June 2, 2016 10:06
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wys1203/830f52c31151226599ac015b87b6e05c to your computer and use it in GitHub Desktop.
Save wys1203/830f52c31151226599ac015b87b6e05c to your computer and use it in GitHub Desktop.
Python singleton metaclass (thread-safe)
from __future__ import absolute_import, division, print_function, unicode_literals
from multiprocessing.dummy import Pool as ThreadPool
from multiprocessing import Lock
from threading import get_ident
class SingletonType(type):
def __new__(mcs, name, bases, attrs):
# Assume the target class is created (i.e. this method to be called) in the main thread.
cls = super(SingletonType, mcs).__new__(mcs, name, bases, attrs)
cls.__shared_instance_lock__ = Lock()
return cls
def __call__(cls, *args, **kwargs):
with cls.__shared_instance_lock__:
try:
return cls.__shared_instance__
except AttributeError:
cls.__shared_instance__ = super(SingletonType, cls).__call__(*args, **kwargs)
return cls.__shared_instance__
class NonThreadSafeSingletonType(type):
def __call__(cls, *args, **kwargs):
try:
return cls.__shared_instance__
except AttributeError:
cls.__shared_instance__ = super(NonThreadSafeSingletonType, cls).__call__(*args, **kwargs)
return cls.__shared_instance__
def run(DatabaseClass):
result_set = set()
result_set_access_lock = Lock()
def worker(_result_set, _result_set_access_lock):
db = DatabaseClass()
with _result_set_access_lock:
_result_set.add(db)
thread_pool = ThreadPool(10)
for i in six.moves.range(100):
thread_pool.apply_async(worker, (result_set, result_set_access_lock))
thread_pool.close()
thread_pool.join()
print(result_set)
print(len(result_set))
if __name__ == "__main__":
import six
class DatabaseBase(object):
def __init__(self):
super(DatabaseBase, self).__init__()
print("Created in thread: {}".format(get_ident()))
def __repr__(self):
return "<A database>"
@six.add_metaclass(SingletonType)
class Database(DatabaseBase):
pass
@six.add_metaclass(NonThreadSafeSingletonType)
class NonThreadSafeDatabase(DatabaseBase):
pass
class NonSingletonDatabase(DatabaseBase):
pass
print("Thread-safe Singleton =============================")
run(Database)
print("Thread-safe Singleton =============================\n\n")
print("Non-Thread-safe Singleton =========================")
run(NonThreadSafeDatabase)
print("Non-Thread-safe Singleton =========================\n\n")
print("Normal ============================================")
run(NonSingletonDatabase)
print("Normal ============================================\n\n")
Thread-safe Singleton =============================
Created in thread: 123145307557888
{<A database>}
1
Thread-safe Singleton =============================
Non-Thread-safe Singleton =========================
Created in thread: 123145307557888
Created in thread: 123145312813056
Created in thread: 123145323323392
Created in thread: 123145339088896
Created in thread: 123145344344064
Created in thread: 123145354854400
Created in thread: 123145328578560
Created in thread: 123145349599232
Created in thread: 123145333833728
Created in thread: 123145318068224
{<A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>}
10
Non-Thread-safe Singleton =========================
Normal ============================================
Created in thread: 123145307557888
Created in thread: 123145312813056
Created in thread: 123145323323392
Created in thread: 123145333833728
Created in thread: 123145344344064
Created in thread: 123145354854400
Created in thread: 123145318068224
Created in thread: 123145339088896
Created in thread: 123145307557888
Created in thread: 123145349599232
Created in thread: 123145312813056
Created in thread: 123145328578560
Created in thread: 123145323323392
Created in thread: 123145333833728
Created in thread: 123145344344064
Created in thread: 123145354854400
Created in thread: 123145318068224
Created in thread: 123145339088896
Created in thread: 123145307557888
Created in thread: 123145349599232
Created in thread: 123145312813056
Created in thread: 123145328578560
Created in thread: 123145323323392
Created in thread: 123145333833728
Created in thread: 123145344344064
Created in thread: 123145354854400
Created in thread: 123145318068224
Created in thread: 123145339088896
Created in thread: 123145307557888
Created in thread: 123145349599232
Created in thread: 123145312813056
Created in thread: 123145328578560
Created in thread: 123145323323392
Created in thread: 123145333833728
Created in thread: 123145344344064
Created in thread: 123145354854400
Created in thread: 123145318068224
Created in thread: 123145339088896
Created in thread: 123145307557888
Created in thread: 123145349599232
Created in thread: 123145312813056
Created in thread: 123145328578560
Created in thread: 123145323323392
Created in thread: 123145333833728
Created in thread: 123145344344064
Created in thread: 123145354854400
Created in thread: 123145318068224
Created in thread: 123145339088896
Created in thread: 123145307557888
Created in thread: 123145349599232
Created in thread: 123145312813056
Created in thread: 123145328578560
Created in thread: 123145333833728
Created in thread: 123145344344064
Created in thread: 123145354854400
Created in thread: 123145323323392
Created in thread: 123145307557888
Created in thread: 123145349599232
Created in thread: 123145339088896
Created in thread: 123145333833728
Created in thread: 123145344344064
Created in thread: 123145312813056
Created in thread: 123145328578560
Created in thread: 123145349599232
Created in thread: 123145339088896
Created in thread: 123145354854400
Created in thread: 123145323323392
Created in thread: 123145307557888
Created in thread: 123145328578560
Created in thread: 123145333833728
Created in thread: 123145344344064
Created in thread: 123145312813056
Created in thread: 123145318068224
Created in thread: 123145349599232
Created in thread: 123145339088896
Created in thread: 123145333833728
Created in thread: 123145344344064
Created in thread: 123145328578560
Created in thread: 123145354854400
Created in thread: 123145323323392
Created in thread: 123145339088896
Created in thread: 123145333833728
Created in thread: 123145312813056
Created in thread: 123145318068224
Created in thread: 123145354854400
Created in thread: 123145307557888
Created in thread: 123145344344064
Created in thread: 123145328578560
Created in thread: 123145312813056
Created in thread: 123145323323392
Created in thread: 123145339088896
Created in thread: 123145333833728
Created in thread: 123145344344064
Created in thread: 123145318068224
Created in thread: 123145354854400
Created in thread: 123145307557888
Created in thread: 123145328578560
Created in thread: 123145323323392
Created in thread: 123145312813056
Created in thread: 123145349599232
{<A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>, <A database>}
100
Normal ============================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment