mirror of
https://github.com/python/cpython.git
synced 2025-07-09 20:35:26 +00:00
bpo-14976: Reentrant simple queue (#3346)
Add a queue.SimpleQueue class, an unbounded FIFO queue with a reentrant C implementation of put().
This commit is contained in:
parent
5ec0feeeec
commit
94e1696d04
12 changed files with 1125 additions and 12 deletions
86
Lib/queue.py
86
Lib/queue.py
|
@ -4,17 +4,26 @@ import threading
|
|||
from collections import deque
|
||||
from heapq import heappush, heappop
|
||||
from time import monotonic as time
|
||||
try:
|
||||
from _queue import SimpleQueue
|
||||
except ImportError:
|
||||
SimpleQueue = None
|
||||
|
||||
__all__ = ['Empty', 'Full', 'Queue', 'PriorityQueue', 'LifoQueue']
|
||||
__all__ = ['Empty', 'Full', 'Queue', 'PriorityQueue', 'LifoQueue', 'SimpleQueue']
|
||||
|
||||
class Empty(Exception):
|
||||
'Exception raised by Queue.get(block=0)/get_nowait().'
|
||||
pass
|
||||
|
||||
try:
|
||||
from _queue import Empty
|
||||
except AttributeError:
|
||||
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
|
||||
|
||||
|
||||
class Queue:
|
||||
'''Create a queue object with a given maximum size.
|
||||
|
||||
|
@ -241,3 +250,72 @@ class LifoQueue(Queue):
|
|||
|
||||
def _get(self):
|
||||
return self.queue.pop()
|
||||
|
||||
|
||||
class _PySimpleQueue:
|
||||
'''Simple, unbounded FIFO queue.
|
||||
|
||||
This pure Python implementation is not reentrant.
|
||||
'''
|
||||
# Note: while this pure Python version provides fairness
|
||||
# (by using a threading.Semaphore which is itself fair, being based
|
||||
# on threading.Condition), fairness is not part of the API contract.
|
||||
# This allows the C version to use a different implementation.
|
||||
|
||||
def __init__(self):
|
||||
self._queue = deque()
|
||||
self._count = threading.Semaphore(0)
|
||||
|
||||
def put(self, item, block=True, timeout=None):
|
||||
'''Put the item on the queue.
|
||||
|
||||
The optional 'block' and 'timeout' arguments are ignored, as this method
|
||||
never blocks. They are provided for compatibility with the Queue class.
|
||||
'''
|
||||
self._queue.append(item)
|
||||
self._count.release()
|
||||
|
||||
def get(self, block=True, timeout=None):
|
||||
'''Remove and return an item from the queue.
|
||||
|
||||
If optional args 'block' is true and 'timeout' is None (the default),
|
||||
block if necessary until an item is available. If 'timeout' is
|
||||
a non-negative number, it blocks at most 'timeout' seconds and raises
|
||||
the Empty exception if no item was available within that time.
|
||||
Otherwise ('block' is false), return an item if one is immediately
|
||||
available, else raise the Empty exception ('timeout' is ignored
|
||||
in that case).
|
||||
'''
|
||||
if timeout is not None and timeout < 0:
|
||||
raise ValueError("'timeout' must be a non-negative number")
|
||||
if not self._count.acquire(block, timeout):
|
||||
raise Empty
|
||||
return self._queue.popleft()
|
||||
|
||||
def put_nowait(self, item):
|
||||
'''Put an item into the queue without blocking.
|
||||
|
||||
This is exactly equivalent to `put(item)` and is only provided
|
||||
for compatibility with the Queue class.
|
||||
'''
|
||||
return self.put(item, block=False)
|
||||
|
||||
def get_nowait(self):
|
||||
'''Remove and return an item from the queue without blocking.
|
||||
|
||||
Only get an item if one is immediately available. Otherwise
|
||||
raise the Empty exception.
|
||||
'''
|
||||
return self.get(block=False)
|
||||
|
||||
def empty(self):
|
||||
'''Return True if the queue is empty, False otherwise (not reliable!).'''
|
||||
return len(self._queue) == 0
|
||||
|
||||
def qsize(self):
|
||||
'''Return the approximate size of the queue (not reliable!).'''
|
||||
return len(self._queue)
|
||||
|
||||
|
||||
if SimpleQueue is None:
|
||||
SimpleQueue = _PySimpleQueue
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue