def __init__(self): self._owner = None self._block = _allocate_lock() self._locking = {} self._count = 0
# Cython, each individual method holds the GIL for its entire # duration, ensuring that no other thread can interrupt us in an # unsafe state (only when we _do_wait do we call back into Python and # allow switching threads). Simulate that here through the use of a manual # lock. (We use a separate lock for each semaphore to allow sys.settrace functions # to use locks *other* than the one being traced.) if PYPY: # TODO: Need to use monkey.get_original? try: from _thread import allocate_lock as _allocate_lock # pylint:disable=import-error,useless-suppression from _thread import get_ident as _get_ident # pylint:disable=import-error,useless-suppression except ImportError: # Python 2 from thread import allocate_lock as _allocate_lock # pylint:disable=import-error,useless-suppression from thread import get_ident as _get_ident # pylint:disable=import-error,useless-suppression _sem_lock = _allocate_lock() def untraceable(f): # Don't allow re-entry to these functions in a single thread, as can # happen if a sys.settrace is used def wrapper(self): me = _get_ident() try: count = self._locking[me] except KeyError: count = self._locking[me] = 1 else: count = self._locking[me] = count + 1 if count: return