def acquire(self, timeout=-1, _caller=None): ''' Acquire the lock and note the caller who takes it. ''' if _caller is None: _caller = caller() lock = self._lock hold = _LockContext(_caller, current_thread()) if timeout != -1: warning( "%s:%d: lock %s: timeout=%s", hold.caller.filename, hold.caller.lineno, lock, timeout ) contended = False if True: if lock.acquire(0): lock.release() else: contended = True held = self._held warning( "%s:%d: lock %s: waiting for contended lock, held by %s:%s:%d", hold.caller.filename, hold.caller.lineno, lock, held.thread, held.caller.filename, held.caller.lineno ) acquired = lock.acquire(timeout=timeout) if contended: warning( "%s:%d: lock %s: %s", hold.caller.filename, hold.caller.lineno, lock, "acquired" if acquired else "timed out" ) self._held = hold if acquired and self.trace_acquire: X("ACQUIRED %r", self) stack_dump() return acquired
def close(self, enforce_final_close=False, caller_frame=None, unopened_ok=False): ''' Decrement the open count. If the count goes to zero, call `self.shutdown()` and return its value. Parameters: * `enforce_final_close`: if true, the caller expects this to be the final close for the object and a `RuntimeError` is raised if this is not actually the case. * `caller_frame`: used for debugging; the caller may specify this if necessary, otherwise it is computed from `cs.py.stack.caller` when needed. Presently the caller of the final close is recorded to help debugging extra close calls. * `unopened_ok`: if true, it is not an error if this is not open. This is intended for closing callbacks which might get called even if the original open never happened. (I'm looking at you, `cs.resources.RunState`.) ''' state = self.__mo_getstate() if not state.opened: if unopened_ok: return None raise RuntimeError("%s: close before initial open" % (self, )) retval = None with state._lock: opens = state._opens if opens < 1: error("%s: UNDERFLOW CLOSE", self) error(" final close was from %s", state._final_close_from) for frame_key in sorted(state._opened_from.keys()): error(" opened from %s %d times", frame_key, state._opened_from[frame_key]) ##from cs.debug import thread_dump ##from threading import current_thread ##thread_dump([current_thread()]) ##raise RuntimeError("UNDERFLOW CLOSE of %s" % (self,)) return retval opens -= 1 state._opens = opens if opens == 0: ##INACTIVE##state.tcm_dump(MultiOpenMixin) if caller_frame is None: caller_frame = caller() state._final_close_from = caller_frame teardown, state._teardown = state._teardown, None retval = teardown() if not state._finalise_later: self.finalise() if enforce_final_close and opens != 0: raise RuntimeError( "%s: expected this to be the final close, but it was not" % (self, )) return retval
def acquire(self, blocking=True, timeout=-1, name=None): if timeout < 0: timeout = self._deadlock_timeout else: timeout = min(timeout, self._deadlock_timeout) ok = (self._lock.acquire(timeout=timeout) if blocking else self._lock.acquire(blocking=blocking)) if not ok: raise RuntimeError("TIMEOUT acquiring lock held by %s:%r" % (self.owner, self.owner_name)) self.owner = caller() self.owner_name = name return True
def open(self, caller_frame=None): ''' Increment the open count. On the first `.open` call `self.startup()`. ''' state = self.__mo_getstate() if False: if caller_frame is None: caller_frame = caller() frame_key = caller_frame.filename, caller_frame.lineno state._opened_from[frame_key] = state._opened_from.get( frame_key, 0) + 1 state.opened = True with state._lock: opens = state._opens opens += 1 state._opens = opens if opens == 1: state._finalise = Condition(state._lock) state._teardown = setup_cmgr(self.startup_shutdown()) return self
def __enter__(self): self.acquire() self.owner = caller() return True
def subfunc(*a, **kw): frame = caller() D("CALL %s()<%s:%d> FROM %s()<%s:%d>", func.__name__, func.__code__.co_filename, func.__code__.co_firstlineno, frame.funcname, frame.filename, frame.lineno) return func(*a, **kw)
def test01caller(self): F = caller()
def __enter_exit__(self): self.open(caller_frame=caller()) try: yield finally: self.close(caller_frame=caller())
def __enter__(self): ##X("%s.ENTER...", type(self).__name__) self.acquire(_caller=caller()) ##X("%s.ENTER: acquired, returning self", type(self).__name__) return self