X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;f=python-eventlet%2Feventlet%2Fsemaphore.py;fp=eventlet%2Feventlet%2Fsemaphore.py;h=b2ef9d34f78e7c37b31a8079f392accb40491f54;hb=358bd9258c2b6d2ee74de4dfd07a5123107abad4;hp=73dbbc15a32c48057e4d1388115916077f30127c;hpb=376ff3bfe7071cc0793184a378c4e74508fb0d97;p=packages%2Ftrusty%2Fpython-eventlet.git diff --git a/eventlet/eventlet/semaphore.py b/python-eventlet/eventlet/semaphore.py similarity index 90% rename from eventlet/eventlet/semaphore.py rename to python-eventlet/eventlet/semaphore.py index 73dbbc1..b2ef9d3 100644 --- a/eventlet/eventlet/semaphore.py +++ b/python-eventlet/eventlet/semaphore.py @@ -1,4 +1,7 @@ from __future__ import with_statement + +import collections + from eventlet import greenthread from eventlet import hubs from eventlet.timeout import Timeout @@ -35,7 +38,7 @@ class Semaphore(object): if value < 0: raise ValueError("Semaphore must be initialized with a positive " "number, got %s" % value) - self._waiters = set() + self._waiters = collections.deque() def __repr__(self): params = (self.__class__.__name__, hex(id(self)), @@ -75,13 +78,25 @@ class Semaphore(object): 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. + + Timeout value must be strictly positive. """ - if not blocking and timeout is not None: - raise ValueError("can't specify timeout for non-blocking acquire") + if timeout == -1: + timeout = None + if timeout is not None and timeout < 0: + raise ValueError("timeout value must be strictly positive") + if not blocking: + if timeout is not None: + raise ValueError("can't specify timeout for non-blocking acquire") + timeout = 0 if not blocking and self.locked(): return False - if self.counter <= 0: - self._waiters.add(greenthread.getcurrent()) + + current_thread = greenthread.getcurrent() + + if self.counter <= 0 or self._waiters: + if current_thread not in self._waiters: + self._waiters.append(current_thread) try: if timeout is not None: ok = False @@ -92,10 +107,19 @@ class Semaphore(object): if not ok: return False else: - while self.counter <= 0: + # If someone else is already in this wait loop, give them + # a chance to get out. + while True: hubs.get_hub().switch() + if self.counter > 0: + break finally: - self._waiters.discard(greenthread.getcurrent()) + try: + self._waiters.remove(current_thread) + except ValueError: + # Fine if its already been dropped. + pass + self.counter -= 1 return True @@ -117,7 +141,7 @@ class Semaphore(object): def _do_acquire(self): if self._waiters and self.counter > 0: - waiter = self._waiters.pop() + waiter = self._waiters.popleft() waiter.switch() def __exit__(self, typ, val, tb):