Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 35.2k
gh-96471: Add queue shutdown#96474
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
gh-96471: Add queue shutdown #96474
Changes from all commits
4fd0640d942c9ef552ac178671f95f31f8ea2035a6978b8d1b19f5296d3b3a585827f1121de125e2df0214c53d7da10d9fFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -25,6 +25,15 @@ class Full(Exception): | ||
| pass | ||
| class ShutDown(Exception): | ||
| '''Raised when put/get with shut-down queue.''' | ||
| _queue_alive = "alive" | ||
| _queue_shutdown = "shutdown" | ||
| _queue_shutdown_immediate = "shutdown-immediate" | ||
EpicWink marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| class Queue: | ||
| '''Create a queue object with a given maximum size. | ||
| @@ -54,6 +63,9 @@ def __init__(self, maxsize=0): | ||
| self.all_tasks_done = threading.Condition(self.mutex) | ||
| self.unfinished_tasks = 0 | ||
| # Queue shut-down state | ||
| self.shutdown_state = _queue_alive | ||
| def task_done(self): | ||
| '''Indicate that a formerly enqueued task is complete. | ||
| @@ -87,6 +99,8 @@ def join(self): | ||
| ''' | ||
| with self.all_tasks_done: | ||
| while self.unfinished_tasks: | ||
| if self.shutdown_state == _queue_shutdown_immediate: | ||
| return | ||
| self.all_tasks_done.wait() | ||
| def qsize(self): | ||
| @@ -130,6 +144,8 @@ def put(self, item, block=True, timeout=None): | ||
| is immediately available, else raise the Full exception ('timeout' | ||
| is ignored in that case). | ||
| ''' | ||
| if self.shutdown_state != _queue_alive: | ||
| raise ShutDown | ||
| with self.not_full: | ||
| if self.maxsize > 0: | ||
| if not block: | ||
| @@ -138,6 +154,8 @@ def put(self, item, block=True, timeout=None): | ||
| elif timeout is None: | ||
| while self._qsize() >= self.maxsize: | ||
| self.not_full.wait() | ||
| if self.shutdown_state != _queue_alive: | ||
| raise ShutDown | ||
| elif timeout < 0: | ||
| raise ValueError("'timeout' must be a non-negative number") | ||
| else: | ||
| @@ -147,6 +165,8 @@ def put(self, item, block=True, timeout=None): | ||
| if remaining <= 0.0: | ||
| raise Full | ||
| self.not_full.wait(remaining) | ||
| if self.shutdown_state != _queue_alive: | ||
| raise ShutDown | ||
| self._put(item) | ||
| self.unfinished_tasks += 1 | ||
| self.not_empty.notify() | ||
| @@ -162,22 +182,36 @@ def get(self, block=True, timeout=None): | ||
| available, else raise the Empty exception ('timeout' is ignored | ||
| in that case). | ||
| ''' | ||
| if self.shutdown_state == _queue_shutdown_immediate: | ||
| raise ShutDown | ||
| with self.not_empty: | ||
| if not block: | ||
| if not self._qsize(): | ||
| if self.shutdown_state != _queue_alive: | ||
| raise ShutDown | ||
| raise Empty | ||
| elif timeout is None: | ||
| while not self._qsize(): | ||
| if self.shutdown_state != _queue_alive: | ||
| raise ShutDown | ||
| self.not_empty.wait() | ||
| if self.shutdown_state != _queue_alive: | ||
| raise ShutDown | ||
| elif timeout < 0: | ||
| raise ValueError("'timeout' must be a non-negative number") | ||
| else: | ||
| endtime = time() + timeout | ||
| while not self._qsize(): | ||
| if self.shutdown_state != _queue_alive: | ||
| raise ShutDown | ||
| remaining = endtime - time() | ||
| if remaining <= 0.0: | ||
| raise Empty | ||
| self.not_empty.wait(remaining) | ||
| if self.shutdown_state != _queue_alive: | ||
| raise ShutDown | ||
| if self.shutdown_state == _queue_shutdown_immediate: | ||
| raise ShutDown | ||
| item = self._get() | ||
| self.not_full.notify() | ||
| return item | ||
| @@ -198,6 +232,28 @@ def get_nowait(self): | ||
| ''' | ||
| return self.get(block=False) | ||
| def shutdown(self, immediate=False): | ||
| '''Shut-down the queue, making queue gets and puts raise. | ||
| By default, gets will only raise once the queue is empty. Set | ||
| 'immediate' to True to make gets raise immediately instead. | ||
| All blocked callers of put() will be unblocked, and also get() | ||
| and join() if 'immediate'. The ShutDown exception is raised. | ||
| ''' | ||
| with self.mutex: | ||
| if immediate: | ||
| self.shutdown_state = _queue_shutdown_immediate | ||
| self.not_empty.notify_all() | ||
| # set self.unfinished_tasks to 0 | ||
| # to break the loop in 'self.join()' | ||
| # when quits from `wait()` | ||
| self.unfinished_tasks = 0 | ||
| self.all_tasks_done.notify_all() | ||
EpicWink marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| else: | ||
| self.shutdown_state = _queue_shutdown | ||
| self.not_full.notify_all() | ||
| # Override these methods to implement other queue organizations | ||
| # (e.g. stack or priority queue). | ||
| # These will only be called with appropriate locks held | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.