Am Mittwoch, 30. März 2005 04:36 schrieb Heiko Wundram:
You could extend the above example quite easily to deal with deallocation
(a reference to each created singleton is retained using the above class,
always, as long as the program is running) and also to make it threadsafe
or to disable initialization in case the singleton has already been
initialized before.
Just to post a complete example of a Singleton class which works in a
multithreaded environment, and allows you to update future instances (a
sample, untested implementation):
<code>
import threading
import weakref
class SingletonBase(object):
__buffer = {}
__bufferLock = threading.RLock()
def __new__(cls,*args,**kwargs):
cls.__bufferLock.acquire()
try:
inst = cls.__create_new__(buffer,*args,**kwargs)
if not hasattr(inst,"_SingletonBase__instanceLock"):
inst.__instanceLock = threading.RLock()
inst.__initialized = False
return inst
finally:
cls.__bufferLock.release()
@classmethod
def __create_new__(cls,*args,**kwargs):
return super(SingletonBase,cls).__new__(cls)
def __init__(self,*args,**kwargs):
self.__instanceLock.acquire()
try:
if not self.__initialized:
self.__initialize_new__(*args,**kwargs)
self.__initialized = True
else:
self.__update_old__(*args,**kwargs)
finally:
self.__instanceLock.release()
def __initialize_new__(self,*args,**kwargs):
pass
def __update_old__(self,*args,**kwargs):
pass
class Singleton(SingletonBase):
@classmethod
def __create_new__(cls,buffer,somearg):
inst = buffer.get(somearg,lambda: None)()
if inst is None:
inst = super(Singleton,cls).__create_new__(cls)
buffer[somearg] = weakref.ref(inst)
return inst
def __initialize_new__(self,somearg):
print "Initializing new instance."
self.__somearg = somearg
def __update_old__(self,somearg):
print "Updating old."
assert somearg == self.__somearg
# Initialize three singletons.
print "Creating singletons for 1, 2, 1."
x = Singleton(1)
y = Singleton(2)
z = Singleton(1)
# Print them out.
print "\nThree singletons: x, y, z."
print repr(x)
print repr(y)
print repr(z)
# Assert that x is not y, and x is z.
print "\nx is y, x is z"
print x is y
print x is z
# Delete names, and make sure weakrefs are unbound.
print "\nRemove all three singletons."
del x
del y
del z
# Recreate singleton for value 1.
print "\nRecreating singleton for value 1."
x = Singleton(1)
y = Singleton(1)
# Print them out.
print "\nNew Singleton(1): x, y."
print repr(x)
print repr(y)
# Check that x is y.
print "\nx is y"
print x is y
</code>
The above program prints the following output when run:
<output>
Creating singletons for 1, 2, 1.
Initializing new instance.
Initializing new instance.
Updating old.
Three singletons: x, y, z.
<__main__.Singleton object at 0xb7bfbc6c>
<__main__.Singleton object at 0xb7bfbcac>
<__main__.Singleton object at 0xb7bfbc6c>
x is y, x is z
False
True
Remove all three singletons.
Recreating singleton for value 1.
Initializing new instance.
Updating old.
New Singleton(1): x, y.
<__main__.Singleton object at 0xb7bfbc6c>
<__main__.Singleton object at 0xb7bfbc6c>
x is y
True
</output>
HTH!
--
--- Heiko.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
iD8DBQBCShdSf0bpgh6uVAMRAmIMAJ9EzsSRebvDog6tixm3MEp3OXBDngCbB6Eu
OYud8wmgcKUyODedkrW4PAQ=
=P8Nt
-----END PGP SIGNATURE-----