RELEASED Python 2.4, alpha 2
Heiko Wundram
heikowu at ceosg.de
Thu Aug 5 12:51:08 EDT 2004
Am Donnerstag, 5. August 2004 18:29 schrieb Christopher T King:
> They purport to solve the problems of function type declaration
> (class/static), function attributes, runtime type checking, and general
> function mangling, when each of these (save general function mangling)
> already have distinct solutions in nearly every other language. The first
> three problems are currently implemented as hacks in Python that happen to
> fall under the category of "general function mangling". Streamlining the
> hack is not the answer.
I don't think they try to solve all the things you state. Rather, it's only
about general function mangling at compile time. Whatever you need to do for
function mangling, that's up to you.
And, at least for me, as I stated elsewhere, the syntax is just fine. I've
tried it out yesterday, porting some code to 2.4a2 which used thread locks
extensively, and just writing a little class InstanceSynchronizer() which is
just a Class which defines __call__ (when decorating a function) and gets the
first parameter from the function call to acquire an instance specific lock
is certainly the right way to go.
Think of the following: (old style)
class x(object):
def __init__(self):
self.lock = threading.RLock()
def synchronized_method(self):
self.lock.acquire()
try:
<bla>
finally:
self.lock.release()
That's just plain horrible compared to what @ decorators can do:
class x(object):
synchronized = InstanceSynchronizer()
@synchronized
def synchronized_method(self):
<bla>
Writing the InstanceSynchronizer is pretty easy too:
class InstanceSynchronizer(object):
def __init__(self):
self._locks = {}
self._refs = {}
def _delete_ref(self,ref):
del self._locks[self._refs[id(ref)][1]]
del self._refs[id(ref)]
def __call__(self,f):
def fsyn(fself,*args,**kwargs):
try:
lock = self._locks[id(fself)]
except KeyError:
lock = threading.RLock()
fselfref = weakref.ref(fself,self._delete_ref)
self._locks[id(fself)] = lock
self._refs[id(fselfref)] = (fselfref,id(fself))
lock.acquire()
try:
return f(fself,*args,**kwargs)
finally:
lock.release()
return fsyn
This little class takes care of everything needed for instance locks. Writing
a class that takes care of class locks for functions (in case you need to
update class data) is easy as pie too.
class ClassSynchronizer(object):
def __init__(self):
self._lock = threading.RLock()
def __call__(self,f):
def fsyn(*args,**kwargs):
self._lock.acquire()
try:
return f(*args,**kwargs)
finally:
self._lock.release()
return fsyn
Now, if you have these two utility classes at your disposal, you can do the
following:
class someobject(object):
__instances__ = {}
isynchronized = InstanceSynchronizer()
csynchronized = ClassSynchronizer()
@csynchronized
def __init__(self):
<work on self.__instances__>
@isynchronized
@csynchronized
def do_something(self):
<work on self.__instances__ and on self>
@isynchronized
def do_somethingelse(self):
<work only on self>
Now tell me that using decorators to do synchronization isn't a lot easier to
read than the first (old) example is, and also less error-prone (resp.
acquiring/releasing locks properly and without deadlocks).
Heiko.
More information about the Python-list
mailing list