All pastes #924636 Raw Edit

Anonymous

public text v1 · immutable
·published 2008-03-01 15:43 UTC
rendered paste body
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()