blob: 6710153d2003c633cd70717145213004eadc89f4 [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 Rossum45e2fbc1998-03-26 21:13:24 +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()
Barry Warsaw3d96d521997-11-20 19:56:38 +000057
58 def get(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +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
Barry Warsaw3d96d521997-11-20 19:56:38 +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 Rossum45e2fbc1998-03-26 21:13:24 +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 Rossum9022fce1992-08-25 12:30:44 +0000103
Barry Warsaw3d96d521997-11-20 19:56:38 +0000104 # XXX Need to define put_nowait() as well.
Guido van Rossum9022fce1992-08-25 12:30:44 +0000105
Guido van Rossum9022fce1992-08-25 12:30:44 +0000106
Barry Warsaw3d96d521997-11-20 19:56:38 +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 Rossum9022fce1992-08-25 12:30:44 +0000110
Barry Warsaw3d96d521997-11-20 19:56:38 +0000111 # Initialize the queue representation
112 def _init(self, maxsize):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000113 self.maxsize = maxsize
114 self.queue = []
Guido van Rossum9022fce1992-08-25 12:30:44 +0000115
Barry Warsaw3d96d521997-11-20 19:56:38 +0000116 def _qsize(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000117 return len(self.queue)
Guido van Rossum9022fce1992-08-25 12:30:44 +0000118
Barry Warsaw3d96d521997-11-20 19:56:38 +0000119 # Check wheter the queue is empty
120 def _empty(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000121 return not self.queue
Guido van Rossum9022fce1992-08-25 12:30:44 +0000122
Barry Warsaw3d96d521997-11-20 19:56:38 +0000123 # Check whether the queue is full
124 def _full(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000125 return self.maxsize > 0 and len(self.queue) == self.maxsize
Guido van Rossum9022fce1992-08-25 12:30:44 +0000126
Barry Warsaw3d96d521997-11-20 19:56:38 +0000127 # Put a new item in the queue
128 def _put(self, item):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000129 self.queue.append(item)
Guido van Rossum9022fce1992-08-25 12:30:44 +0000130
Barry Warsaw3d96d521997-11-20 19:56:38 +0000131 # Get an item from the queue
132 def _get(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000133 item = self.queue[0]
134 del self.queue[0]
135 return item