| 
									
										
										
										
											2000-02-02 15:10:15 +00:00
										 |  |  | """A multi-producer, multi-consumer queue.""" | 
					
						
							| 
									
										
										
										
											1992-08-25 12:30:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-01-15 22:53:46 +00:00
										 |  |  | class Empty(Exception): | 
					
						
							|  |  |  |     "Exception raised by Queue.get(block=0)/get_nowait()." | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Full(Exception): | 
					
						
							|  |  |  |     "Exception raised by Queue.put(block=0)/put_nowait()." | 
					
						
							|  |  |  |     pass | 
					
						
							| 
									
										
										
										
											1992-08-25 12:30:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Queue: | 
					
						
							| 
									
										
										
										
											1999-09-09 14:54:28 +00:00
										 |  |  |     def __init__(self, maxsize=0): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Initialize a queue object with a given maximum size.
 | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         If maxsize is <= 0, the queue size is infinite. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         import thread | 
					
						
							|  |  |  |         self._init(maxsize) | 
					
						
							|  |  |  |         self.mutex = thread.allocate_lock() | 
					
						
							|  |  |  |         self.esema = thread.allocate_lock() | 
					
						
							| 
									
										
										
										
											1998-04-29 14:29:32 +00:00
										 |  |  |         self.esema.acquire() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         self.fsema = thread.allocate_lock() | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def qsize(self): | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |         """Return the approximate size of the queue (not reliable!).""" | 
					
						
							| 
									
										
										
										
											1998-04-29 14:29:32 +00:00
										 |  |  |         self.mutex.acquire() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         n = self._qsize() | 
					
						
							| 
									
										
										
										
											1998-04-29 14:29:32 +00:00
										 |  |  |         self.mutex.release() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         return n | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def empty(self): | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |         """Return 1 if the queue is empty, 0 otherwise (not reliable!).""" | 
					
						
							| 
									
										
										
										
											1998-04-29 14:29:32 +00:00
										 |  |  |         self.mutex.acquire() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         n = self._empty() | 
					
						
							| 
									
										
										
										
											1998-04-29 14:29:32 +00:00
										 |  |  |         self.mutex.release() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         return n | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def full(self): | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |         """Return 1 if the queue is full, 0 otherwise (not reliable!).""" | 
					
						
							| 
									
										
										
										
											1998-04-29 14:29:32 +00:00
										 |  |  |         self.mutex.acquire() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         n = self._full() | 
					
						
							| 
									
										
										
										
											1998-04-29 14:29:32 +00:00
										 |  |  |         self.mutex.release() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         return n | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |     def put(self, item, block=1): | 
					
						
							| 
									
										
										
										
											1998-04-09 14:25:32 +00:00
										 |  |  |         """Put an item into the queue.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |         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. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         if block: | 
					
						
							|  |  |  |             self.fsema.acquire() | 
					
						
							|  |  |  |         elif not self.fsema.acquire(0): | 
					
						
							|  |  |  |             raise Full | 
					
						
							| 
									
										
										
										
											1998-04-29 14:29:32 +00:00
										 |  |  |         self.mutex.acquire() | 
					
						
							| 
									
										
										
										
											2002-04-19 00:11:32 +00:00
										 |  |  |         release_fsema = True | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             was_empty = self._empty() | 
					
						
							|  |  |  |             self._put(item) | 
					
						
							|  |  |  |             # If we fail before here, the empty state has | 
					
						
							|  |  |  |             # not changed, so we can skip the release of esema | 
					
						
							|  |  |  |             if was_empty: | 
					
						
							|  |  |  |                 self.esema.release() | 
					
						
							|  |  |  |             # If we fail before here, the queue can not be full, so | 
					
						
							|  |  |  |             # release_full_sema remains True | 
					
						
							|  |  |  |             release_fsema = not self._full() | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             # Catching system level exceptions here (RecursionDepth, | 
					
						
							|  |  |  |             # OutOfMemory, etc) - so do as little as possible in terms | 
					
						
							|  |  |  |             # of Python calls. | 
					
						
							|  |  |  |             if release_fsema: | 
					
						
							|  |  |  |                 self.fsema.release() | 
					
						
							|  |  |  |             self.mutex.release() | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |     def put_nowait(self, item): | 
					
						
							|  |  |  |         """Put an item into the queue without blocking.
 | 
					
						
							| 
									
										
										
										
											1998-04-09 14:25:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |         Only enqueue the item if a free slot is immediately available. | 
					
						
							|  |  |  |         Otherwise raise the Full exception. | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |         return self.put(item, 0) | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |     def get(self, block=1): | 
					
						
							|  |  |  |         """Remove and return an item from the queue.
 | 
					
						
							| 
									
										
										
										
											1998-04-09 14:25:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |         If optional arg 'block' is 1 (the default), block if | 
					
						
							|  |  |  |         necessary until an item is available.  Otherwise (block is 0), | 
					
						
							|  |  |  |         return an item if one is immediately available, else raise the | 
					
						
							|  |  |  |         Empty exception. | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |         if block: | 
					
						
							|  |  |  |             self.esema.acquire() | 
					
						
							|  |  |  |         elif not self.esema.acquire(0): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             raise Empty | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |         self.mutex.acquire() | 
					
						
							| 
									
										
										
										
											2002-04-19 00:11:32 +00:00
										 |  |  |         release_esema = True | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             was_full = self._full() | 
					
						
							|  |  |  |             item = self._get() | 
					
						
							|  |  |  |             # If we fail before here, the full state has | 
					
						
							|  |  |  |             # not changed, so we can skip the release of fsema | 
					
						
							|  |  |  |             if was_full: | 
					
						
							|  |  |  |                 self.fsema.release() | 
					
						
							|  |  |  |             # Failure means empty state also unchanged - release_esema | 
					
						
							|  |  |  |             # remains True. | 
					
						
							|  |  |  |             release_esema = not self._empty() | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             if release_esema: | 
					
						
							|  |  |  |                 self.esema.release() | 
					
						
							|  |  |  |             self.mutex.release() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         return item | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |     def get_nowait(self): | 
					
						
							|  |  |  |         """Remove and return an item from the queue without blocking.
 | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-08 18:34:01 +00:00
										 |  |  |         Only get an item if one is immediately available.  Otherwise | 
					
						
							|  |  |  |         raise the Empty exception. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         return self.get(0) | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Override these methods to implement other queue organizations | 
					
						
							|  |  |  |     # (e.g. stack or priority queue). | 
					
						
							|  |  |  |     # These will only be called with appropriate locks held | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Initialize the queue representation | 
					
						
							|  |  |  |     def _init(self, maxsize): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         self.maxsize = maxsize | 
					
						
							|  |  |  |         self.queue = [] | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _qsize(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         return len(self.queue) | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-06-28 14:48:01 +00:00
										 |  |  |     # Check whether the queue is empty | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  |     def _empty(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         return not self.queue | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Check whether the queue is full | 
					
						
							|  |  |  |     def _full(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         return self.maxsize > 0 and len(self.queue) == self.maxsize | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Put a new item in the queue | 
					
						
							|  |  |  |     def _put(self, item): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         self.queue.append(item) | 
					
						
							| 
									
										
										
										
											1997-11-20 19:56:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Get an item from the queue | 
					
						
							|  |  |  |     def _get(self): | 
					
						
							| 
									
										
										
										
											2002-06-30 03:39:14 +00:00
										 |  |  |         return self.queue.pop(0) |