from functools import wraps
from threading import RLock
def lock_for_object(obj, locks={}):
return locks.setdefault(id(obj), RLock())
def synchronized(call):
assert call.__code__.co_varnames[0] in ['self', 'cls']
@wraps(call)
def inner(*args, **kwds):
with lock_for_object(args[0]):
return call(*args, **kwds)
return inner