Scopes: where resources register their release.
acquire_release adds a finalizer to the current Scope (which joins
R); scoped creates a scope, runs the effect in it, and closes it
however the effect ends, removing Scope from R. Finalizers run in
reverse order of registration, uninterruptibly, and all of them run even if
some fail.
Classes#
Functions#
scoped#
scoped(eff) -> Effect[Any, Any, Any]Run eff in a new scope and close it when eff ends.
| Parameter | Type | Description |
|---|---|---|
eff | Effect[Any, Any, Any] |
Returns Effect[Any, Any, Any]
def scoped(eff: Effect[Any, Any, Any]) -> Effect[Any, Any, Any]:
"""Run ``eff`` in a new scope and close it when ``eff`` ends."""
require_effect(eff, "eff")
def body() -> Effect[Any, Any, Any]:
scope = CloseableScope()
inner: Effect[Any, Any, Any] = _Locally(eff, lambda ctx: ctx.add(Scope, scope))
return inner.on_exit(scope.close)
return _Suspend(body)scoped_with#
scoped_with(f) -> Effect[A, E, R]Run f with a new scope and close it when the effect f gives
ends.
| Parameter | Type | Description |
|---|---|---|
f | Callable[[CloseableScope], Effect[A, E, R]] |
Returns Effect[A, E, R]
def scoped_with[A, E = Never, R = Never](
f: Callable[[CloseableScope], Effect[A, E, R]],
) -> Effect[A, E, R]:
"""Run ``f`` with a new scope and close it when the effect ``f`` gives
ends."""
def body() -> Effect[A, E, R]:
scope = CloseableScope()
return _call_user(f, scope).on_exit(scope.close)
return _Suspend(body)add_finalizer#
add_finalizer(f) -> Effect[None, Never, Scope | R]| Parameter | Type | Description |
|---|---|---|
f | Callable[[Exit[Any, Any]], Effect[object, Never, R]] |
Returns Effect[None, Never, Scope | R]
def add_finalizer[R = Never](
f: Callable[[Exit[Any, Any]], Effect[object, Never, R]],
) -> Effect[None, Never, Scope | R]:
return Scope().flat_map(lambda scope: scope.add_finalizer(f))acquire_release#
acquire_release(acquire, release) -> Effect[A, E, RR | Scope]Acquire uninterruptibly and register release on the current
scope.
| Parameter | Type | Description |
|---|---|---|
acquire | Effect[A, E, RR] | |
release | Callable[[A, Exit[Any, Any]], Effect[object, Never, RR]] |
Returns Effect[A, E, RR | Scope]
def acquire_release[A, E = Never, RR = Never](
acquire: Effect[A, E, RR],
release: Callable[[A, Exit[Any, Any]], Effect[object, Never, RR]],
) -> Effect[A, E, RR | Scope]:
"""Acquire uninterruptibly and register ``release`` on the current
scope."""
require_effect(acquire, "acquire")
def body():
a = yield from acquire
scope = yield from Scope()
yield from scope.add_finalizer(lambda ex: release(a, ex))
return a
return _Gen(body).uninterruptible()acquire_use_release#
acquire_use_release(acquire, use, release) -> Effect[B, EE, RR]Acquire, use, and always release, without needing a scope.
| Parameter | Type | Description |
|---|---|---|
acquire | Effect[A, EE, RR] | |
use | Callable[[A], Effect[B, EE, RR]] | |
release | Callable[[A, Exit[B, EE]], Effect[object, Never, RR]] |
Returns Effect[B, EE, RR]
def acquire_use_release[A, B, EE = Never, RR = Never](
acquire: Effect[A, EE, RR],
use: Callable[[A], Effect[B, EE, RR]],
release: Callable[[A, Exit[B, EE]], Effect[object, Never, RR]],
) -> Effect[B, EE, RR]:
"""Acquire, use, and always release, without needing a scope."""
require_effect(acquire, "acquire")
return uninterruptible_mask(
lambda restore: acquire.flat_map(
lambda a: restore(_call_user(use, a)).on_exit(lambda ex: release(a, ex))
)
)fork_scoped#
fork_scoped(eff, *, start_immediately=False, uninterruptible=False) -> Effect[Fiber[A, E], Never, R | Scope]Fork eff into the current scope (see fork_in).
| Parameter | Type | Description |
|---|---|---|
eff | Effect[A, E, R] | |
start_immediately | bool = False | |
uninterruptible | Uninterruptible = False |
Returns Effect[Fiber[A, E], Never, R | Scope]
def fork_scoped[A, E, R](
eff: Effect[A, E, R],
*,
start_immediately: bool = False,
uninterruptible: Uninterruptible = False,
) -> Effect[Fiber[A, E], Never, R | Scope]:
"""Fork ``eff`` into the current scope (see ``fork_in``)."""
require_effect(eff, "eff")
return Scope().flat_map(
lambda scope: fork_in(
eff, scope, start_immediately=start_immediately, uninterruptible=uninterruptible
)
)fork_in#
fork_in(eff, scope, *, start_immediately=False, uninterruptible=False) -> Effect[Fiber[A, E], Never, R]Fork eff on a fiber that outlives its parent but is interrupted
when scope closes, and leaves the scope when it exits. Into a
closed scope it gives an already-interrupted fiber that never ran
eff.
| Parameter | Type | Description |
|---|---|---|
eff | Effect[A, E, R] | |
scope | CloseableScope | |
start_immediately | bool = False | |
uninterruptible | Uninterruptible = False |
Returns Effect[Fiber[A, E], Never, R]
def fork_in[A, E, R](
eff: Effect[A, E, R],
scope: CloseableScope,
*,
start_immediately: bool = False,
uninterruptible: Uninterruptible = False,
) -> Effect[Fiber[A, E], Never, R]:
"""Fork ``eff`` on a fiber that outlives its parent but is interrupted
when ``scope`` closes, and leaves the scope when it exits. Into a
closed scope it gives an already-interrupted fiber that never ran
``eff``."""
require_effect(eff, "eff")
def body(parent: Fiber[Any, Any]) -> Effect[Fiber[A, E]]:
if scope._closed is not None:
unstarted: Fiber[A, E] = Fiber(parent._run_scheduler, parent._context, None)
unstarted.unsafe_interrupt_as(parent.id, parent._interruptor_annotations())
return _Succeed(unstarted)
fiber: Fiber[A, E] = parent._fork(
eff, daemon=True, start_immediately=start_immediately, uninterruptible=uninterruptible
)
scope._watch(fiber)
return _AfterStarted(fiber)
return _WithFiber(body)