An improvement to Queue

Michael Abbott michael at rcp.co.uk
Thu Jan 31 15:29:24 CET 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