1
1
"""Queues"""
2
2
3
- __all__ = ['Queue' , 'PriorityQueue' , 'LifoQueue' , 'JoinableQueue ' ,
4
- 'QueueFull' , 'QueueEmpty ' ]
3
+ __all__ = ['Queue' , 'PriorityQueue' , 'LifoQueue' , 'QueueFull' , 'QueueEmpty ' ,
4
+ 'JoinableQueue ' ]
5
5
6
6
import collections
7
7
import heapq
@@ -49,6 +49,9 @@ def __init__(self, maxsize=0, *, loop=None):
49
49
self ._getters = collections .deque ()
50
50
# Pairs of (item, Future).
51
51
self ._putters = collections .deque ()
52
+ self ._unfinished_tasks = 0
53
+ self ._finished = locks .Event (loop = self ._loop )
54
+ self ._finished .set ()
52
55
self ._init (maxsize )
53
56
54
57
def _init (self , maxsize ):
@@ -59,6 +62,8 @@ def _get(self):
59
62
60
63
def _put (self , item ):
61
64
self ._queue .append (item )
65
+ self ._unfinished_tasks += 1
66
+ self ._finished .clear ()
62
67
63
68
def __repr__ (self ):
64
69
return '<{} at {:#x} {}>' .format (
@@ -75,6 +80,8 @@ def _format(self):
75
80
result += ' _getters[{}]' .format (len (self ._getters ))
76
81
if self ._putters :
77
82
result += ' _putters[{}]' .format (len (self ._putters ))
83
+ if self ._unfinished_tasks :
84
+ result += ' tasks={}' .format (self ._unfinished_tasks )
78
85
return result
79
86
80
87
def _consume_done_getters (self ):
@@ -126,9 +133,6 @@ def put(self, item):
126
133
'queue non-empty, why are getters waiting?' )
127
134
128
135
getter = self ._getters .popleft ()
129
-
130
- # Use _put and _get instead of passing item straight to getter, in
131
- # case a subclass has logic that must run (e.g. JoinableQueue).
132
136
self ._put (item )
133
137
134
138
# getter cannot be cancelled, we just removed done getters
@@ -154,9 +158,6 @@ def put_nowait(self, item):
154
158
'queue non-empty, why are getters waiting?' )
155
159
156
160
getter = self ._getters .popleft ()
157
-
158
- # Use _put and _get instead of passing item straight to getter, in
159
- # case a subclass has logic that must run (e.g. JoinableQueue).
160
161
self ._put (item )
161
162
162
163
# getter cannot be cancelled, we just removed done getters
@@ -219,6 +220,38 @@ def get_nowait(self):
219
220
else :
220
221
raise QueueEmpty
221
222
223
+ def task_done (self ):
224
+ """Indicate that a formerly enqueued task is complete.
225
+
226
+ Used by queue consumers. For each get() used to fetch a task,
227
+ a subsequent call to task_done() tells the queue that the processing
228
+ on the task is complete.
229
+
230
+ If a join() is currently blocking, it will resume when all items have
231
+ been processed (meaning that a task_done() call was received for every
232
+ item that had been put() into the queue).
233
+
234
+ Raises ValueError if called more times than there were items placed in
235
+ the queue.
236
+ """
237
+ if self ._unfinished_tasks <= 0 :
238
+ raise ValueError ('task_done() called too many times' )
239
+ self ._unfinished_tasks -= 1
240
+ if self ._unfinished_tasks == 0 :
241
+ self ._finished .set ()
242
+
243
+ @coroutine
244
+ def join (self ):
245
+ """Block until all items in the queue have been gotten and processed.
246
+
247
+ The count of unfinished tasks goes up whenever an item is added to the
248
+ queue. The count goes down whenever a consumer calls task_done() to
249
+ indicate that the item was retrieved and all work on it is complete.
250
+ When the count of unfinished tasks drops to zero, join() unblocks.
251
+ """
252
+ if self ._unfinished_tasks > 0 :
253
+ yield from self ._finished .wait ()
254
+
222
255
223
256
class PriorityQueue (Queue ):
224
257
"""A subclass of Queue; retrieves entries in priority order (lowest first).
@@ -249,54 +282,5 @@ def _get(self):
249
282
return self ._queue .pop ()
250
283
251
284
252
- class JoinableQueue (Queue ):
253
- """A subclass of Queue with task_done() and join() methods."""
254
-
255
- def __init__ (self , maxsize = 0 , * , loop = None ):
256
- super ().__init__ (maxsize = maxsize , loop = loop )
257
- self ._unfinished_tasks = 0
258
- self ._finished = locks .Event (loop = self ._loop )
259
- self ._finished .set ()
260
-
261
- def _format (self ):
262
- result = Queue ._format (self )
263
- if self ._unfinished_tasks :
264
- result += ' tasks={}' .format (self ._unfinished_tasks )
265
- return result
266
-
267
- def _put (self , item ):
268
- super ()._put (item )
269
- self ._unfinished_tasks += 1
270
- self ._finished .clear ()
271
-
272
- def task_done (self ):
273
- """Indicate that a formerly enqueued task is complete.
274
-
275
- Used by queue consumers. For each get() used to fetch a task,
276
- a subsequent call to task_done() tells the queue that the processing
277
- on the task is complete.
278
-
279
- If a join() is currently blocking, it will resume when all items have
280
- been processed (meaning that a task_done() call was received for every
281
- item that had been put() into the queue).
282
-
283
- Raises ValueError if called more times than there were items placed in
284
- the queue.
285
- """
286
- if self ._unfinished_tasks <= 0 :
287
- raise ValueError ('task_done() called too many times' )
288
- self ._unfinished_tasks -= 1
289
- if self ._unfinished_tasks == 0 :
290
- self ._finished .set ()
291
-
292
- @coroutine
293
- def join (self ):
294
- """Block until all items in the queue have been gotten and processed.
295
-
296
- The count of unfinished tasks goes up whenever an item is added to the
297
- queue. The count goes down whenever a consumer thread calls task_done()
298
- to indicate that the item was retrieved and all work on it is complete.
299
- When the count of unfinished tasks drops to zero, join() unblocks.
300
- """
301
- if self ._unfinished_tasks > 0 :
302
- yield from self ._finished .wait ()
285
+ JoinableQueue = Queue
286
+ """Deprecated alias for Queue."""
0 commit comments