By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,932 Members | 1,455 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,932 IT Pros & Developers. It's quick & easy.

Thread specific singleton

P: n/a
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
Jun 9 '06 #1
Share this Question
Share on Google+
2 Replies


P: n/a
In article <44***********************@reader1.news.tin.it>,
Gabriele Farina <g.******@html.it> wrote:

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.
--
Aahz (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/

"I saw `cout' being shifted "Hello world" times to the left and stopped
right there." --Steve Gonedes
Jun 12 '06 #2

P: n/a

Gabriele Farina wrote:
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

Jun 12 '06 #3

This discussion thread is closed

Replies have been disabled for this discussion.