Synchronization mixin in Python anyone?
Chris Liechti
cliechti at gmx.net
Fri May 3 22:28:15 EDT 2002
sorry if this msg show up multiple times - i had troubles posting...
Sean McGrath <sean.mcgrath at propylon.com> wrote in
news:mailman.1020454627.587.python-list at python.org:
> The Zope system contains a Synchronization mixin class
> for thread synchronization written in C. Derive a class from Synchronized
> and any mythod calls on an instance of the class are
> thread safe.
>
> Does anybody know of any Python implementation? The C version
> exhibits "interesting" refcounting behavior I need to work around.
not exactly what you asked for but solving exactly that problem...
i attched my attempt to make a method "synchronized" (like known from
Java). as you will see in the source comment, there is a small problem on
the first use of a sync'd method.
someone on the group with a solution appart from derriving from a special
base class "Synchronized" which does allocate the condition object? (yes
that works but it's a lot more typing and the user has the "chance" to
forget the __init__ of it etc. )-:
chris
---------------synchronized.py
#! /usr/bin/env python
#
# emulate Java's synchronized methods through a threading.Condition object
# python 2.1+ required
# cliechti at gmx.net
from __future__ import nested_scopes #for those who still use 2.1 ;-)
import threading
def synchronized(f):
"""use this method like "staticmethod" to wrap methods in a class."""
def syncwrap(self, *args,**kwargs):
#first of all there is no lock, the moment where one is created
#is critical - if two or more threads enter a sync'd method on a
#"fresh" instance both might create a __lock but the first one
#looses his Condition object which was overwriten by the second
#thread. one solution could be to implement the wrap function in
#c and enable threading right before the wrapped method is called.
try:
self.__lock.acquire()
except AttributeError: #lock does not yet exist (first time use)
self.__lock = threading.Condition()
self.__lock.acquire()
#mirror those practical methods on the instance itself
self.wait = self.__lock.wait
self.notifyAll = self.__lock.notifyAll
self.notify = self.__lock.notify
try:
return f(self, *args,**kwargs)
finally:
self.__lock.release()
return syncwrap
if __name__ == '__main__':
#testing...
class B:
def f(self):
import time
print "waiting for 3 seconds...",
time.sleep(3)
print "ok"
f = synchronized(f)
def g(self):
print "just g()"
g = synchronized(g)
def cons(self):
print "cons() waiting..."
self.wait()
print "cons() ok"
cons = synchronized(cons)
def prod(self):
print "prod() notify"
self.notifyAll()
prod = synchronized(prod)
b=B()
#simple locking test
threading.Timer(1, b.g).start() #call g while still in f
b.f() #f will take 3 seconds
#consumer-producer problem test
threading.Timer(2, b.prod).start() #call prod after a short delay
b.cons() #wait until prod notifies
--
Chris <cliechti at gmx.net>
More information about the Python-list
mailing list