Thread specific singleton

Gabriele Farina g.farina at html.it
Fri Jun 9 11:23:47 EDT 2006


Hi,

I'm tring to implement a Singleton object that should be specific for 
every thread who create it, not global.
I tried a solution that seems to work, but I have a very poor knowledge 
of concurrent programming, so I'd like someone to help me find some 
problems in my implementation.

Here is the code:

-------------------------------------------------------------

import thread

class ThreadLock(object):

     locks = {}

     def __new__(cls):
         id = thread.get_ident()
         try:
             lock = cls.locks[id]
         except KeyError:
             lock = thread.allocate_lock()
             cls.locks[id] = lock

         return lock

     @classmethod
     def clear(cls, id=None):
         """ Clear the lock associated with a given id.

         If the id is None, thread.get_ident() is used.
         """

         if id is None:
             id = thread.get_ident()
         try:
             del cls.locks[id]
         except KeyError:
             pass

class ThreadedSingleton(object):

     pool = {}

     def __new__(cls, *args, **kw):
         lock = ThreadLock()
         lock.acquire()

         id = thread.get_ident()
         try:
             obj = cls.pool[id]
         except KeyError:
             obj = object.__new__(cls, *args, **kw)
             if hasattr(obj, '__init_singleton__'):
                 obj.__init_singleton__(*args, **kw)
             cls.pool[id] = obj

         lock.release()

         return obj

     def __del__(self):
         id = thread.get_ident()
         ThreadLock.clear(id)
         try:
             del cls.pool[id]
         except KeyError:
             pass

if __name__ == '__main__':

     import time
     import random

     class Specific(ThreadedSingleton):

         def __init_singleton__(self):
             print "Init singleton"
             self.a = None

     def test(a):
         s = Specific()
         s.a = a
         print "%d: %s" %(thread.get_ident(), Specific().a)
         time.sleep(1)
         print "%d: %s" %(thread.get_ident(), Specific().a)
         time.sleep(random.randint(1, 5))
         print "%d: %s" %(thread.get_ident(), Specific().a)
         time.sleep(2)
         print "%d: %s" %(thread.get_ident(), Specific().a)

     for x in range(4):
         thread.start_new_thread(test, (x, ))

     time.sleep(10)

-------------------------------------------------------------

using the thread module should be fine even if threads are created 
trought the threading module, right ?

Thanks,
Gabriele



More information about the Python-list mailing list