Skip to content Skip to sidebar Skip to footer

Possible To Create A @synchronized Decorator That's Aware Of A Method's Object?

I'm trying to create a @synchronized wrapper that creates one Lock per object and makes method calls thread safe. I can only do this if I can access method.im_self of the method in

Solution 1:

Go read:

and in particular:

The wrapt module then contains the @synchronized decorator described there.

The full implementation is flexible enough to do:

@synchronized # lock bound to function1
def function1():
    pass 

@synchronized # lock bound to function2
def function2():
    pass 

@synchronized # lock bound to Class
class Class(object):  

    @synchronized # lock bound to instance of Class
    def function_im(self):
        pass 

    @synchronized # lock bound to Class
    @classmethod
    def function_cm(cls):
        pass

    @synchronized # lock bound to function_sm
    @staticmethod
    def function_sm():
        pass

Along with context manager like usage as well:

classObject(object):  

    @synchronizeddeffunction_im_1(self):
        passdeffunction_im_2(self):
        with synchronized(self):
            pass

Further information and examples can also be found in:

There is also a conference talk you can watch on how this is implemented at:

Solution 2:

(1) What's confusing is that the func parameter passed to my decorator changes type before it gets passed into the wrapper-generator. This seem is rude and unnecessary. Why does this happen?

It doesn't! Rather, function objects (and other descriptors) produce their __get__'s results when that method of theirs is called -- and that result is the method object!

But what lives in the class's __dict__ is always the descriptor -- specifically, the function object! Check it out...:

>>>classX(object):...defx(self): pass...>>>X.__dict__['x']
<function x at 0x10fe04e60>
>>>type(X.__dict__['x'])
<type 'function'>

See? No method objects around anywhere at all!-)

Therefore, no im_self around either, at decoration time -- and you'll need to go with your introspection-based alternative idea.

Solution 3:

You can't get self at decoration time because the decorator is applied at function definition time. No self exists yet; in fact, the class doesn't exist yet.

If you're willing to store your lock on the instance (which is arguably where a per-instance value should go) then this might do ya:

defsynchronized_method(func):
    def_synchronized(self, *args, **kw):
         ifnothasattr(self, "_lock"): self._lock = oneLockPerObject(self)
         with self._lock: return func(self, *args, **kw)
    return _synchronized

You could also generate the lock in your __init__() method on a base class of some sort, and store it on the instance in the same way. That simplifies your decorator because you don't have to check for the existence of the self._lock attribute.

Post a Comment for "Possible To Create A @synchronized Decorator That's Aware Of A Method's Object?"