ic_cdk_executor/lib.rs
1//! An async executor for [`ic-cdk`](https://docs.rs/ic-cdk). Most users should not use this crate directly. It is useful
2//! primarily for those who are writing their own CDK or a runtime host for non-Rust languages.
3//!
4//! ## Contexts
5//!
6//! The expected boilerplate for a canister method or other entrypoint (*not* including callbacks) looks like this:
7//!
8//! ```
9//! # use ic_cdk_executor::*;
10//! pub extern "C" fn function() {
11//! in_tracking_executor_context(|| {
12//! // method goes here
13//! });
14//! }
15//! ```
16//!
17//! The [`in_tracking_executor_context`] function permits you to call `spawn_*` functions. As little code as possible
18//! should exist outside the block, because [`in_tracking_executor_context`] additionally sets up the panic handler.
19//!
20//! The above applies to update contexts. Query contexts, including `canister_inspect_message`, should use
21//! [`in_tracking_query_executor_context`].
22//!
23//! The expected boilerplate for an inter-canister call callback looks like this:
24//!
25//! ```
26//! # use ic_cdk_executor::*;
27//! # fn unpack_env(env: usize) -> MethodHandle { unimplemented!() }
28//! unsafe extern "C" fn callback(env: usize) {
29//! let method = unpack_env(env);
30//! in_callback_executor_context_for(method, || {
31//! // wake the call future
32//! });
33//! }
34//! unsafe extern "C" fn cleanup(env: usize) {
35//! let method = unpack_env(env);
36//! in_trap_recovery_context_for(method, || {
37//! cancel_all_tasks_attached_to_current_method();
38//! });
39//! }
40//! ```
41//!
42//! In async contexts, all scheduled tasks are run *after* the closure passed to the context function
43//! returns, but *before* the context function itself returns.
44//!
45//! The `method` parameter must be retrieved *before* making inter-canister calls via the [`extend_current_method_context`]
46//! function. Calling this function from the callback instead will trap.
47//!
48//! ## Protection
49//!
50//! Tasks can be either *protected* or *migratory*. Protected tasks are attached to the method that spawned them,
51//! when awoken will not resume until that method continues, and will be canceled if the method returns before they complete.
52//! Migratory tasks are not attached to any method, and will resume in whatever method wakes them.
53mod machinery;
54
55#[doc(inline)]
56pub use machinery::{
57 MethodHandle, TaskHandle, cancel_all_tasks_attached_to_current_method, cancel_task,
58 extend_current_method_context, in_callback_executor_context_for, in_tracking_executor_context,
59 in_tracking_query_executor_context, in_trap_recovery_context_for, is_recovering_from_trap,
60 spawn_migratory, spawn_protected,
61};