to implement a cache: is there a thread safe map?
Clark C . Evans
cce at clarkevans.com
Sun Aug 12 21:19:30 EDT 2001
Pardon my ignorance here. I'm rather new to threading
and I have the following situation:
1. I have multiple threads.
2. I have several constructs ("objects") which
are very common, costly to construct,
and should be kept around for a while.
3. These objects are static once created, they
are tuples of strings).
4. The objects are used frequently, and thus
will be requested all of the time.
5. I can't predict what combination of objects
will be required at compile time.
To be a bit more pragmatic, suppose I have the
following function...
def make(args):
"""
A function that constructs a complicated
object based on its parameters.
The object constructed is a constant
(non-mutable) object, and the parameters
are also non-mutable.
This is a brain-dead version.
"""
return args
How could I go about building a "generic", thread-safe
cashe object around the following function. Thus, I'd
like...
cashedmake = CashedFunction(make)
obj = cashedmake('a')
class CashedFunction:
def __init__(self,func):
self.func = func
self.cache = {}
def __call__(self,arg):
ret = self.cache.get(arg,None)
if not(res):
ret = self.func(arg)
self.cashe[arg] = ret
return ret
My problem: (Yes, the above probably isn't right)
1. How do I make something like the above thread
safe? I would add:
self.lock = threading.Lock()
to the __init__ and then surround
self.lock.acquire()
ret = self.func(arg)
self.cashe[arg] = ret
self.loc.release()
Is this right?
a) It seems that if two threads
hit the lock.acquire() at the
same time, I'll construct the
object twice... is there a way
around this?
b) It looks like the map could be
altered mid "get", does the entire
function need to be locked, or
can I just lock the mutating portion?
c) What other concerns am I missing?
2. Dropping items from the cashe.
I suppose I could make my entries in the
map (created,value) to store the time
it was created, periodically sweeping
through the map to clear entries.
Would a weak reference help here?
Would it be better to keep another map
with the last time that a given object
was accessed?
In short... what is the interaction of a map
object and multiple threads. What do I have
to be concerned about?
Thank you so much,
Clark
More information about the Python-list
mailing list