Automatic access serialization

Gabriel Genellina gagenellina at softlab.com.ar
Fri Jan 30 20:53:44 EST 2004


Hello!

I have a number of objects that are not thread-safe - no locking
mechanism was originally provided.
But I want to use them in a thread-safe way. I don't want to analyze
each class details, looking for where and when I must protect the
code. So I wrote this sort-of-brute-force locking mechanism using
threading.RLock() around __getattr__ / __setattr__ / __delattr__.
The idea is that *any* attribute and method access is protected by the
lock. The calling thread may acquire the lock multiple times, but
other threads must wait until it is released.
This may be too much restrictive, and a bottleneck in performance,
since *all* accesses are effectively serialized - but it's the best I
could imagine without deeply analyzing the actual code.
I *think* this works well, but since I'm not an expert in these
things, any comments are welcome. Specially what could go wrong, if
someone could anticipate it.
Note: As written, this only works for old-style classes. I think that
just by adding a similar __getattribute__ would suffice for new-style
classes too - is that true?


--- begin autolock.py ---
import threading

class AutoLock:
    # "brute-force" locking wrapper to any object
    # *all* attribute access is serialized in a thread-safe way.
    
    def __init__(self, target):
        dict = self.__dict__
        dict['_%s__lock'%self.__class__.__name__] = threading.RLock()
        dict['_%s__target'%self.__class__.__name__] = target

    def __getattr__(self, key):
        self.__lock.acquire()
        try:
            return getattr(self.__target, key)
        finally:
            self.__lock.release()
            
    def __setattr__(self, key, value):
        self.__lock.acquire()
        try:
            setattr(self.__target, key, value)
        finally:
            self.__lock.release()
            
    def __delattr__(self, key):
        self.__lock.acquire()
        try:
            delattr(self.__target, key)
        finally:
            self.__lock.release()

--- end autolock.py ---

Gabriel Genellina
Softlab SRL



More information about the Python-list mailing list