from __future__ import with_statement import thread import threading class synchronized(object): """ synchronized decorator and with statement similar to synchronized in Java. When decorating a non-member function, a lock or any class inheriting from object must be provided. """ def __init__(self, obj=None): if obj is None: # decorator in classes self._lock = None return if isinstance(obj, (threading._RLock, thread.LockType)): # decorator from functions self._lock = obj return # with statement or function decorator with object if not hasattr(obj, '_kaa_synchronized_lock'): obj._kaa_synchronized_lock = threading.RLock() self._lock = obj._kaa_synchronized_lock def __enter__(self): """ with statement enter """ if self._lock is None: raise RuntimeError('synchronized in with needs a parameter') self._lock.acquire() return self._lock def __exit__(self, type, value, traceback): """ with statement exit """ self._lock.release() return False def __call__(self, func): """ decorator init """ def call(*args, **kwargs): """ decorator call """ lock = self._lock if lock is None: # Try to find out if the function is actually an instance method. # The decorator only sees a function object, even for methods, so # this kludge compares the code object of call (this wrapper) # with the code object of the first argument's attribute of the # function's name. If they're the same, then we must be decorating # a method, and we can attach the timer object to the instance # instead of the function. if args and call.func_code == \ getattr(getattr(args[0], func.func_name, None), 'func_code', None): # first parameter is self, link lock to self obj = args[0] else: obj = func if not hasattr(obj, '_kaa_synchronized_lock'): obj._kaa_synchronized_lock = threading.RLock() lock = obj._kaa_synchronized_lock lock.acquire() try: return func(*args, **kwargs) finally: lock.release() return call class Test(object): def foo(self): with synchronized(self): print 5 @synchronized() def bar(self, x, y): print 1, x, y lock = threading.Lock() @synchronized(lock) def foo(): print 6 t = Test() @synchronized(t) def bar(x): print 7, x @synchronized() def zap(x): print 9, x @synchronized() def baz(): print 10 t.bar(5, 9) t.foo() t2 = Test() t2.foo() foo() bar(8) zap(8) baz()