blob: 5e698eaf11eae07225dde07b28c83ce6ed6f929f [file] [log] [blame]
Guido van Rossum9022fce1992-08-25 12:30:44 +00001# A multi-producer, multi-consumer queue.
2
Barry Warsaw3d96d521997-11-20 19:56:38 +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 Rossum45e2fbc1998-03-26 21:13:24 +00007 pass
Barry Warsaw3d96d521997-11-20 19:56:38 +00008except TypeError:
9 # string based exceptions
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000010 Empty = 'Queue.Empty' # Exception raised by get_nowait()
Guido van Rossum9022fce1992-08-25 12:30:44 +000011
12class Queue:
Barry Warsaw3d96d521997-11-20 19:56:38 +000013 def __init__(self, maxsize):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000014 """Initialize a queue object with a given maximum size.
Guido van Rossum9022fce1992-08-25 12:30:44 +000015
Guido van Rossum45e2fbc1998-03-26 21:13:24 +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()
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000022 self.esema.acquire()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000023 self.fsema = thread.allocate_lock()
Guido van Rossum9022fce1992-08-25 12:30:44 +000024
Barry Warsaw3d96d521997-11-20 19:56:38 +000025 def qsize(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000026 """Returns the approximate size of the queue (not reliable!)."""
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000027 self.mutex.acquire()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000028 n = self._qsize()
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000029 self.mutex.release()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000030 return n
Barry Warsaw3d96d521997-11-20 19:56:38 +000031
32 def empty(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000033 """Returns 1 if the queue is empty, 0 otherwise (not reliable!)."""
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000034 self.mutex.acquire()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000035 n = self._empty()
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000036 self.mutex.release()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000037 return n
Barry Warsaw3d96d521997-11-20 19:56:38 +000038
39 def full(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000040 """Returns 1 if the queue is full, 0 otherwise (not reliable!)."""
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000041 self.mutex.acquire()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000042 n = self._full()
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000043 self.mutex.release()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000044 return n
Barry Warsaw3d96d521997-11-20 19:56:38 +000045
46 def put(self, item):
Guido van Rossumc09e6b11998-04-09 14:25:32 +000047 """Put an item into the queue.
48
49 If the queue is full, block until a free slot is avaiable.
50 """
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000051 self.fsema.acquire()
52 self.mutex.acquire()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000053 was_empty = self._empty()
54 self._put(item)
55 if was_empty:
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000056 self.esema.release()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000057 if not self._full():
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000058 self.fsema.release()
59 self.mutex.release()
Barry Warsaw3d96d521997-11-20 19:56:38 +000060
61 def get(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000062 """Gets and returns an item from the queue.
Guido van Rossumc09e6b11998-04-09 14:25:32 +000063
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000064 This method blocks if necessary until an item is available.
65 """
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000066 self.esema.acquire()
67 self.mutex.acquire()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000068 was_full = self._full()
69 item = self._get()
70 if was_full:
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000071 self.fsema.release()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000072 if not self._empty():
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000073 self.esema.release()
74 self.mutex.release()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000075 return item
Barry Warsaw3d96d521997-11-20 19:56:38 +000076
77 # Get an item from the queue if one is immediately available,
78 # raise Empty if the queue is empty or temporarily unavailable
79 def get_nowait(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000080 """Gets and returns an item from the queue.
Guido van Rossumc09e6b11998-04-09 14:25:32 +000081
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000082 Only gets an item if one is immediately available, Otherwise
83 this raises the Empty exception if the queue is empty or
84 temporarily unavailable.
85 """
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000086 locked = self.esema.acquire(0)
87 self.mutex.acquire()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000088 if self._empty():
89 # The queue is empty -- we can't have esema
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000090 self.mutex.release()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000091 raise Empty
92 if not locked:
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000093 locked = self.esema.acquire(0)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000094 if not locked:
95 # Somebody else has esema
96 # but we have mutex --
97 # go out of their way
Guido van Rossum7e6d18c1998-04-29 14:29:32 +000098 self.mutex.release()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000099 raise Empty
100 was_full = self._full()
101 item = self._get()
102 if was_full:
Guido van Rossum7e6d18c1998-04-29 14:29:32 +0000103 self.fsema.release()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000104 if not self._empty():
Guido van Rossum7e6d18c1998-04-29 14:29:32 +0000105 self.esema.release()
106 self.mutex.release()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000107 return item
Guido van Rossum9022fce1992-08-25 12:30:44 +0000108
Barry Warsaw3d96d521997-11-20 19:56:38 +0000109 # XXX Need to define put_nowait() as well.
Guido van Rossum9022fce1992-08-25 12:30:44 +0000110
Guido van Rossum9022fce1992-08-25 12:30:44 +0000111
Barry Warsaw3d96d521997-11-20 19:56:38 +0000112 # Override these methods to implement other queue organizations
113 # (e.g. stack or priority queue).
114 # These will only be called with appropriate locks held
Guido van Rossum9022fce1992-08-25 12:30:44 +0000115
Barry Warsaw3d96d521997-11-20 19:56:38 +0000116 # Initialize the queue representation
117 def _init(self, maxsize):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000118 self.maxsize = maxsize
119 self.queue = []
Guido van Rossum9022fce1992-08-25 12:30:44 +0000120
Barry Warsaw3d96d521997-11-20 19:56:38 +0000121 def _qsize(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000122 return len(self.queue)
Guido van Rossum9022fce1992-08-25 12:30:44 +0000123
Barry Warsaw3d96d521997-11-20 19:56:38 +0000124 # Check wheter the queue is empty
125 def _empty(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000126 return not self.queue
Guido van Rossum9022fce1992-08-25 12:30:44 +0000127
Barry Warsaw3d96d521997-11-20 19:56:38 +0000128 # Check whether the queue is full
129 def _full(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000130 return self.maxsize > 0 and len(self.queue) == self.maxsize
Guido van Rossum9022fce1992-08-25 12:30:44 +0000131
Barry Warsaw3d96d521997-11-20 19:56:38 +0000132 # Put a new item in the queue
133 def _put(self, item):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000134 self.queue.append(item)
Guido van Rossum9022fce1992-08-25 12:30:44 +0000135
Barry Warsaw3d96d521997-11-20 19:56:38 +0000136 # Get an item from the queue
137 def _get(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000138 item = self.queue[0]
139 del self.queue[0]
140 return item