Add queues will alternative fetch orders (priority based and stack based).

This commit is contained in:
Raymond Hettinger 2008-01-16 23:40:45 +00:00
parent 171f3916c5
commit 9e1bc982ff
2 changed files with 57 additions and 14 deletions

View File

@ -2,8 +2,9 @@
from time import time as _time from time import time as _time
from collections import deque from collections import deque
import heapq
__all__ = ['Empty', 'Full', 'Queue'] __all__ = ['Empty', 'Full', 'Queue', 'PriorityQueue', 'LifoQueue']
class Empty(Exception): class Empty(Exception):
"Exception raised by Queue.get(block=0)/get_nowait()." "Exception raised by Queue.get(block=0)/get_nowait()."
@ -196,7 +197,7 @@ class Queue:
def _init(self, maxsize): def _init(self, maxsize):
self.queue = deque() self.queue = deque()
def _qsize(self): def _qsize(self, len=len):
return len(self.queue) return len(self.queue)
# Put a new item in the queue # Put a new item in the queue
@ -206,3 +207,38 @@ class Queue:
# Get an item from the queue # Get an item from the queue
def _get(self): def _get(self):
return self.queue.popleft() return self.queue.popleft()
class PriorityQueue(Queue):
'''Variant of Queue that retrieves open entries in priority order (lowest first).
Entries are typically tuples of the form: (priority number, data).
'''
def _init(self, maxsize):
self.queue = []
def _qsize(self, len=len):
return len(self.queue)
def _put(self, item, heappush=heapq.heappush):
heappush(self.queue, item)
def _get(self, heappop=heapq.heappop):
return heappop(self.queue)
class LifoQueue(Queue):
'''Variant of Queue that retrieves most recently added entries first.'''
def _init(self, maxsize):
self.queue = []
def _qsize(self, len=len):
return len(self.queue)
def _put(self, item):
self.queue.append(item)
def _get(self):
return self.queue.pop()

View File

@ -181,8 +181,13 @@ def SimpleQueueTest(q):
raise RuntimeError, "Call this function with an empty queue" raise RuntimeError, "Call this function with an empty queue"
# I guess we better check things actually queue correctly a little :) # I guess we better check things actually queue correctly a little :)
q.put(111) q.put(111)
q.put(333)
q.put(222) q.put(222)
verify(q.get() == 111 and q.get() == 222, target_order = dict(Queue = [111, 333, 222],
LifoQueue = [222, 333, 111],
PriorityQueue = [111, 222, 333])
actual_order = [q.get(), q.get(), q.get()]
verify(actual_order == target_order[q.__class__.__name__],
"Didn't seem to queue the correct data!") "Didn't seem to queue the correct data!")
for i in range(QUEUE_SIZE-1): for i in range(QUEUE_SIZE-1):
q.put(i) q.put(i)
@ -260,18 +265,20 @@ def QueueTaskDoneTest(q):
raise TestFailed("Did not detect task count going negative") raise TestFailed("Did not detect task count going negative")
def test(): def test():
q = Queue.Queue() for Q in Queue.Queue, Queue.LifoQueue, Queue.PriorityQueue:
QueueTaskDoneTest(q) q = Q()
QueueJoinTest(q) QueueTaskDoneTest(q)
QueueJoinTest(q) QueueJoinTest(q)
QueueTaskDoneTest(q) QueueJoinTest(q)
QueueTaskDoneTest(q)
q = Q(QUEUE_SIZE)
# Do it a couple of times on the same queue
SimpleQueueTest(q)
SimpleQueueTest(q)
if verbose:
print "Simple Queue tests seemed to work for", Q.__name__
q = Queue.Queue(QUEUE_SIZE)
# Do it a couple of times on the same queue
SimpleQueueTest(q)
SimpleQueueTest(q)
if verbose:
print "Simple Queue tests seemed to work"
q = FailingQueue(QUEUE_SIZE) q = FailingQueue(QUEUE_SIZE)
FailingQueueTest(q) FailingQueueTest(q)
FailingQueueTest(q) FailingQueueTest(q)