@@ -25,6 +25,15 @@ class Full(Exception):
2525 pass
2626
2727
28+ class ShutDown (Exception ):
29+ '''Raised when put/get with shut-down queue.'''
30+
31+
32+ _queue_alive = "alive"
33+ _queue_shutdown = "shutdown"
34+ _queue_shutdown_immediate = "shutdown-immediate"
35+
36+
2837class Queue :
2938 '''Create a queue object with a given maximum size.
3039
@@ -54,6 +63,9 @@ def __init__(self, maxsize=0):
5463 self .all_tasks_done = threading .Condition (self .mutex )
5564 self .unfinished_tasks = 0
5665
66+ # Queue shut-down state
67+ self .shutdown_state = _queue_alive
68+
5769 def task_done (self ):
5870 '''Indicate that a formerly enqueued task is complete.
5971
@@ -87,6 +99,8 @@ def join(self):
8799 '''
88100 with self .all_tasks_done :
89101 while self .unfinished_tasks :
102+ if self .shutdown_state == _queue_shutdown_immediate :
103+ return
90104 self .all_tasks_done .wait ()
91105
92106 def qsize (self ):
@@ -130,6 +144,8 @@ def put(self, item, block=True, timeout=None):
130144 is immediately available, else raise the Full exception ('timeout'
131145 is ignored in that case).
132146 '''
147+ if self .shutdown_state != _queue_alive :
148+ raise ShutDown
133149 with self .not_full :
134150 if self .maxsize > 0 :
135151 if not block :
@@ -138,6 +154,8 @@ def put(self, item, block=True, timeout=None):
138154 elif timeout is None :
139155 while self ._qsize () >= self .maxsize :
140156 self .not_full .wait ()
157+ if self .shutdown_state != _queue_alive :
158+ raise ShutDown
141159 elif timeout < 0 :
142160 raise ValueError ("'timeout' must be a non-negative number" )
143161 else :
@@ -147,6 +165,8 @@ def put(self, item, block=True, timeout=None):
147165 if remaining <= 0.0 :
148166 raise Full
149167 self .not_full .wait (remaining )
168+ if self .shutdown_state != _queue_alive :
169+ raise ShutDown
150170 self ._put (item )
151171 self .unfinished_tasks += 1
152172 self .not_empty .notify ()
@@ -162,22 +182,36 @@ def get(self, block=True, timeout=None):
162182 available, else raise the Empty exception ('timeout' is ignored
163183 in that case).
164184 '''
185+ if self .shutdown_state == _queue_shutdown_immediate :
186+ raise ShutDown
165187 with self .not_empty :
166188 if not block :
167189 if not self ._qsize ():
190+ if self .shutdown_state != _queue_alive :
191+ raise ShutDown
168192 raise Empty
169193 elif timeout is None :
170194 while not self ._qsize ():
195+ if self .shutdown_state != _queue_alive :
196+ raise ShutDown
171197 self .not_empty .wait ()
198+ if self .shutdown_state != _queue_alive :
199+ raise ShutDown
172200 elif timeout < 0 :
173201 raise ValueError ("'timeout' must be a non-negative number" )
174202 else :
175203 endtime = time () + timeout
176204 while not self ._qsize ():
205+ if self .shutdown_state != _queue_alive :
206+ raise ShutDown
177207 remaining = endtime - time ()
178208 if remaining <= 0.0 :
179209 raise Empty
180210 self .not_empty .wait (remaining )
211+ if self .shutdown_state != _queue_alive :
212+ raise ShutDown
213+ if self .shutdown_state == _queue_shutdown_immediate :
214+ raise ShutDown
181215 item = self ._get ()
182216 self .not_full .notify ()
183217 return item
@@ -198,6 +232,24 @@ def get_nowait(self):
198232 '''
199233 return self .get (block = False )
200234
235+ def shutdown (self , immediate = False ):
236+ '''Shut-down the queue, making queue gets and puts raise.
237+
238+ By default, gets will only raise once the queue is empty. Set
239+ 'immediate' to True to make gets raise immediately instead.
240+
241+ All blocked callers of put() will be unblocked, and also get()
242+ and join() if 'immediate'. The ShutDown exception is raised.
243+ '''
244+ with self .mutex :
245+ if immediate :
246+ self .shutdown_state = _queue_shutdown_immediate
247+ self .not_empty .notify_all ()
248+ self .all_tasks_done .notify_all ()
249+ else :
250+ self .shutdown_state = _queue_shutdown
251+ self .not_full .notify_all ()
252+
201253 # Override these methods to implement other queue organizations
202254 # (e.g. stack or priority queue).
203255 # These will only be called with appropriate locks held
0 commit comments