|
1 | 1 | # A multi-producer, multi-consumer queue. |
2 | 2 |
|
3 | | -Empty = 'Queue.Empty' # Exception raised by get_nowait() |
| 3 | +# define this exception to be compatible with Python 1.5's class |
| 4 | +# exceptions, but also when -X option is used. |
| 5 | +try: |
| 6 | + class Empty(Exception): |
| 7 | + pass |
| 8 | +except TypeError: |
| 9 | + # string based exceptions |
| 10 | + Empty = 'Queue.Empty' # Exception raised by get_nowait() |
4 | 11 |
|
5 | 12 | class Queue: |
6 | | - |
7 | | - # Initialize a queue object with a given maximum size |
8 | | - # (If maxsize is <= 0, the maximum size is infinite) |
9 | | - def __init__(self, maxsize): |
10 | | - import thread |
11 | | - self._init(maxsize) |
12 | | - self.mutex = thread.allocate_lock() |
13 | | - self.esema = thread.allocate_lock() |
14 | | - self.esema.acquire_lock() |
15 | | - self.fsema = thread.allocate_lock() |
16 | | - |
17 | | - # Get an approximation of the queue size (not reliable!) |
18 | | - def qsize(self): |
19 | | - self.mutex.acquire_lock() |
20 | | - n = self._qsize() |
21 | | - self.mutex.release_lock() |
22 | | - return n |
23 | | - |
24 | | - # Check if the queue is empty (not reliable!) |
25 | | - def empty(self): |
26 | | - self.mutex.acquire_lock() |
27 | | - n = self._empty() |
28 | | - self.mutex.release_lock() |
29 | | - return n |
30 | | - |
31 | | - # Check if the queue is full (not reliable!) |
32 | | - def full(self): |
33 | | - self.mutex.acquire_lock() |
34 | | - n = self._full() |
35 | | - self.mutex.release_lock() |
36 | | - return n |
37 | | - |
38 | | - # Put a new item into the queue |
39 | | - def put(self, item): |
40 | | - self.fsema.acquire_lock() |
41 | | - self.mutex.acquire_lock() |
42 | | - was_empty = self._empty() |
43 | | - self._put(item) |
44 | | - if was_empty: |
45 | | - self.esema.release_lock() |
46 | | - if not self._full(): |
47 | | - self.fsema.release_lock() |
48 | | - self.mutex.release_lock() |
49 | | - |
50 | | - # Get an item from the queue, |
51 | | - # blocking if necessary until one is available |
52 | | - def get(self): |
53 | | - self.esema.acquire_lock() |
54 | | - self.mutex.acquire_lock() |
55 | | - was_full = self._full() |
56 | | - item = self._get() |
57 | | - if was_full: |
58 | | - self.fsema.release_lock() |
59 | | - if not self._empty(): |
60 | | - self.esema.release_lock() |
61 | | - self.mutex.release_lock() |
62 | | - return item |
63 | | - |
64 | | - # Get an item from the queue if one is immediately available, |
65 | | - # raise Empty if the queue is empty or temporarily unavailable |
66 | | - def get_nowait(self): |
67 | | - locked = self.esema.acquire_lock(0) |
68 | | - self.mutex.acquire_lock() |
69 | | - if self._empty(): |
70 | | - # The queue is empyt -- we can't have esema |
71 | | - self.mutex.release_lock() |
72 | | - raise Empty |
73 | | - if not locked: |
74 | | - locked = self.esema.acquire_lock(0) |
75 | | - if not locked: |
76 | | - # Somebody else has esema |
77 | | - # but we have mutex -- |
78 | | - # go out of their way |
79 | | - self.mutex.release_lock() |
80 | | - raise Empty |
81 | | - was_full = self._full() |
82 | | - item = self._get() |
83 | | - if was_full: |
84 | | - self.fsema.release_lock() |
85 | | - if not self._empty(): |
86 | | - self.esema.release_lock() |
| 13 | + def __init__(self, maxsize): |
| 14 | + """Initialize a queue object with a given maximum size. |
| 15 | +
|
| 16 | + 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() |
| 24 | + |
| 25 | + 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 |
87 | 93 | self.mutex.release_lock() |
88 | | - return item |
89 | | - |
90 | | - # XXX Need to define put_nowait() as well. |
91 | | - |
92 | | - |
93 | | - # Override these methods to implement other queue organizations |
94 | | - # (e.g. stack or priority queue). |
95 | | - # These will only be called with appropriate locks held |
96 | | - |
97 | | - # Initialize the queue representation |
98 | | - def _init(self, maxsize): |
99 | | - self.maxsize = maxsize |
100 | | - self.queue = [] |
101 | | - |
102 | | - def _qsize(self): |
103 | | - return len(self.queue) |
104 | | - |
105 | | - # Check wheter the queue is empty |
106 | | - def _empty(self): |
107 | | - return not self.queue |
108 | | - |
109 | | - # Check whether the queue is full |
110 | | - def _full(self): |
111 | | - return self.maxsize > 0 and len(self.queue) == self.maxsize |
112 | | - |
113 | | - # Put a new item in the queue |
114 | | - def _put(self, item): |
115 | | - self.queue.append(item) |
116 | | - |
117 | | - # Get an item from the queue |
118 | | - def _get(self): |
119 | | - item = self.queue[0] |
120 | | - del self.queue[0] |
121 | | - return item |
| 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 |
| 103 | + |
| 104 | + # XXX Need to define put_nowait() as well. |
| 105 | + |
| 106 | + |
| 107 | + # 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 |
| 110 | + |
| 111 | + # Initialize the queue representation |
| 112 | + def _init(self, maxsize): |
| 113 | + self.maxsize = maxsize |
| 114 | + self.queue = [] |
| 115 | + |
| 116 | + def _qsize(self): |
| 117 | + return len(self.queue) |
| 118 | + |
| 119 | + # Check wheter the queue is empty |
| 120 | + def _empty(self): |
| 121 | + return not self.queue |
| 122 | + |
| 123 | + # Check whether the queue is full |
| 124 | + def _full(self): |
| 125 | + return self.maxsize > 0 and len(self.queue) == self.maxsize |
| 126 | + |
| 127 | + # Put a new item in the queue |
| 128 | + def _put(self, item): |
| 129 | + self.queue.append(item) |
| 130 | + |
| 131 | + # Get an item from the queue |
| 132 | + def _get(self): |
| 133 | + item = self.queue[0] |
| 134 | + del self.queue[0] |
| 135 | + return item |
0 commit comments