@classmethod<EOL><INDENT>def synchronized(cls, obj=None):<DEDENT>
def get_key(f, o):<EOL><INDENT>if o is None:<EOL><INDENT>key = hash(f)<EOL><DEDENT>else:<EOL><INDENT>key = hash(o)<EOL><DEDENT>return key<EOL><DEDENT>def get_lock(f, o):<EOL><INDENT>key = get_key(f, o)<EOL>if key not in cls.lock_map:<EOL><INDENT>with cls.lock_map_lock:<EOL><INDENT>if key not in cls.lock_map:<EOL><INDENT>cls.lock_map[key] = _init_lock()<EOL><DEDENT><DEDENT><DEDENT>return cls.lock_map[key]<EOL><DEDENT>def wrap(f):<EOL><INDENT>@functools.wraps(f)<EOL>def new_func(*args, **kw):<EOL><INDENT>with get_lock(f, obj):<EOL><INDENT>return f(*args, **kw)<EOL><DEDENT><DEDENT>return new_func<EOL><DEDENT>return wrap<EOL>
synchronize on obj if obj is supplied.

        :param obj: the obj to lock on.  if none, lock to the function
        :return: return of the func.