@@ -25,6 +25,15 @@ class Full(Exception):
25
25
pass
26
26
27
27
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
+
28
37
class Queue :
29
38
'''Create a queue object with a given maximum size.
30
39
@@ -54,6 +63,9 @@ def __init__(self, maxsize=0):
54
63
self .all_tasks_done = threading .Condition (self .mutex )
55
64
self .unfinished_tasks = 0
56
65
66
+ # Queue shut-down state
67
+ self .shutdown_state = _queue_alive
68
+
57
69
def task_done (self ):
58
70
'''Indicate that a formerly enqueued task is complete.
59
71
@@ -87,6 +99,8 @@ def join(self):
87
99
'''
88
100
with self .all_tasks_done :
89
101
while self .unfinished_tasks :
102
+ if self .shutdown_state == _queue_shutdown_immediate :
103
+ return
90
104
self .all_tasks_done .wait ()
91
105
92
106
def qsize (self ):
@@ -130,6 +144,8 @@ def put(self, item, block=True, timeout=None):
130
144
is immediately available, else raise the Full exception ('timeout'
131
145
is ignored in that case).
132
146
'''
147
+ if self .shutdown_state != _queue_alive :
148
+ raise ShutDown
133
149
with self .not_full :
134
150
if self .maxsize > 0 :
135
151
if not block :
@@ -138,6 +154,8 @@ def put(self, item, block=True, timeout=None):
138
154
elif timeout is None :
139
155
while self ._qsize () >= self .maxsize :
140
156
self .not_full .wait ()
157
+ if self .shutdown_state != _queue_alive :
158
+ raise ShutDown
141
159
elif timeout < 0 :
142
160
raise ValueError ("'timeout' must be a non-negative number" )
143
161
else :
@@ -147,6 +165,8 @@ def put(self, item, block=True, timeout=None):
147
165
if remaining <= 0.0 :
148
166
raise Full
149
167
self .not_full .wait (remaining )
168
+ if self .shutdown_state != _queue_alive :
169
+ raise ShutDown
150
170
self ._put (item )
151
171
self .unfinished_tasks += 1
152
172
self .not_empty .notify ()
@@ -162,22 +182,36 @@ def get(self, block=True, timeout=None):
162
182
available, else raise the Empty exception ('timeout' is ignored
163
183
in that case).
164
184
'''
185
+ if self .shutdown_state == _queue_shutdown_immediate :
186
+ raise ShutDown
165
187
with self .not_empty :
166
188
if not block :
167
189
if not self ._qsize ():
190
+ if self .shutdown_state != _queue_alive :
191
+ raise ShutDown
168
192
raise Empty
169
193
elif timeout is None :
170
194
while not self ._qsize ():
195
+ if self .shutdown_state != _queue_alive :
196
+ raise ShutDown
171
197
self .not_empty .wait ()
198
+ if self .shutdown_state != _queue_alive :
199
+ raise ShutDown
172
200
elif timeout < 0 :
173
201
raise ValueError ("'timeout' must be a non-negative number" )
174
202
else :
175
203
endtime = time () + timeout
176
204
while not self ._qsize ():
205
+ if self .shutdown_state != _queue_alive :
206
+ raise ShutDown
177
207
remaining = endtime - time ()
178
208
if remaining <= 0.0 :
179
209
raise Empty
180
210
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
181
215
item = self ._get ()
182
216
self .not_full .notify ()
183
217
return item
@@ -198,6 +232,24 @@ def get_nowait(self):
198
232
'''
199
233
return self .get (block = False )
200
234
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
+
201
253
# Override these methods to implement other queue organizations
202
254
# (e.g. stack or priority queue).
203
255
# These will only be called with appropriate locks held
0 commit comments