def get(self, block=True, timeout=None): self.mutex.acquire() try: if block: if timeout is None: while not len(self) and self._writable: self.not_empty.wait() else: endtime = _time() + timeout while not len(self) and self._writable: remaining = endtime - _time() if remaining <= 0.0: raise Empty self.not_empty.wait(remaining) # END handle timeout mode # END handle block # can throw if we woke up because we are not writable anymore try: return self.popleft() except IndexError: raise Empty # END handle unblocking reason finally: self.mutex.release()
def acquire(self,blocking=True,timeout=None): """Attempt to acquire this lock. If the optional argument "blocking" is True and "timeout" is None, this methods blocks until is successfully acquires the lock. If "blocking" is False, it returns immediately if the lock could not be acquired. Otherwise, it blocks for at most "timeout" seconds trying to acquire the lock. In all cases, this methods returns True if the lock was successfully acquired and False otherwise. """ if timeout is None: return self.__lock.acquire(blocking) else: # Simulated timeout using progressively longer sleeps. # This is the same timeout scheme used in the stdlib Condition # class. If there's lots of contention on the lock then there's # a good chance you won't get it; but then again, Python doesn't # guarantee fairness anyway. We hope that platform-specific # extensions can provide a better mechanism. endtime = _time() + timeout delay = 0.0005 while not self.__lock.acquire(False): remaining = endtime - _time() if remaining <= 0: return False delay = min(delay*2,remaining,0.05) _sleep(delay) return True
def acquire(self, blocking=True, timeout=None): if not blocking and timeout is not None: raise ValueError("can't specify timeout for non-blocking acquire") rc = False endtime = None self._cond.acquire() while self._value == 0: if not blocking: break if __debug__: self._note("%s.acquire(%s): blocked waiting, value=%s", self, blocking, self._value) if timeout is not None: if endtime is None: endtime = threading._time() + timeout else: timeout = endtime - threading._time() if timeout <= 0: break self._cond.wait(timeout) else: self._value = self._value - 1 if __debug__: self._note("%s.acquire: success, value=%s", self, self._value) rc = True self._cond.release() return rc
def wait(self, timeout=None): waiter = _allocate_lock() waiter.acquire() # get it the first time, no blocking self.append(waiter) try: # restore state no matter what (e.g., KeyboardInterrupt) # now we block, as we hold the lock already # in the momemnt we release our lock, someone else might actually resume self._lock.release() if timeout is None: waiter.acquire() else: # Balancing act: We can't afford a pure busy loop, because of the # GIL, so we have to sleep # We try to sleep only tiny amounts of time though to be very responsive # NOTE: this branch is not used by the async system anyway, but # will be hit when the user reads with timeout endtime = _time() + timeout delay = self.delay acquire = waiter.acquire while True: gotit = acquire(0) if gotit: break remaining = endtime - _time() if remaining <= 0: break # this makes 4 threads working as good as two, but of course # it causes more frequent micro-sleeping #delay = min(delay * 2, remaining, .05) _sleep(delay) # END endless loop if not gotit: try: self.remove(waiter) except AttributeError: # handle python 2.4 - actually this should be made thread-safe # but lets see ... try: # lets hope we pop the right one - we don't loop over it # yet-we just keep minimal compatability with py 2.4 item = self.pop() if item != waiter: self.append(item) except IndexError: pass except ValueError: pass # END didn't ever get it finally: # reacquire the lock self._lock.acquire()
def wait(self, timeout=None): if not self._is_owned(): raise RuntimeError("cannot wait on un-acquired lock") waiter = _allocate_lock() waiter.acquire() self.__waiters.append(waiter) saved_state = self._release_save() try: # restore state no matter what (e.g., KeyboardInterrupt) if timeout is None: waiter.acquire() if __debug__: self._note("%s.wait(): got it", self) else: # Balancing act: We can't afford a pure busy loop, so we # have to sleep; but if we sleep the whole timeout time, # we'll be unresponsive. The scheme here sleeps very # little at first, longer as time goes on, but never longer # than 20 times per second (or the timeout time remaining). endtime = _time() + timeout delay = 0.0005 # 500 us -> initial delay of 1 ms while True: gotit = waiter.acquire(0) if gotit: break remaining = endtime - _time() if remaining <= 0: break delay = min(delay * 2, remaining, .05) _sleep(delay) if not gotit: if __debug__: self._note("%s.wait(%s): timed out", self, timeout) try: self.__waiters.remove(waiter) except ValueError: pass else: if __debug__: self._note("%s.wait(%s): got it", self, timeout) finally: self._acquire_restore(saved_state)
def acquire(self, blocking=True, timeout=None): """Acquire a semaphore, decrementing the internal counter by one. When invoked without arguments: if the internal counter is larger than zero on entry, decrement it by one and return immediately. If it is zero on entry, block, waiting until some other thread has called release() to make it larger than zero. This is done with proper interlocking so that if multiple acquire() calls are blocked, release() will wake exactly one of them up. The implementation may pick one at random, so the order in which blocked threads are awakened should not be relied on. There is no return value in this case. When invoked with blocking set to true, do the same thing as when called without arguments, and return true. When invoked with blocking set to false, do not block. If a call without an argument would block, return false immediately; otherwise, do the same thing as when called without arguments, and return true. When invoked with a timeout other than None, it will block for at most timeout seconds. If acquire does not complete successfully in that interval, return false. Return true otherwise. """ if not blocking and timeout is not None: raise ValueError("can't specify timeout for non-blocking acquire") rc = False endtime = None with self._cond: while self._value == 0: if not blocking: break if timeout is not None: if endtime is None: endtime = threading._time() + timeout else: timeout = endtime - threading._time() if timeout <= 0: break self._cond.wait(timeout) else: self._value -= 1 rc = True return rc