An improvement to Queue
Michael Abbott
michael at rcp.co.uk
Thu Jan 31 09:29:24 EST 2002
I would like to suggest a simple and fully backwards compatible improvement
to the standard Queue class. How do I go about arranging that this
actually happens?
The proposal is very simple:
1. The Queue.get() method be modified to return a flag indicating whether
the queue has just changed state from empty to non-empty. This allows the
generating process to know whether a "wake-up" signal needs to be passed to
the client thread, and is useful for non-blocking use of the queue.
2. A new Queue.get_all() method be added which returns the entire content
of the queue in one gulp. Of course this can be implemented by looping on
Queue.get(), but get_all can be *much* more efficient.
An assistant _get_all method is provided to be compatible with the
existing _get, _put, _init etc methods.
Below is my current implementation as a sub-class of Queue; I'm suggesting
that this be rolled into the existing Queue in the obvious manner.
import Queue
class XQueue(Queue.Queue):
def put(self, item, block=1):
"""Put an item into the queue.
If optional arg 'block' is 1 (the default), block if
necessary until a free slot is available. Otherwise (block
is 0), put an item on the queue if a free slot is immediately
available, else raise the Full exception.
Returns true iff the queue was empty when this item was added.
"""
if block:
self.fsema.acquire()
elif not self.fsema.acquire(0):
raise Full
self.mutex.acquire()
was_empty = self._empty()
self._put(item)
if was_empty:
self.esema.release()
if not self._full():
self.fsema.release()
self.mutex.release()
return was_empty # Only change to existing implementation
# This code is modified from the existing get() implementation.
def get_all(self, block=1):
"""Remove and returns the entire content of the queue as a list.
If optional arg 'block' is 1 (the default), block if necessary
until at least one item is available. Otherwise the entire content
of the queue is unconditionally returned.
"""
self.esema.acquire(block) # After this the queue WILL be empty!
self.mutex.acquire()
was_full = self._full()
items = self._get_all() # Hook for implementation override
if was_full:
self.fsema.release()
self.mutex.release()
return items
# This is a new implementation hook. Note that this only needs to be
# overridden if get_all() is actually used.
def _get_all(self):
item = self.queue
self.queue = []
return item
More information about the Python-list
mailing list