blob: 6710153d2003c633cd70717145213004eadc89f4 [file] [log] [blame]
Guido van Rossum5c971671996-07-22 15:23:25 +00001# A multi-producer, multi-consumer queue.
2
Guido van Rossum0b233481997-11-26 15:44:34 +00003# define this exception to be compatible with Python 1.5's class
4# exceptions, but also when -X option is used.
5try:
6 class Empty(Exception):
Guido van Rossum548703a1998-03-26 22:14:20 +00007 pass
Guido van Rossum0b233481997-11-26 15:44:34 +00008except TypeError:
9 # string based exceptions
Guido van Rossum548703a1998-03-26 22:14:20 +000010 Empty = 'Queue.Empty' # Exception raised by get_nowait()
Guido van Rossum5c971671996-07-22 15:23:25 +000011
12class Queue:
Guido van Rossum0b233481997-11-26 15:44:34 +000013 def __init__(self, maxsize):
Guido van Rossum548703a1998-03-26 22:14:20 +000014 """Initialize a queue object with a given maximum size.
Guido van Rossum5c971671996-07-22 15:23:25 +000015
Guido van Rossum548703a1998-03-26 22:14:20 +000016 If maxsize is <= 0, the queue size is infinite.
17 """
18 import thread
19 self._init(maxsize)
20 self.mutex = thread.allocate_lock()
21 self.esema = thread.allocate_lock()
22 self.esema.acquire_lock()
23 self.fsema = thread.allocate_lock()
Guido van Rossum5c971671996-07-22 15:23:25 +000024
Guido van Rossum0b233481997-11-26 15:44:34 +000025 def qsize(self):
Guido van Rossum548703a1998-03-26 22:14:20 +000026 """Returns the approximate size of the queue (not reliable!)."""
27 self.mutex.acquire_lock()
28 n = self._qsize()
29 self.mutex.release_lock()
30 return n
Guido van Rossum0b233481997-11-26 15:44:34 +000031
32 def empty(self):
Guido van Rossum548703a1998-03-26 22:14:20 +000033 """Returns 1 if the queue is empty, 0 otherwise (not reliable!)."""
34 self.mutex.acquire_lock()
35 n = self._empty()
36 self.mutex.release_lock()
37 return n
Guido van Rossum0b233481997-11-26 15:44:34 +000038
39 def full(self):
Guido van Rossum548703a1998-03-26 22:14:20 +000040 """Returns 1 if the queue is full, 0 otherwise (not reliable!)."""
41 self.mutex.acquire_lock()
42 n = self._full()
43 self.mutex.release_lock()
44 return n
Guido van Rossum0b233481997-11-26 15:44:34 +000045
46 def put(self, item):
Guido van Rossum548703a1998-03-26 22:14:20 +000047 """Put an item into the queue."""
48 self.fsema.acquire_lock()
49 self.mutex.acquire_lock()
50 was_empty = self._empty()
51 self._put(item)
52 if was_empty:
53 self.esema.release_lock()
54 if not self._full():
55 self.fsema.release_lock()
56 self.mutex.release_lock()
Guido van Rossum0b233481997-11-26 15:44:34 +000057
58 def get(self):
Guido van Rossum548703a1998-03-26 22:14:20 +000059 """Gets and returns an item from the queue.
60 This method blocks if necessary until an item is available.
61 """
62 self.esema.acquire_lock()
63 self.mutex.acquire_lock()
64 was_full = self._full()
65 item = self._get()
66 if was_full:
67 self.fsema.release_lock()
68 if not self._empty():
69 self.esema.release_lock()
70 self.mutex.release_lock()
71 return item
Guido van Rossum0b233481997-11-26 15:44:34 +000072
73 # Get an item from the queue if one is immediately available,
74 # raise Empty if the queue is empty or temporarily unavailable
75 def get_nowait(self):
Guido van Rossum548703a1998-03-26 22:14:20 +000076 """Gets and returns an item from the queue.
77 Only gets an item if one is immediately available, Otherwise
78 this raises the Empty exception if the queue is empty or
79 temporarily unavailable.
80 """
81 locked = self.esema.acquire_lock(0)
82 self.mutex.acquire_lock()
83 if self._empty():
84 # The queue is empty -- we can't have esema
85 self.mutex.release_lock()
86 raise Empty
87 if not locked:
88 locked = self.esema.acquire_lock(0)
89 if not locked:
90 # Somebody else has esema
91 # but we have mutex --
92 # go out of their way
93 self.mutex.release_lock()
94 raise Empty
95 was_full = self._full()
96 item = self._get()
97 if was_full:
98 self.fsema.release_lock()
99 if not self._empty():
100 self.esema.release_lock()
101 self.mutex.release_lock()
102 return item
Guido van Rossum5c971671996-07-22 15:23:25 +0000103
Guido van Rossum0b233481997-11-26 15:44:34 +0000104 # XXX Need to define put_nowait() as well.
Guido van Rossum5c971671996-07-22 15:23:25 +0000105
Guido van Rossum5c971671996-07-22 15:23:25 +0000106
Guido van Rossum0b233481997-11-26 15:44:34 +0000107 # Override these methods to implement other queue organizations
108 # (e.g. stack or priority queue).
109 # These will only be called with appropriate locks held
Guido van Rossum5c971671996-07-22 15:23:25 +0000110
Guido van Rossum0b233481997-11-26 15:44:34 +0000111 # Initialize the queue representation
112 def _init(self, maxsize):
Guido van Rossum548703a1998-03-26 22:14:20 +0000113 self.maxsize = maxsize
114 self.queue = []
Guido van Rossum5c971671996-07-22 15:23:25 +0000115
Guido van Rossum0b233481997-11-26 15:44:34 +0000116 def _qsize(self):
Guido van Rossum548703a1998-03-26 22:14:20 +0000117 return len(self.queue)
Guido van Rossum5c971671996-07-22 15:23:25 +0000118
Guido van Rossum0b233481997-11-26 15:44:34 +0000119 # Check wheter the queue is empty
120 def _empty(self):
Guido van Rossum548703a1998-03-26 22:14:20 +0000121 return not self.queue
Guido van Rossum5c971671996-07-22 15:23:25 +0000122
Guido van Rossum0b233481997-11-26 15:44:34 +0000123 # Check whether the queue is full
124 def _full(self):
Guido van Rossum548703a1998-03-26 22:14:20 +0000125 return self.maxsize > 0 and len(self.queue) == self.maxsize
Guido van Rossum5c971671996-07-22 15:23:25 +0000126
Guido van Rossum0b233481997-11-26 15:44:34 +0000127 # Put a new item in the queue
128 def _put(self, item):
Guido van Rossum548703a1998-03-26 22:14:20 +0000129 self.queue.append(item)
Guido van Rossum5c971671996-07-22 15:23:25 +0000130
Guido van Rossum0b233481997-11-26 15:44:34 +0000131 # Get an item from the queue
132 def _get(self):
Guido van Rossum548703a1998-03-26 22:14:20 +0000133 item = self.queue[0]
134 del self.queue[0]
135 return item