Thread specific singleton

  • Thread starter Gabriele Farina
  • Start date
G

Gabriele Farina

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
 
A

Aahz

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.

Try using threading.local(), but you'll need 2.4 or later.
 
J

jhnsmth

Gabriele said:
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

import thread

class Singleton:
pass

singletons = {}

def get_singleton():
ident = thread.get_ident()
try:
singleton = singletons[ident]
except KeyError:
singleton = Singleton()
singletons[ident] = singleton
return singleton
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top