Attributes#
| Attribute | Type | Description |
|---|---|---|
capacity | int | None | How many items the queue holds; |
Functions#
__init__#
__init__(capacity=None, strategy='suspend') -> None| Parameter | Type | Description |
|---|---|---|
capacity | int | None = None | |
strategy | Strategy = 'suspend' |
def __init__(self, capacity: int | None = None, strategy: Strategy = "suspend") -> None:
if capacity is not None and capacity < 0:
raise ValueError(f"capacity must be >= 0, got {capacity}")
self._capacity = capacity
self._strategy: Strategy = strategy
self._items: deque[A] = deque()
self._state: st.State[A, E] = st.Open()make#
make(capacity=None, *, strategy='suspend') -> Effect[Queue[A, E]]A queue of capacity items (None: unbounded) that handles a
full queue by strategy.
| Parameter | Type | Description |
|---|---|---|
capacity | int | None = None | |
strategy | Strategy = 'suspend' |
Returns Effect[Queue[A, E]]
@classmethod
def make(
cls, capacity: int | None = None, *, strategy: Strategy = "suspend"
) -> Effect[Queue[A, E]]:
"""A queue of ``capacity`` items (``None``: unbounded) that handles a
full queue by ``strategy``."""
return _Sync(lambda: cls(capacity, strategy))unbounded#
unbounded() -> Effect[Queue[A, E]]Returns Effect[Queue[A, E]]
@classmethod
def unbounded(cls) -> Effect[Queue[A, E]]:
return _Sync(cls)bounded#
bounded(capacity) -> Effect[Queue[A, E]]offer waits while the queue holds capacity items.
| Parameter | Type | Description |
|---|---|---|
capacity | int |
Returns Effect[Queue[A, E]]
@classmethod
def bounded(cls, capacity: int) -> Effect[Queue[A, E]]:
"""``offer`` waits while the queue holds ``capacity`` items."""
return _Sync(lambda: cls(capacity, "suspend"))dropping#
dropping(capacity) -> Effect[Queue[A, E]]| Parameter | Type | Description |
|---|---|---|
capacity | int |
Returns Effect[Queue[A, E]]
@classmethod
def dropping(cls, capacity: int) -> Effect[Queue[A, E]]:
return _Sync(lambda: cls(capacity, "dropping"))sliding#
sliding(capacity) -> Effect[Queue[A, E]]| Parameter | Type | Description |
|---|---|---|
capacity | int |
Returns Effect[Queue[A, E]]
@classmethod
def sliding(cls, capacity: int) -> Effect[Queue[A, E]]:
return _Sync(lambda: cls(capacity, "sliding"))offer#
offer(item) -> Effect[bool]Add an item. False if the queue is finished, or if it is full
and drops new items.
| Parameter | Type | Description |
|---|---|---|
item | A |
Returns Effect[bool]
def offer(self, item: A) -> Effect[bool]:
"""Add an item. ``False`` if the queue is finished, or if it is full
and drops new items."""
def register(resume: Callable[[Effect[bool]], None]) -> Effect[None] | None:
if self.unsafe_offer(item):
resume(_Succeed(True))
elif isinstance(self._state, st.Open) and self._strategy == "suspend":
return self._park(self._state.offers, st.OfferOne(item, resume))
else:
resume(_Succeed(False))
return None
return _Callback(register)unsafe_offer#
unsafe_offer(item) -> booloffer without waiting, from outside an effect: False if it
would have to wait. Call on the queue's fibers' scheduler thread.
| Parameter | Type | Description |
|---|---|---|
item | A |
Returns bool
def unsafe_offer(self, item: A) -> bool:
"""``offer`` without waiting, from outside an effect: ``False`` if it
would have to wait. Call on the queue's fibers' scheduler thread."""
match self._state:
case st.Open(takers=takers):
if self._free(takers) > 0 or self._strategy == "sliding":
# As Effect's ``offerUnsafe``: a full sliding queue
# swaps its oldest item for this one, even at capacity 0.
self._push([item], takers, keep_at_least=1)
return True
return False
case st.Closing() | st.Done():
return Falseoffer_all#
offer_all(items) -> Effect[list[T]]Add items in order; succeeds with those not added. What fits is added at once. A suspending queue waits to add the rest, and returns what is left if the queue is finished meanwhile.
| Parameter | Type | Description |
|---|---|---|
items | Iterable[T] |
Returns Effect[list[T]]
def offer_all[T](self: Queue[T, Any], items: Iterable[T]) -> Effect[list[T]]:
"""Add items in order; succeeds with those not added. What fits is
added at once. A suspending queue waits to add the rest, and returns
what is left if the queue is finished meanwhile."""
def register(resume: Callable[[Effect[list[T]]], None]) -> Effect[None] | None:
rest = self.unsafe_offer_all(items)
if rest and isinstance(self._state, st.Open) and self._strategy == "suspend":
return self._park(self._state.offers, st.OfferMany(rest, resume))
resume(_Succeed(rest))
return None
return _Callback(register)unsafe_offer_all#
unsafe_offer_all(items) -> list[T]offer_all without waiting: the items that did not fit.
| Parameter | Type | Description |
|---|---|---|
items | Iterable[T] |
Returns list[T]
def unsafe_offer_all[T](self: Queue[T, Any], items: Iterable[T]) -> list[T]:
"""``offer_all`` without waiting: the items that did not fit."""
batch = list(items)
match self._state:
case st.Open(takers=takers):
fits = len(batch) if self._strategy == "sliding" else self._free(takers)
self._push(batch[:fits], takers)
return batch[fits:]
case st.Closing() | st.Done():
return batchend#
end() -> Effect[bool]No more items. Takers fail with Done() once the queue drains.
Only available on queues whose error type includes Done.
Returns Effect[bool]
def end(self: Enqueue[Any, Done]) -> Effect[bool]:
"""No more items. Takers fail with ``Done()`` once the queue drains.
Only available on queues whose error type includes ``Done``."""
return self.fail_cause(fail_cause(Done()))unsafe_end#
unsafe_end() -> boolReturns bool
def unsafe_end(self: Queue[Any, Done]) -> bool:
return self.unsafe_fail_cause(fail_cause(Done()))fail#
fail(error) -> Effect[bool]Takers fail with error once the queue drains.
| Parameter | Type | Description |
|---|---|---|
error | E |
Returns Effect[bool]
def fail(self, error: E) -> Effect[bool]:
"""Takers fail with ``error`` once the queue drains."""
return self.fail_cause(fail_cause(error))interrupt#
interrupt() -> Effect[bool]Takers are interrupted (by the calling fiber) once the queue drains.
Returns Effect[bool]
def interrupt(self) -> Effect[bool]:
"""Takers are interrupted (by the calling fiber) once the queue
drains."""
return _WithFiber(lambda fiber: self.fail_cause(interrupt_cause(fiber.id)))fail_cause#
fail_cause(cause) -> Effect[bool]False if the queue was already ended, failed or shut down.
| Parameter | Type | Description |
|---|---|---|
cause | Cause[E] |
Returns Effect[bool]
def fail_cause(self, cause: Cause[E]) -> Effect[bool]:
"""``False`` if the queue was already ended, failed or shut down."""
return _Sync(lambda: self.unsafe_fail_cause(cause))unsafe_fail_cause#
unsafe_fail_cause(cause) -> bool| Parameter | Type | Description |
|---|---|---|
cause | Cause[E] |
Returns bool
def unsafe_fail_cause(self, cause: Cause[E]) -> bool:
match self._state:
case st.Open(takers=takers, offers=offers, awaiters=awaiters):
self._state = st.Closing(takers, offers, awaiters, cause)
# A batch take waiting for its minimum can now drain the rest.
takers.notify_ready()
self._finish_if_drained()
return True
case st.Closing() | st.Done():
return Falseshutdown#
shutdown() -> Effect[bool]Drop all items and waiting offers; takers are interrupted (or see
the failure of a queue that was closing). False if the queue was
already done.
Returns Effect[bool]
def shutdown(self) -> Effect[bool]:
"""Drop all items and waiting offers; takers are interrupted (or see
the failure of a queue that was closing). ``False`` if the queue was
already done."""
return _Sync(self.unsafe_shutdown)unsafe_shutdown#
unsafe_shutdown() -> boolReturns bool
def unsafe_shutdown(self) -> bool:
match self._state:
case st.Done():
return False
case st.Open(offers=offers):
self._shut(interrupt_cause(), offers)
case st.Closing(offers=offers, cause=cause):
self._shut(cause, offers)
return Trueinto#
into(eff) -> Effect[bool, Never, R]Run eff, then end the queue, or fail it with eff's cause.
The queue is finished even if the running fiber is interrupted.
| Parameter | Type | Description |
|---|---|---|
eff | Effect[object, EE | Done, R] |
Returns Effect[bool, Never, R]
def into[R, EE](
self: Queue[Any, EE | Done], eff: Effect[object, EE | Done, R]
) -> Effect[bool, Never, R]:
"""Run ``eff``, then end the queue, or fail it with ``eff``'s cause.
The queue is finished even if the running fiber is interrupted."""
require_effect(eff, "eff")
return uninterruptible_mask(
lambda restore: restore(eff).match_cause_effect(
on_failure=self.fail_cause, on_success=lambda _: self.end()
)
)take#
take() -> Effect[A, E]Wait for an item.
Returns Effect[A, E]
def take(self) -> Effect[A, E]:
"""Wait for an item."""
def attempt() -> Effect[A, E]:
ex = self.unsafe_take()
return self._wait_then(1, attempt) if ex is None else _FromExit(ex)
return _Suspend(attempt)unsafe_take#
unsafe_take() -> Exit[A, E] | NoneAn item, the failure of a finished queue, or None if take
would wait.
Returns Exit[A, E] | None
def unsafe_take(self) -> Exit[A, E] | None:
"""An item, the failure of a finished queue, or ``None`` if ``take``
would wait."""
match self._state:
case st.Done(cause=cause):
return Failure(cause)
case st.Open(offers=offers) | st.Closing(offers=offers):
if not self._items and not self._takes_from(offers):
return None
item = self._take_one(offers)
self._release()
return Success(item)take_between#
take_between(minimum, maximum) -> Effect[list[A], E]Wait until minimum items are there (or the queue is finishing),
then take up to maximum. A bounded queue never holds more than
its capacity, so it waits for at most that many. A count of 0 or less
takes nothing and does not wait (but still fails on a finished
queue).
| Parameter | Type | Description |
|---|---|---|
minimum | int | |
maximum | int |
Returns Effect[list[A], E]
def take_between(self, minimum: int, maximum: int) -> Effect[list[A], E]:
"""Wait until ``minimum`` items are there (or the queue is finishing),
then take up to ``maximum``. A bounded queue never holds more than
its capacity, so it waits for at most that many. A count of 0 or less
takes nothing and does not wait (but still fails on a finished
queue)."""
return self._take_between(minimum, maximum)take_n#
take_n(n) -> Effect[list[A], E]take_between(n, n).
| Parameter | Type | Description |
|---|---|---|
n | int |
Returns Effect[list[A], E]
def take_n(self, n: int) -> Effect[list[A], E]:
"""``take_between(n, n)``."""
return self._take_between(n, n)take_all#
take_all() -> Effect[list[A], E]Wait for at least one item, then take everything.
Returns Effect[list[A], E]
def take_all(self) -> Effect[list[A], E]:
"""Wait for at least one item, then take everything."""
return self._take_between(1, None)poll#
poll() -> Effect[Option[A]]An item if one is there now; None if not, or if the queue is
finished.
Returns Effect[Option[A]]
def poll(self) -> Effect[Option[A]]:
"""An item if one is there now; ``None`` if not, or if the queue is
finished."""
def attempt() -> Effect[Option[A]]:
ex = self.unsafe_take()
return _Succeed(Some(ex.value) if isinstance(ex, Success) else None)
return _Suspend(attempt)peek#
peek() -> Effect[A, E]Wait for an item and succeed with it, leaving it in the queue.
Offers waiting on a rendezvous queue are not visible to peek.
Returns Effect[A, E]
def peek(self) -> Effect[A, E]:
"""Wait for an item and succeed with it, leaving it in the queue.
Offers waiting on a rendezvous queue are not visible to ``peek``."""
def attempt() -> Effect[A, E]:
match self._state:
case st.Done(cause=cause):
return _FailCause(cause)
case st.Open(takers=takers) | st.Closing(takers=takers):
if not self._items:
ready = self._finished_or(lambda: bool(self._items))
return takers.wait(ready).and_then(_Suspend(attempt))
return _Succeed(self._items[0])
return _Suspend(attempt)clear#
clear() -> Effect[list[Any], Any]Take every item there is now, without waiting. On a queue that
was ended, succeeds with []; on one that failed, fails with that
failure (without Done).
Returns Effect[list[Any], Any]
def clear(self: Queue[Any, Any]) -> Effect[list[Any], Any]:
"""Take every item there is now, without waiting. On a queue that
was ended, succeeds with ``[]``; on one that failed, fails with that
failure (without ``Done``)."""
def attempt() -> Effect[list[Any], Any]:
match self._state:
case st.Done(cause=cause):
return _catch_done(cause, [])
case st.Open(offers=offers) | st.Closing(offers=offers):
if self._items:
items = self._take_buffered(len(self._items))
elif self._takes_from(offers):
items = [st.take_offer(offers)]
else:
return _Succeed([])
self._release()
return _Succeed(items)
return _Suspend(attempt)collect#
collect() -> Effect[list[Any], Any]Take items until the queue is ended, and succeed with all of them. If the queue fails instead, fail with that failure.
Returns Effect[list[Any], Any]
def collect(self: Queue[Any, Any]) -> Effect[list[Any], Any]:
"""Take items until the queue is ended, and succeed with all of them.
If the queue fails instead, fail with that failure."""
def body() -> Generator[Effect[Any, Any, Any], Any, list[Any]]:
out: list[Any] = []
while True:
taken: Exit[list[Any], Any] = yield self.take_all().exit()
match taken:
case Success(value=items):
out.extend(items)
case Failure(cause=cause):
return (yield _catch_done(cause, out))
return _Gen(body)await_done#
await_done() -> Effect[None, Any]Wait until the queue is finished: ended, failed or shut down, and
drained. Succeeds if it was ended; otherwise fails as its takers do
(Effect's Queue.await).
Returns Effect[None, Any]
def await_done(self: Queue[Any, Any]) -> Effect[None, Any]:
"""Wait until the queue is finished: ended, failed or shut down, and
drained. Succeeds if it was ended; otherwise fails as its takers do
(Effect's ``Queue.await``)."""
def attempt() -> Effect[None, Any]:
match self._state:
case st.Done(cause=cause):
return _catch_done(cause, None)
case st.Open(awaiters=awaiters) | st.Closing(awaiters=awaiters):
return awaiters.wait(self._finished_or(lambda: False)).and_then(
_Suspend(attempt)
)
return _Suspend(attempt)size#
size() -> Effect[int]How many items the queue holds (0 once it is finished).
Returns Effect[int]
def size(self) -> Effect[int]:
"""How many items the queue holds (0 once it is finished)."""
return _Sync(self.unsafe_size)unsafe_size#
unsafe_size() -> intReturns int
def unsafe_size(self) -> int:
return 0 if isinstance(self._state, st.Done) else len(self._items)is_full#
is_full() -> Effect[bool]Whether the queue holds capacity items.
Returns Effect[bool]
def is_full(self) -> Effect[bool]:
"""Whether the queue holds ``capacity`` items."""
return _Sync(self.unsafe_is_full)unsafe_is_full#
unsafe_is_full() -> boolReturns bool
def unsafe_is_full(self) -> bool:
return self.unsafe_size() == self._capacityOn This Page
AttributesFunctions__init__makeunboundedboundeddroppingslidingofferunsafe_offeroffer_allunsafe_offer_allendunsafe_endfailinterruptfail_causeunsafe_fail_causeshutdownunsafe_shutdownintotakeunsafe_taketake_betweentake_ntake_allpollpeekclearcollectawait_donesizeunsafe_sizeis_fullunsafe_is_full