The asynchronous effect is composed of four primitive effects.
async-awaitstd/async/internal/async-await: (E, V) -> V allows awaiting asynchronous operations,
async-cancelstd/async/internal/async-cancel: (E, V) -> V allows cancelation of outstanding asynchronous operations,
async-iocstd/async/internal/async-ioc: (E, V) -> V allows execution of linear I/O (iocstd/core/ioc: E) at the handler scope,
and discontinuestd/async/async/discontinue: (E, V) -> V discontinues any running strand (using final ctl).
The main asyncstd/async/async/async: E handler. Uses “libuv” for the C backend,
(with a libuv emscripten wrapper for the Wasm Web backend).
Uses the standard async calls for Javascript (web or Node).
Internal: The current strand of execution is canceled
Call the final ctl discontinuestd/async/async/discontinue: forall<a> () -> discontinue a operation of the effect discontinuestd/async/async/discontinue: (E, V) -> V.
Show an await result.
Wait (asynchronously) for optional secs seconds durationstd/time/duration/duration: V (= 0.seconds or 100.milli-seconds).
Use yieldstd/async/async/yield: () -> async ()() to yield generally to other asynchronous operations.
Wait (asynchronously) for secs seconds as a double.
Use yieldstd/async/async/yield: () -> async ()() to yield to other asynchronous operations.
Await with the exception effect.
Primitive await: call setup to set up an asynchronous callback with the host platform.
The setup is passed the eventloop of the async handler, and a resumestd/core/hnd/resume: forall<a,e,e1,b> (r : resume-context<a,e,e1,b>, x : a) -> e b function
that takes an await-resultstd/async/internal/await-result: V -> V: a cancelation, exception, or regular result.
The setup function returns either an error, or a dispose funcion that is invoked on cancellation
to dispose of any resources (see the implementation of wait).
The resumestd/core/hnd/resume: forall<a,e,e1,b> (r : resume-context<a,e,e1,b>, x : a) -> e b is invoked exactly once (either on the async completion callback, or on cancelation).
Perform a stateful operation in the outer async handler.
Await a zero argument callback.
Await a single argument callback.
Convenience function for awaiting a single argument callback that never fails.
Cancel any other outstanding operations that are interleaved and
part of the same cancelation scope (see cancelation-scopestd/async/async/cancelation-scope: forall<a,e> (action : () -> <async|e> a) -> <async|e> a).
Set up a new cancelation scope.
Run an action as if it is part of the parent scope
(so it will be canceled only if the parent scope is canceled).
Is the current cancelation canceled?
Catch a discontinue as a maybestd/core/types/maybe: V -> V.
Use with care as cancelation should not be ignored.
Yield to other asynchronous operations. Same as wait(0).
Asynchronous primitives.
This module is based closely on [1] and aims to have robust and composable asynchronous primitives. In particular, any outstanding asynchronous operation can be canceled (through
cancel-outstandingstd/async/async/cancel-outstanding: () -> async-cancel ()) within a certain cancelation scope which allows for composable primitives liketimeoutandinterleave.1. Cancelation
When calling
cancel-outstandingstd/async/async/cancel-outstanding: () -> async-cancel (), it cancels any outstanding async operations in the current cancelation scope and any of its child scopes. Some reasons for cancelation: - returning normally, cancelation prevents dangling callbacks - returning abnormally (e.g. an exception), we cancel any pending callbacks - within afirstof, we have decided to cancel all remaining strands after the first is one completesAfter
cancel-outstandingstd/async/async/cancel-outstanding: () -> async-cancel ()is called, the caller continues as normal - callingcancel-oustandingsimply returns().The way that cancelation is observed is that all outstanding async operaions in the cancelation scope receive a
Cancelstd/async/internal/Cancel: forall<a> await-result<a>result instead of aResultstd/async/internal/Result: forall<a> (value : a) -> await-result<a>(orException). Aside from low-level code, a user won't observe this as the abstractions awaiting a result automatically usediscontinuestd/async/async/discontinue: forall<a> () -> discontinue a()whenCancelstd/async/internal/Cancel: forall<a> await-result<a>a result is given.We use a separate effect
discontinuestd/async/async/discontinue: (E, V) -> Vinstead of an exception since it is intended that adiscontinuestd/async/async/discontinue: forall<a> () -> discontinue ais never handled and always discontinues a stsrand. Of course,finallystd/core/hnd/finally: forall<a,e> (fin : () -> e (), action : () -> e a) -> e ablocks still execute so external resources can be released properly.2. References
.