blob: 843b9dca197ef6abe915ec5ec9e0430f738ed685 [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()
22 self.esema.acquire_lock()
23 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!)."""
27 self.mutex.acquire_lock()
28 n = self._qsize()
29 self.mutex.release_lock()
30 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!)."""
34 self.mutex.acquire_lock()
35 n = self._empty()
36 self.mutex.release_lock()
37 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!)."""
41 self.mutex.acquire_lock()
42 n = self._full()
43 self.mutex.release_lock()
44 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 Rossum45e2fbc1998-03-26 21:13:24 +000051 self.fsema.acquire_lock()
52 self.mutex.acquire_lock()
53 was_empty = self._empty()
54 self._put(item)
55 if was_empty:
56 self.esema.release_lock()
57 if not self._full():
58 self.fsema.release_lock()
59 self.mutex.release_lock()
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 """
66 self.esema.acquire_lock()
67 self.mutex.acquire_lock()
68 was_full = self._full()
69 item = self._get()
70 if was_full:
71 self.fsema.release_lock()
72 if not self._empty():
73 self.esema.release_lock()
74 self.mutex.release_lock()
75 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 """
86 locked = self.esema.acquire_lock(0)
87 self.mutex.acquire_lock()
88 if self._empty():
89 # The queue is empty -- we can't have esema
90 self.mutex.release_lock()
91 raise Empty
92 if not locked:
93 locked = self.esema.acquire_lock(0)
94 if not locked:
95 # Somebody else has esema
96 # but we have mutex --
97 # go out of their way
98 self.mutex.release_lock()
99 raise Empty
100 was_full = self._full()
101 item = self._get()
102 if was_full:
103 self.fsema.release_lock()
104 if not self._empty():
105 self.esema.release_lock()
106 self.mutex.release_lock()
107 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