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()