Attributes#
| Attribute | Type | Description |
|---|---|---|
capacity | = max(0, permits) | |
available | Effect[int] |
Functions#
__init__#
__init__(permits) -> None| Parameter | Type | Description |
|---|---|---|
permits | int |
def __init__(self, permits: int) -> None:
self.capacity = max(0, permits)
self._total = self.capacity # free permits nobody is waiting for
self._waiting = 0 # permits waiters still miss
self._pending = 0 # released permits not yet handed out
self._releasing = False
# Typed by Hashable, not K, so K only goes in (contravariant, as in Effect).
self._waiters: RoundRobin[Hashable, _Waiter] = RoundRobin()make#
make(permits) -> Effect[PartitionedSemaphore[K]]PartitionedSemaphore[str].make(4)
| Parameter | Type | Description |
|---|---|---|
permits | int |
Returns Effect[PartitionedSemaphore[K]]
@classmethod
def make(cls, permits: int) -> Effect[PartitionedSemaphore[K]]:
"""``PartitionedSemaphore[str].make(4)``"""
return _Sync(lambda: cls(permits))take#
take(key, n=1) -> Effect[None]Wait in key's queue for n permits and take them. Prefer
with_permits, which also gives them back.
| Parameter | Type | Description |
|---|---|---|
key | K | |
n | int = 1 |
Returns Effect[None]
def take(self, key: K, n: int = 1) -> Effect[None]:
"""Wait in ``key``'s queue for ``n`` permits and take them. Prefer
``with_permits``, which also gives them back."""
if n <= 0:
return _VOID
if self.capacity < n:
return never
def run(fiber: Fiber[Any, Any]) -> Effect[None]:
guard = _GiveBackOnFailure(lambda: self._release(n))
fiber._push(guard)
def arm(_: None) -> None:
guard.armed = True
return uninterruptible_mask(lambda restore: self._acquire(key, n, restore).map(arm))
return _WithFiber(run)release#
release(n=1) -> Effect[int]Give back n permits; succeeds with the number now free.
| Parameter | Type | Description |
|---|---|---|
n | int = 1 |
Returns Effect[int]
def release(self, n: int = 1) -> Effect[int]:
"""Give back ``n`` permits; succeeds with the number now free."""
return _Sync(lambda: self._release(n))with_permits#
with_permits(key, eff, n=1) -> Effect[A, E, R]Run eff holding n permits taken in key's queue,
releasing them however it ends.
| Parameter | Type | Description |
|---|---|---|
key | K | |
eff | Effect[A, E, R] | |
n | int = 1 |
Returns Effect[A, E, R]
def with_permits[A, E, R](self, key: K, eff: Effect[A, E, R], n: int = 1) -> Effect[A, E, R]:
"""Run ``eff`` holding ``n`` permits taken in ``key``'s queue,
releasing them however it ends."""
require_effect(eff, "eff")
if n <= 0:
return eff
if self.capacity < n:
return never
release = self.release(n)
return uninterruptible_mask(
lambda restore: self._acquire(key, n, restore).and_then(restore(eff).ensuring(release))
)with_permits_if_available#
with_permits_if_available(eff, n=1) -> Effect[Option[A], E, R]Run eff holding n permits if they are free now (Some
of its result); otherwise None without running it.
| Parameter | Type | Description |
|---|---|---|
eff | Effect[A, E, R] | |
n | int = 1 |
Returns Effect[Option[A], E, R]
def with_permits_if_available[A, E, R](
self, eff: Effect[A, E, R], n: int = 1
) -> Effect[Option[A], E, R]:
"""Run ``eff`` holding ``n`` permits if they are free now (``Some``
of its result); otherwise ``None`` without running it."""
require_effect(eff, "eff")
if n <= 0:
return eff.map(Some)
def body(restore: Restore) -> Effect[Option[A], E, R]:
def run() -> Effect[Option[A], E, R]:
if self._total < n:
return _Succeed(None)
self._total -= n
return restore(eff.map(Some)).ensuring(self.release(n))
return _Suspend(run)
return uninterruptible_mask(body)