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(o bject):
__buffer = {}
__bufferLock = threading.RLock ()
def __new__(cls,*ar gs,**kwargs):
cls.__bufferLoc k.acquire()
try:
inst = cls.__create_ne w__(buffer,*arg s,**kwargs)
if not hasattr(inst,"_ SingletonBase__ instanceLock"):
inst.__instance Lock = threading.RLock ()
inst.__initiali zed = False
return inst
finally:
cls.__bufferLoc k.release()
@classmethod
def __create_new__( cls,*args,**kwa rgs):
return super(Singleton Base,cls).__new __(cls)
def __init__(self,* args,**kwargs):
self.__instance Lock.acquire()
try:
if not self.__initiali zed:
self.__initiali ze_new__(*args, **kwargs)
self.__initiali zed = True
else:
self.__update_o ld__(*args,**kw args)
finally:
self.__instance Lock.release()
def __initialize_ne w__(self,*args, **kwargs):
pass
def __update_old__( self,*args,**kw args):
pass
class Singleton(Singl etonBase):
@classmethod
def __create_new__( cls,buffer,some arg):
inst = buffer.get(some arg,lambda: None)()
if inst is None:
inst = super(Singleton ,cls).__create_ new__(cls)
buffer[somearg] = weakref.ref(ins t)
return inst
def __initialize_ne w__(self,somear g):
print "Initializi ng 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 "\nRecreati ng 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__.Singl eton object at 0xb7bfbc6c>
<__main__.Singl eton object at 0xb7bfbcac>
<__main__.Singl eton 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__.Singl eton object at 0xb7bfbc6c>
<__main__.Singl eton object at 0xb7bfbc6c>
x is y
True
</output>
HTH!
--
--- Heiko.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
iD8DBQBCShdSf0b pgh6uVAMRAmIMAJ 9EzsSRebvDog6ti xm3MEp3OXBDngCb B6Eu
OYud8wmgcKUyODe dkrW4PAQ=
=P8Nt
-----END PGP SIGNATURE-----