blob: 1cec4e30af21f609beb7f9fab3c591c8b9b418fe [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):
7 pass
8except TypeError:
9 # string based exceptions
10 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):
14 """Initialize a queue object with a given maximum size.
Guido van Rossum5c971671996-07-22 15:23:25 +000015
Guido van Rossum0b233481997-11-26 15:44:34 +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):
26 """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
31
32 def empty(self):
33 """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
38
39 def full(self):
40 """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
45
46 def put(self, item):
47 """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()
57
58 def get(self):
59 """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
72
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):
76 """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
Guido van Rossum5c971671996-07-22 15:23:25 +000093 self.mutex.release_lock()
Guido van Rossum0b233481997-11-26 15:44:34 +000094 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):
113 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):
117 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):
121 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):
125 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):
129 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):
133 item = self.queue[0]
134 del self.queue[0]
135 return item