Commit d8771860 authored by Vincent Pelletier's avatar Vincent Pelletier

Do not conditionaly define locking classes, so that they can be available...

Do not conditionaly define locking classes, so that they can be available independently from VERBOSE_LOCKING value for finer-grained lock tracing.


git-svn-id: https://svn.erp5.org/repos/neo/branches/prototype3@1217 71dcc9de-d417-0410-9af5-da40c76e7ee4
parent 37bc1b1b
...@@ -23,101 +23,104 @@ __all__ = ['Lock', 'RLock'] ...@@ -23,101 +23,104 @@ __all__ = ['Lock', 'RLock']
VERBOSE_LOCKING = False VERBOSE_LOCKING = False
import traceback
import sys
import os
class LockUser(object):
def __init__(self, level=0):
self.ident = currentThread().getName()
# This class is instanciated from a place desiring to known what
# called it.
# limit=1 would return execution position in this method
# limit=2 would return execution position in caller
# limit=3 returns execution position in caller's caller
# Additionnal level value (should be positive only) can be used when
# more intermediate calls are involved
self.stack = stack = traceback.extract_stack()[:-(2 + level)]
path, line_number, func_name, line = stack[-1]
# Simplify path. Only keep 3 last path elements. It is enough for
# current Neo directory structure.
path = os.path.join('...', *path.split(os.path.sep)[-3:])
self.caller = (path, line_number, func_name, line)
def __eq__(self, other):
return isinstance(other, self.__class__) and self.ident == other.ident
def __repr__(self):
return '%s@%s:%s %s' % (self.ident, self.caller[0], self.caller[1], self.caller[3])
def formatStack(self):
return ''.join(traceback.format_list(self.stack))
class VerboseLockBase(object):
def __init__(self, reentrant=False):
self.reentrant = reentrant
self.owner = None
self.waiting = []
self._note('%s@%X created by %r', self.__class__.__name__, id(self), LockUser(1))
def _note(self, fmt, *args):
sys.stderr.write(fmt % args + '\n')
sys.stderr.flush()
def _getOwner(self):
if self._locked():
owner = self.owner
else:
owner = None
return owner
def acquire(self, blocking=1):
me = LockUser()
owner = self._getOwner()
self._note('[%r]%s.acquire(%s) Waiting for lock. Owned by:%r Waiting:%r', me, self, blocking, owner, self.waiting)
if not self.reentrant and blocking and me == owner:
self._note('[%r]%s.acquire(%s): Deadlock detected: I already own this lock:%r', me, self, blocking, owner)
self._note('Owner traceback:\n%s', owner.formatStack())
self._note('My traceback:\n%s', me.formatStack())
self.waiting.append(me)
try:
return self.lock.acquire(blocking)
finally:
self.owner = me
self.waiting.remove(me)
self._note('[%r]%s.acquire(%s) Lock granted. Waiting: %r', me, self, blocking, self.waiting)
def release(self):
me = LockUser()
self._note('[%r]%s.release() Waiting: %r', me, self, self.waiting)
return self.lock.release()
def _locked(self):
raise NotImplementedError
def __repr__(self):
return '<%s@%X>' % (self.__class__.__name__, id(self))
class VerboseRLock(VerboseLockBase):
def __init__(self, verbose=None):
VerboseLock.__init__(self, reentrant=True)
self.lock = threading_RLock()
def _locked(self):
return self.lock.__block.locked()
def _is_owned(self):
return self.lock._is_owned()
class VerboseLock(VerboseLockBase):
def __init__(self, verbose=None):
VerboseLock.__init__(self)
self.lock = threading_Lock()
def locked(self):
return self.lock.locked()
_locked = locked
if VERBOSE_LOCKING: if VERBOSE_LOCKING:
import traceback Lock = VerboseLock
import sys RLock = VerboseRLock
import os
class LockUser(object):
def __init__(self, level=0):
self.ident = currentThread().getName()
# This class is instanciated from a place desiring to known what
# called it.
# limit=1 would return execution position in this method
# limit=2 would return execution position in caller
# limit=3 returns execution position in caller's caller
# Additionnal level value (should be positive only) can be used when
# more intermediate calls are involved
self.stack = stack = traceback.extract_stack()[:-(2 + level)]
path, line_number, func_name, line = stack[-1]
# Simplify path. Only keep 3 last path elements. It is enough for
# current Neo directory structure.
path = os.path.join('...', *path.split(os.path.sep)[-3:])
self.caller = (path, line_number, func_name, line)
def __eq__(self, other):
return isinstance(other, self.__class__) and self.ident == other.ident
def __repr__(self):
return '%s@%s:%s %s' % (self.ident, self.caller[0], self.caller[1], self.caller[3])
def formatStack(self):
return ''.join(traceback.format_list(self.stack))
class VerboseLock(object):
def __init__(self, reentrant=False):
self.reentrant = reentrant
self.owner = None
self.waiting = []
self._note('%s@%X created by %r', self.__class__.__name__, id(self), LockUser(1))
def _note(self, fmt, *args):
sys.stderr.write(fmt % args + '\n')
sys.stderr.flush()
def _getOwner(self):
if self._locked():
owner = self.owner
else:
owner = None
return owner
def acquire(self, blocking=1):
me = LockUser()
owner = self._getOwner()
self._note('[%r]%s.acquire(%s) Waiting for lock. Owned by:%r Waiting:%r', me, self, blocking, owner, self.waiting)
if not self.reentrant and blocking and me == owner:
self._note('[%r]%s.acquire(%s): Deadlock detected: I already own this lock:%r', me, self, blocking, owner)
self._note('Owner traceback:\n%s', owner.formatStack())
self._note('My traceback:\n%s', me.formatStack())
self.waiting.append(me)
try:
return self.lock.acquire(blocking)
finally:
self.owner = me
self.waiting.remove(me)
self._note('[%r]%s.acquire(%s) Lock granted. Waiting: %r', me, self, blocking, self.waiting)
def release(self):
me = LockUser()
self._note('[%r]%s.release() Waiting: %r', me, self, self.waiting)
return self.lock.release()
def _locked(self):
raise NotImplementedError
def __repr__(self):
return '<%s@%X>' % (self.__class__.__name__, id(self))
class RLock(VerboseLock):
def __init__(self, verbose=None):
VerboseLock.__init__(self, reentrant=True)
self.lock = threading_RLock()
def _locked(self):
return self.lock.__block.locked()
def _is_owned(self):
return self.lock._is_owned()
class Lock(VerboseLock):
def __init__(self, verbose=None):
VerboseLock.__init__(self)
self.lock = threading_Lock()
def locked(self):
return self.lock.locked()
_locked = locked
else: else:
Lock = threading_Lock Lock = threading_Lock
RLock = threading_RLock RLock = threading_RLock
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment