I
Irmen de Jong
I created my first ever Python Meta Class to solve a
problem I'm having. I have an existing class that I want
to make thread-safe: all method calls should use a thread-lock
to avoid having multiple threads active in the class at the
same time. I don't want to change every method of the class
by adding lock.acquire()...try...finally..lock.release() stuff,
so I decided to try it with a Meta Class.
Below is what I came up with (after a bit of googling).
Since it's my first attempt at a non-trivial meta class,
can you please comment on it? Is this the way to do things?
It appears to work, at least the example method call at the
bottom prints:
[E:\]python meta.pyirmen 42
<<released lock
which is what I wanted..
--
Irmen de Jong.
#----------Code follows-----------
from types import FunctionType
from threading import RLock
class MonitorMetaClass(type):
def __new__(meta, name, bases, dict):
meta.convert_methods(dict)
return super(MonitorMetaClass, meta).__new__(meta, name, bases, dict)
def makeThreadsafeMethod(func):
def threadsafemethod(self, *args, **kwargs):
self._monitor_lockObj.acquire()
print ">>got lock"
try:
return func(self, *args, **kwargs)
finally:
self._monitor_lockObj.release()
print "<<released lock"
return threadsafemethod
makeThreadsafeMethod = staticmethod(makeThreadsafeMethod)
def convert_methods(cls, dict):
methods=[ v for k,v in dict.iteritems() if isinstance(v, FunctionType) ]
for m in methods:
dict[m.__name__]=cls.makeThreadsafeMethod(m)
dict["_monitor_lockObj"] = RLock()
convert_methods = classmethod(convert_methods)
class MyClass(object):
__metaclass__=MonitorMetaClass
def method(self, a1, a2):
print a1,a2
m=MyClass()
m.method("irmen",42)
problem I'm having. I have an existing class that I want
to make thread-safe: all method calls should use a thread-lock
to avoid having multiple threads active in the class at the
same time. I don't want to change every method of the class
by adding lock.acquire()...try...finally..lock.release() stuff,
so I decided to try it with a Meta Class.
Below is what I came up with (after a bit of googling).
Since it's my first attempt at a non-trivial meta class,
can you please comment on it? Is this the way to do things?
It appears to work, at least the example method call at the
bottom prints:
[E:\]python meta.pyirmen 42
<<released lock
which is what I wanted..
--
Irmen de Jong.
#----------Code follows-----------
from types import FunctionType
from threading import RLock
class MonitorMetaClass(type):
def __new__(meta, name, bases, dict):
meta.convert_methods(dict)
return super(MonitorMetaClass, meta).__new__(meta, name, bases, dict)
def makeThreadsafeMethod(func):
def threadsafemethod(self, *args, **kwargs):
self._monitor_lockObj.acquire()
print ">>got lock"
try:
return func(self, *args, **kwargs)
finally:
self._monitor_lockObj.release()
print "<<released lock"
return threadsafemethod
makeThreadsafeMethod = staticmethod(makeThreadsafeMethod)
def convert_methods(cls, dict):
methods=[ v for k,v in dict.iteritems() if isinstance(v, FunctionType) ]
for m in methods:
dict[m.__name__]=cls.makeThreadsafeMethod(m)
dict["_monitor_lockObj"] = RLock()
convert_methods = classmethod(convert_methods)
class MyClass(object):
__metaclass__=MonitorMetaClass
def method(self, a1, a2):
print a1,a2
m=MyClass()
m.method("irmen",42)