Author: dmeyer
Date: Sat Mar  1 11:05:01 2008
New Revision: 3144

Log:
Improve kaa.synchronized. It can be used as decorator and with
with statements and supports any object as lock. This is similar
to synchronized in Java.


Added:
   trunk/base/test/synchronized.py
Modified:
   trunk/base/src/notifier/thread.py

Modified: trunk/base/src/notifier/thread.py
==============================================================================
--- trunk/base/src/notifier/thread.py   (original)
+++ trunk/base/src/notifier/thread.py   Sat Mar  1 11:05:01 2008
@@ -58,7 +58,6 @@
 import fcntl
 import socket
 import errno
-import thread
 import types
 
 # notifier imports
@@ -129,20 +128,74 @@
     return decorator
 
 
-def synchronized(lock=threading.Lock()):
+class synchronized(object):
     """
-    Synchronization decorator. This decorator does not work
-    together with coroutines (yet).
-    """
-    def decorator(f):
-        def newFunction(*args, **kw):
+    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):
+            # 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 f(*args, **kw)
+                return func(*args, **kwargs)
             finally:
                 lock.release()
-        return newFunction
-    return decorator
+        return call
 
 
 def is_mainthread():
@@ -371,7 +424,7 @@
 
     def _create_job(self, *args, **kwargs):
         cb = Callback._get_callback(self)
-        job = thread.ThreadInProgress(cb, *args, **kwargs)
+        job = ThreadInProgress(cb, *args, **kwargs)
         job.priority = self.priority
         if not _threads.has_key(self._thread):
             _threads[self._thread] = _JobServer(self._thread)

Added: trunk/base/test/synchronized.py
==============================================================================
--- (empty file)
+++ trunk/base/test/synchronized.py     Sat Mar  1 11:05:01 2008
@@ -0,0 +1,45 @@
+from __future__ import with_statement
+import threading
+import kaa
+
+class Test(object):
+
+    def foo(self):
+        with kaa.synchronized(self):
+            print 5
+
+    @kaa.synchronized()
+    def bar(self, x, y):
+        print 1, x, y
+
+
+# threading.Lock does NOT work
+lock = threading.RLock()
[EMAIL PROTECTED](lock)
+def foo():
+    print 6
+
+t = Test()
+
[EMAIL PROTECTED](t)
+def bar(x):
+    print 7, x
+
[EMAIL PROTECTED]()
+def zap(x):
+    print 9, x
+
[EMAIL PROTECTED]()
+def baz():
+    print 10
+
+t.bar(5, 9)
+t.foo()
+
+t2 = Test()
+t2.foo()
+
+foo()
+bar(8)
+zap(8)
+baz()

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to