def acquire(self, blocking=1): tid = get_ident() gid = id(getcurrent()) tid_gid = (tid, gid) if tid_gid == self._owner: # We trust the GIL here so we can do this comparison w/o locking. self._count = self._count + 1 return True greenlet_lock = self._get_greenlet_lock() self._wait_queue.append(gid) # this is a safety in case an exception is raised somewhere and we must make sure we're not in the queue # otherwise it'll get stuck forever. remove_from_queue_on_return = True try: while True: if not greenlet_lock.acquire(blocking): return False # non-blocking and failed to acquire lock if self._wait_queue[0] == gid: # Hurray, we can have the lock. self._owner = tid_gid self._count = 1 remove_from_queue_on_return = False # don't remove us from the queue return True else: # we already hold the greenlet lock so obviously the owner is not in our thread. greenlet_lock.release() if blocking: sleep(0.0005) # 500 us -> initial delay of 1 ms else: return False finally: if remove_from_queue_on_return: self._wait_queue.remove(gid)
def release(self): tid_gid = (get_ident(), id(getcurrent())) if tid_gid != self._owner: raise RuntimeError("cannot release un-acquired lock") self._count = self._count - 1 if not self._count: self._owner = None gid = self._wait_queue.pop(0) assert gid == tid_gid[1] self._thread_local.greenlet_lock.release()
def _is_owned(self): return self._owner == (get_ident(), id(getcurrent()))