Source code for radical.utils.lockable
__author__ = "Radical.Utils Development Team (Andre Merzky)"
__copyright__ = "Copyright 2013, RADICAL@Rutgers"
__license__ = "MIT"
import threading
# pylint: disable=protected-access
# ------------------------------------------------------------------------------
#
[docs]def Lockable(cls):
'''
This class decorator will add lock/unlock methods to the thusly decorated
classes, which will be enacted via an also added `threading.RLock` member
(`self._rlock`)::
@Lockable
class A(object):
def call(self):
print 'locked: %s' % self._locked
The class instance can then be used like this::
a = A()
a.call()
a.lock()
a.call()
a.lock()
a.call()
a.unlock()
a.call()
with a:
a.call()
a.call()
a.unlock()
a.call()
which will result in::
locked: 0
locked: 1
locked: 2
locked: 1
locked: 2
locked: 1
locked: 0
The class A can also internally use the lock, and can, for example, use::
@Lockable
class A(object):
...
def work(self):
with self:
# locked code section
...
'''
if hasattr(cls, '__enter__'):
raise RuntimeError("Cannot make '%s' lockable -- has __enter__" % cls)
if hasattr(cls, '__exit__'):
raise RuntimeError("Cannot make '%s' lockable -- has __exit__" % cls)
if hasattr(cls, '_rlock'):
raise RuntimeError("Cannot make '%s' lockable -- has _rlock" % cls)
if hasattr(cls, '_locked'):
raise RuntimeError("Cannot make '%s' lockable -- has _locked" % cls)
if hasattr(cls, 'locked'):
raise RuntimeError("Cannot make '%s' lockable -- has locked" % cls)
if hasattr(cls, 'lock'):
raise RuntimeError("Cannot make '%s' lockable -- has lock()" % cls)
if hasattr(cls, 'unlock'):
raise RuntimeError("Cannot make '%s' lockable -- has unlock()" % cls)
def locked(self):
return self._locked
def locker(self):
self._rlock.acquire()
self._locked += 1
def unlocker(self, *args): # pylint: disable=unused-argument
self._rlock.release()
self._locked -= 1
cls._rlock = threading.RLock()
cls._locked = 0
cls.locked = locked
cls.is_locked = locked
cls.lock = locker
cls.unlock = unlocker
cls.__enter__ = locker
cls.__exit__ = unlocker
return cls
# ------------------------------------------------------------------------------
#
# @Lockable
# class A(object):
#
# def call(self):
# print 'locked 1: %s' % self.locked()
#
# with self:
# print 'locked 2: %s' % self.locked()
#
# print 'locked 3: %s\n' % self.locked()
#
# print
# a = A()
# a.call()
# a.lock()
# a.call()
# a.lock()
# a.call()
# a.unlock()
# a.call()
# with a:
# a.call()
# a.call()
# a.unlock()
# a.call()
# try:
# a.unlock()
# print 'oops\n'
# except:
# print 'ok\n'
# a.lock()
# a.call()
# with a:
# a.call()
# a.call()
# a.unlock()
# a.call()
# try:
# a.unlock()
# print 'oops\n'
# except:
# print 'ok\n'
# ------------------------------------------------------------------------------