pub struct Cx<Caps = CapSet<true, true, true, true, true>> { /* private fields */ }Expand description
The capability context for a task.
Cx provides access to runtime capabilities within Asupersync. All effectful
operations flow through Cx, ensuring explicit capability security with no
ambient authority.
§Overview
A Cx instance is provided to each task by the runtime. It grants access to:
- Identity: Query the current region and task IDs
- Budget: Check remaining time/poll quotas
- Cancellation: Observe and respond to cancellation requests
- Tracing: Emit trace events for observability
§Usage for External Crates
External crates like fastapi_rust can depend on Asupersync and use Cx:
use asupersync::Cx;
async fn handle_request(cx: &Cx) -> Result<Response, Error> {
// Check if the request should be cancelled
if cx.is_cancel_requested() {
return Err(Error::Cancelled);
}
// Check remaining budget (timeout)
let budget = cx.budget();
if budget.is_expired() {
return Err(Error::Timeout);
}
// Trace request handling
cx.trace("Processing request");
// Do work...
Ok(Response::new())
}§Cloning
Cx is cheaply clonable (it wraps an Arc). Clones share the same
underlying state, so cancellation signals and budget updates are visible
to all clones.
§Lifetime Considerations
While Cx can be cloned and moved, it semantically belongs to a specific
task within a specific region. The runtime ensures proper cleanup when
tasks complete.
Implementations§
Source§impl Cx
impl Cx
Sourcepub fn current() -> Option<Cx>
pub fn current() -> Option<Cx>
Returns the current task context, if one is set.
This is set by the runtime while polling a task.
Sourcepub fn set_current(cx: Option<Cx>) -> CurrentCxGuard
pub fn set_current(cx: Option<Cx>) -> CurrentCxGuard
Sets the current task context for the duration of the guard.
Source§impl<Caps> Cx<Caps>
impl<Caps> Cx<Caps>
Sourcepub fn new(region: RegionId, task: TaskId, budget: Budget) -> Cx<Caps>
pub fn new(region: RegionId, task: TaskId, budget: Budget) -> Cx<Caps>
Creates a new capability context (internal use).
Sourcepub fn new_with_observability(
region: RegionId,
task: TaskId,
budget: Budget,
observability: Option<ObservabilityState>,
io_driver: Option<IoDriverHandle>,
entropy: Option<Arc<dyn EntropySource>>,
) -> Cx<Caps>
pub fn new_with_observability( region: RegionId, task: TaskId, budget: Budget, observability: Option<ObservabilityState>, io_driver: Option<IoDriverHandle>, entropy: Option<Arc<dyn EntropySource>>, ) -> Cx<Caps>
Creates a new capability context with optional observability state (internal use).
Sourcepub fn new_with_io(
region: RegionId,
task: TaskId,
budget: Budget,
observability: Option<ObservabilityState>,
io_driver: Option<IoDriverHandle>,
io_cap: Option<Arc<dyn IoCap>>,
entropy: Option<Arc<dyn EntropySource>>,
) -> Cx<Caps>
pub fn new_with_io( region: RegionId, task: TaskId, budget: Budget, observability: Option<ObservabilityState>, io_driver: Option<IoDriverHandle>, io_cap: Option<Arc<dyn IoCap>>, entropy: Option<Arc<dyn EntropySource>>, ) -> Cx<Caps>
Creates a new capability context with optional I/O capability (internal use).
Sourcepub fn new_with_drivers(
region: RegionId,
task: TaskId,
budget: Budget,
observability: Option<ObservabilityState>,
io_driver: Option<IoDriverHandle>,
io_cap: Option<Arc<dyn IoCap>>,
timer_driver: Option<TimerDriverHandle>,
entropy: Option<Arc<dyn EntropySource>>,
) -> Cx<Caps>
pub fn new_with_drivers( region: RegionId, task: TaskId, budget: Budget, observability: Option<ObservabilityState>, io_driver: Option<IoDriverHandle>, io_cap: Option<Arc<dyn IoCap>>, timer_driver: Option<TimerDriverHandle>, entropy: Option<Arc<dyn EntropySource>>, ) -> Cx<Caps>
Creates a new capability context with optional I/O and timer drivers (internal use).
Sourcepub fn restrict<NewCaps>(&self) -> Cx<NewCaps>where
NewCaps: SubsetOf<Caps>,
pub fn restrict<NewCaps>(&self) -> Cx<NewCaps>where
NewCaps: SubsetOf<Caps>,
Re-type this context to a narrower capability set.
This is a zero-cost type-level restriction. It does not change runtime behavior, but removes access to gated APIs at compile time.
Sourcepub fn logical_now(&self) -> LogicalTime
pub fn logical_now(&self) -> LogicalTime
Returns the current logical time without ticking.
Sourcepub fn logical_tick(&self) -> LogicalTime
pub fn logical_tick(&self) -> LogicalTime
Records a local logical event and returns the updated time.
Sourcepub fn logical_receive(&self, sender_time: &LogicalTime) -> LogicalTime
pub fn logical_receive(&self, sender_time: &LogicalTime) -> LogicalTime
Merges a received logical time and returns the updated time.
Sourcepub fn timer_driver(&self) -> Option<TimerDriverHandle>where
Caps: HasTime,
pub fn timer_driver(&self) -> Option<TimerDriverHandle>where
Caps: HasTime,
Returns a cloned handle to the timer driver, if present.
The timer driver provides access to timer registration for async time
operations like sleep, timeout, and interval. When present, these
operations use the runtime’s timer wheel instead of spawning threads.
§Example
if let Some(timer) = Cx::current().and_then(|cx| cx.timer_driver()) {
let deadline = timer.now() + Duration::from_secs(1);
let handle = timer.register(deadline, waker);
}Sourcepub fn has_timer(&self) -> boolwhere
Caps: HasTime,
pub fn has_timer(&self) -> boolwhere
Caps: HasTime,
Returns true if a timer driver is available.
When true, time operations can use the runtime’s timer wheel. When false, time operations fall back to OS-level timing.
Sourcepub fn io(&self) -> Option<&dyn IoCap>where
Caps: HasIo,
pub fn io(&self) -> Option<&dyn IoCap>where
Caps: HasIo,
Returns the I/O capability, if one is configured.
The I/O capability provides access to async I/O operations. If no capability
is configured, this returns None and I/O operations are not available.
§Capability Model
Asupersync uses explicit capability-based I/O:
- Production runtime configures real I/O capability (via reactor)
- Lab runtime can configure virtual I/O for deterministic testing
- Code that needs I/O must explicitly check for and use this capability
§Example
async fn read_data(cx: &Cx) -> io::Result<Vec<u8>> {
let io = cx.io().ok_or_else(|| {
io::Error::new(io::ErrorKind::Unsupported, "I/O not available")
})?;
// Use io capability...
Ok(vec![])
}Sourcepub fn has_io(&self) -> boolwhere
Caps: HasIo,
pub fn has_io(&self) -> boolwhere
Caps: HasIo,
Returns true if I/O capability is available.
Convenience method to check if I/O operations can be performed.
Sourcepub fn remote(&self) -> Option<&RemoteCap>where
Caps: HasRemote,
pub fn remote(&self) -> Option<&RemoteCap>where
Caps: HasRemote,
Returns the remote capability, if one is configured.
The remote capability authorizes spawning tasks on remote nodes.
Without this capability, spawn_remote
returns RemoteError::NoCapability.
§Capability Model
Remote execution is an explicit capability:
- Production runtime configures remote capability with transport config
- Lab runtime can configure it for deterministic distributed testing
- Code that needs remote spawning must check for this capability
Sourcepub fn has_remote(&self) -> boolwhere
Caps: HasRemote,
pub fn has_remote(&self) -> boolwhere
Caps: HasRemote,
Returns true if the remote capability is available.
Convenience method to check if remote task operations can be performed.
Sourcepub fn register_io<S>(
&self,
source: &S,
interest: Interest,
) -> Result<IoRegistration, Error>
pub fn register_io<S>( &self, source: &S, interest: Interest, ) -> Result<IoRegistration, Error>
Registers an I/O source with the reactor for the given interest.
This method registers a source (such as a socket or file descriptor) with the reactor so that the task can be woken when I/O operations are ready.
§Arguments
source- The I/O source to register (must implementSource)interest- The I/O operations to monitor for (read, write, or both)
§Returns
Returns a IoRegistration handle that represents the active registration.
When dropped, the registration is automatically deregistered from the reactor.
§Errors
Returns an error if:
- No reactor is available (reactor not initialized or not present)
- The reactor fails to register the source
Sourcepub fn task_type(&self) -> Option<String>
pub fn task_type(&self) -> Option<String>
Returns the task type label, if one has been set.
Task types are optional metadata used by adaptive deadline monitoring and metrics to group similar work.
Sourcepub fn set_task_type(&self, task_type: impl Into<String>)
pub fn set_task_type(&self, task_type: impl Into<String>)
Sets a task type label for adaptive monitoring and metrics.
This is intended to be called early in task execution to associate a stable label with the task’s behavior profile.
Sourcepub fn budget(&self) -> Budget
pub fn budget(&self) -> Budget
Returns the current budget.
The budget defines resource limits for this task:
deadline: Absolute time limitpoll_quota: Maximum number of pollscost_quota: Abstract cost unitspriority: Scheduling priority
Frameworks can use the budget to implement request timeouts:
§Example
async fn check_timeout(cx: &Cx) -> Result<(), TimeoutError> {
let budget = cx.budget();
if budget.is_expired() {
return Err(TimeoutError::DeadlineExceeded);
}
Ok(())
}Sourcepub fn is_cancel_requested(&self) -> bool
pub fn is_cancel_requested(&self) -> bool
Returns true if cancellation has been requested.
This is a non-blocking check that queries whether a cancellation signal
has been sent to this task. Unlike checkpoint(), this method does not
return an error - it just reports the current state.
Frameworks should check this periodically during long-running operations to enable graceful shutdown.
§Example
async fn process_items(cx: &Cx, items: Vec<Item>) -> Result<(), Error> {
for item in items {
// Check for cancellation between items
if cx.is_cancel_requested() {
return Err(Error::Cancelled);
}
process(item).await?;
}
Ok(())
}Sourcepub fn checkpoint(&self) -> Result<(), Error>
pub fn checkpoint(&self) -> Result<(), Error>
Checks for cancellation and returns an error if cancelled.
This is a checkpoint where cancellation can be observed. It combines
checking the cancellation flag with returning an error, making it
convenient for use with the ? operator.
In addition to cancellation checking, this method records progress by updating the checkpoint state. This is useful for:
- Detecting stuck/stalled tasks via
checkpoint_state() - Work-stealing scheduler decisions
- Observability and debugging
If the context is currently masked (via masked()), this method
returns Ok(()) even when cancellation is pending, deferring the
cancellation until the mask is released.
§Errors
Returns an Err with kind ErrorKind::Cancelled if cancellation is
pending and the context is not masked.
§Example
async fn do_work(cx: &Cx) -> Result<(), Error> {
// Use checkpoint with ? for concise cancellation handling
cx.checkpoint()?;
expensive_operation().await?;
cx.checkpoint()?;
another_operation().await?;
Ok(())
}Sourcepub fn checkpoint_with(&self, msg: impl Into<String>) -> Result<(), Error>
pub fn checkpoint_with(&self, msg: impl Into<String>) -> Result<(), Error>
Checks for cancellation with a progress message.
This is like checkpoint() but also records a
human-readable message describing the current progress. The message
is stored in the checkpoint state and can be retrieved via
checkpoint_state().
§Errors
Returns an Err with kind ErrorKind::Cancelled if cancellation is
pending and the context is not masked.
§Example
async fn process_batch(cx: &Cx, items: &[Item]) -> Result<(), Error> {
for (i, item) in items.iter().enumerate() {
cx.checkpoint_with(format!("Processing item {}/{}", i + 1, items.len()))?;
process(item).await?;
}
Ok(())
}Sourcepub fn checkpoint_state(&self) -> CheckpointState
pub fn checkpoint_state(&self) -> CheckpointState
Returns a snapshot of the current checkpoint state.
The checkpoint state tracks progress reporting checkpoints:
last_checkpoint: When the last checkpoint was recordedlast_message: The message from the lastcheckpoint_with()callcheckpoint_count: Total number of checkpoints
This is useful for monitoring task progress and detecting stalled tasks.
§Example
fn check_task_health(cx: &Cx) -> bool {
let state = cx.checkpoint_state();
if let Some(last) = state.last_checkpoint {
// Stalled if no checkpoint in 30 seconds
last.elapsed() < Duration::from_secs(30)
} else {
// Never checkpointed, could be stuck
false
}
}Sourcepub fn masked<F, R>(&self, f: F) -> Rwhere
F: FnOnce() -> R,
pub fn masked<F, R>(&self, f: F) -> Rwhere
F: FnOnce() -> R,
Executes a closure with cancellation masked.
While masked, checkpoint() will return Ok(()) even if cancellation
has been requested. This is used for critical sections that must not
be interrupted, such as:
- Completing a two-phase commit
- Flushing buffered data
- Releasing resources in a specific order
Masking can be nested - each call to masked() increments a depth
counter, and cancellation is only observable when depth returns to 0.
§Example
async fn commit_transaction(cx: &Cx, tx: Transaction) -> Result<(), Error> {
// Critical section: must complete even if cancelled
cx.masked(|| {
tx.prepare()?;
tx.commit()?; // Cannot be interrupted here
Ok(())
})
}§Note
Use masking sparingly. Long-masked sections defeat the purpose of responsive cancellation. Prefer short critical sections followed by a checkpoint.
Sourcepub fn trace(&self, message: &str)
pub fn trace(&self, message: &str)
Traces an event for observability.
Trace events are associated with the current task and region, enabling structured observability. In the lab runtime, traces are captured deterministically for replay and debugging.
§Example
async fn process_request(cx: &Cx, request: &Request) -> Response {
cx.trace("Request received");
let result = handle(request).await;
cx.trace("Request processed");
result
}§Note
This is currently a placeholder. The full implementation will write to the trace buffer maintained by the runtime.
Sourcepub fn trace_with_fields(&self, message: &str, fields: &[(&str, &str)])
pub fn trace_with_fields(&self, message: &str, fields: &[(&str, &str)])
Sourcepub fn enter_span(&self, name: &str) -> SpanGuard<Caps>
pub fn enter_span(&self, name: &str) -> SpanGuard<Caps>
Enters a named span, returning a guard that ends the span on drop.
The span forks the current DiagnosticContext, assigning a new
SpanId with the previous span as parent. When the guard is
dropped the original context is restored.
§Example
{
let _guard = cx.enter_span("parse_request");
// ... work inside the span ...
} // span ends hereSourcepub fn set_request_id(&self, id: impl Into<String>)
pub fn set_request_id(&self, id: impl Into<String>)
Sets a request correlation ID on the diagnostic context.
The ID propagates to all log entries and child spans created from this context, enabling end-to-end request tracing.
Sourcepub fn request_id(&self) -> Option<String>
pub fn request_id(&self) -> Option<String>
Returns the current request correlation ID, if set.
Sourcepub fn log(&self, entry: LogEntry)
pub fn log(&self, entry: LogEntry)
Logs a structured entry to the attached collector, if present.
Sourcepub fn diagnostic_context(&self) -> DiagnosticContext
pub fn diagnostic_context(&self) -> DiagnosticContext
Returns a snapshot of the current diagnostic context.
Sourcepub fn set_diagnostic_context(&self, ctx: DiagnosticContext)
pub fn set_diagnostic_context(&self, ctx: DiagnosticContext)
Replaces the current diagnostic context.
Sourcepub fn set_log_collector(&self, collector: LogCollector)
pub fn set_log_collector(&self, collector: LogCollector)
Attaches a log collector to this context.
Sourcepub fn log_collector(&self) -> Option<LogCollector>
pub fn log_collector(&self) -> Option<LogCollector>
Returns the current log collector, if attached.
Sourcepub fn set_trace_buffer(&self, trace: TraceBufferHandle)
pub fn set_trace_buffer(&self, trace: TraceBufferHandle)
Attaches a trace buffer to this context.
Sourcepub fn trace_buffer(&self) -> Option<TraceBufferHandle>
pub fn trace_buffer(&self) -> Option<TraceBufferHandle>
Returns the current trace buffer handle, if attached.
Sourcepub fn entropy(&self) -> &(dyn EntropySource + 'static)where
Caps: HasRandom,
pub fn entropy(&self) -> &(dyn EntropySource + 'static)where
Caps: HasRandom,
Returns the entropy source for this context.
Sourcepub fn random_u64(&self) -> u64where
Caps: HasRandom,
pub fn random_u64(&self) -> u64where
Caps: HasRandom,
Generates a random u64 using the context entropy source.
Sourcepub fn random_bytes(&self, dest: &mut [u8])where
Caps: HasRandom,
pub fn random_bytes(&self, dest: &mut [u8])where
Caps: HasRandom,
Fills a buffer with random bytes using the context entropy source.
Sourcepub fn random_usize(&self, bound: usize) -> usizewhere
Caps: HasRandom,
pub fn random_usize(&self, bound: usize) -> usizewhere
Caps: HasRandom,
Generates a random usize in [0, bound) with rejection sampling.
Sourcepub fn random_bool(&self) -> boolwhere
Caps: HasRandom,
pub fn random_bool(&self) -> boolwhere
Caps: HasRandom,
Generates a random boolean.
Sourcepub fn random_f64(&self) -> f64where
Caps: HasRandom,
pub fn random_f64(&self) -> f64where
Caps: HasRandom,
Generates a random f64 in [0, 1).
Sourcepub fn shuffle<T>(&self, slice: &mut [T])where
Caps: HasRandom,
pub fn shuffle<T>(&self, slice: &mut [T])where
Caps: HasRandom,
Shuffles a slice in place using Fisher-Yates.
Sourcepub fn set_cancel_requested(&self, value: bool)
pub fn set_cancel_requested(&self, value: bool)
Sets the cancellation flag for testing purposes.
This method allows tests to simulate cancellation signals. It sets the
cancel_requested flag, which will cause subsequent checkpoint() calls
to return an error (unless masked).
§Example
use asupersync::Cx;
let cx = Cx::for_testing();
assert!(cx.checkpoint().is_ok());
cx.set_cancel_requested(true);
assert!(cx.checkpoint().is_err());§Note
This API is intended for testing only. In production, cancellation signals are propagated by the runtime through the task tree.
Sourcepub fn cancel_with(&self, kind: CancelKind, message: Option<&'static str>)
pub fn cancel_with(&self, kind: CancelKind, message: Option<&'static str>)
Cancels this context with a detailed reason.
This is the preferred method for initiating cancellation, as it provides complete attribution information. The reason includes:
- The kind of cancellation (e.g., User, Timeout, Deadline)
- An optional message explaining the cancellation
- Origin region and task information (automatically set)
§Arguments
kind- The type of cancellation being initiatedmessage- An optional human-readable message explaining why
§Example
use asupersync::{Cx, types::CancelKind};
let cx = Cx::for_testing();
cx.cancel_with(CancelKind::User, Some("User pressed Ctrl+C"));
assert!(cx.is_cancel_requested());
if let Some(reason) = cx.cancel_reason() {
assert_eq!(reason.kind, CancelKind::User);
}§Note
This method only sets the local cancellation flag. In a real runtime,
cancellation propagates through the region tree via cancel_request().
Sourcepub fn cancel_fast(&self, kind: CancelKind)
pub fn cancel_fast(&self, kind: CancelKind)
Cancels without building a full attribution chain (performance-critical path).
Use this when attribution isn’t needed and minimizing allocations is important. The cancellation reason will have minimal attribution (kind + region only).
§Performance
This method avoids:
- Message string allocation
- Cause chain allocation
- Timestamp lookup
Use cancel_with when you need full attribution for debugging.
§Example
use asupersync::{Cx, types::CancelKind};
let cx = Cx::for_testing();
// Fast cancellation - no allocation
cx.cancel_fast(CancelKind::RaceLost);
assert!(cx.is_cancel_requested());Sourcepub fn cancel_reason(&self) -> Option<CancelReason>
pub fn cancel_reason(&self) -> Option<CancelReason>
Gets the cancellation reason if this context is cancelled.
Returns None if the context is not cancelled, or Some(reason) if
cancellation has been requested. The returned reason includes full
attribution (kind, origin region, origin task, timestamp, cause chain).
§Example
use asupersync::{Cx, types::CancelKind};
let cx = Cx::for_testing();
assert!(cx.cancel_reason().is_none());
cx.cancel_with(CancelKind::Timeout, Some("request timeout"));
if let Some(reason) = cx.cancel_reason() {
assert_eq!(reason.kind, CancelKind::Timeout);
println!("Cancelled: {:?}", reason.kind);
}Sourcepub fn cancel_chain(&self) -> impl Iterator<Item = CancelReason>
pub fn cancel_chain(&self) -> impl Iterator<Item = CancelReason>
Iterates through the full cancellation cause chain.
The first element is the immediate reason, followed by parent causes in order (immediate -> root). This is useful for understanding the full propagation path of a cancellation.
Returns an empty iterator if the context is not cancelled.
§Example
use asupersync::{Cx, types::{CancelKind, CancelReason}};
let cx = Cx::for_testing();
// Create a chained reason: ParentCancelled -> Deadline
let root_cause = CancelReason::deadline();
let chained = CancelReason::parent_cancelled().with_cause(root_cause);
// Set it via internal method for testing
cx.set_cancel_reason(chained);
let chain: Vec<_> = cx.cancel_chain().collect();
assert_eq!(chain.len(), 2);
assert_eq!(chain[0].kind, CancelKind::ParentCancelled);
assert_eq!(chain[1].kind, CancelKind::Deadline);Sourcepub fn root_cancel_cause(&self) -> Option<CancelReason>
pub fn root_cancel_cause(&self) -> Option<CancelReason>
Gets the root cause of cancellation.
This is the original trigger that initiated the cancellation, regardless
of how many parent regions the cancellation propagated through. For example,
if a grandchild task was cancelled due to a parent timeout, root_cancel_cause()
returns the original Timeout reason, not the intermediate ParentCancelled reasons.
Returns None if the context is not cancelled.
§Example
use asupersync::{Cx, types::{CancelKind, CancelReason}};
let cx = Cx::for_testing();
// Simulate a deep cancellation chain
let deadline = CancelReason::deadline();
let parent1 = CancelReason::parent_cancelled().with_cause(deadline);
let parent2 = CancelReason::parent_cancelled().with_cause(parent1);
cx.set_cancel_reason(parent2);
// Root cause is the original Deadline, not ParentCancelled
if let Some(root) = cx.root_cancel_cause() {
assert_eq!(root.kind, CancelKind::Deadline);
}Sourcepub fn cancelled_by(&self, kind: CancelKind) -> bool
pub fn cancelled_by(&self, kind: CancelKind) -> bool
Checks if cancellation was due to a specific kind.
This checks the immediate reason only, not the cause chain. For example,
if a task was cancelled with ParentCancelled due to an upstream timeout,
cancelled_by(CancelKind::ParentCancelled) returns true but
cancelled_by(CancelKind::Timeout) returns false.
Use any_cause_is() to check the full cause chain.
§Example
use asupersync::{Cx, types::CancelKind};
let cx = Cx::for_testing();
cx.cancel_with(CancelKind::User, Some("manual cancel"));
assert!(cx.cancelled_by(CancelKind::User));
assert!(!cx.cancelled_by(CancelKind::Timeout));Sourcepub fn any_cause_is(&self, kind: CancelKind) -> bool
pub fn any_cause_is(&self, kind: CancelKind) -> bool
Checks if any cause in the chain is a specific kind.
This searches the entire cause chain, from the immediate reason to the root cause. This is useful for checking if a specific condition (like a timeout) anywhere in the hierarchy caused this cancellation.
§Example
use asupersync::{Cx, types::{CancelKind, CancelReason}};
let cx = Cx::for_testing();
// Grandchild cancelled due to parent timeout
let timeout = CancelReason::timeout();
let parent_cancelled = CancelReason::parent_cancelled().with_cause(timeout);
cx.set_cancel_reason(parent_cancelled);
// Immediate reason is ParentCancelled, but timeout is in the chain
assert!(cx.cancelled_by(CancelKind::ParentCancelled));
assert!(!cx.cancelled_by(CancelKind::Timeout)); // immediate only
assert!(cx.any_cause_is(CancelKind::Timeout)); // searches chain
assert!(cx.any_cause_is(CancelKind::ParentCancelled)); // also in chainSourcepub fn set_cancel_reason(&self, reason: CancelReason)
pub fn set_cancel_reason(&self, reason: CancelReason)
Sets the cancellation reason (for testing purposes).
This method allows tests to set a specific cancellation reason, including
complex cause chains. It sets both the cancel_requested flag and the
cancel_reason.
§Example
use asupersync::{Cx, types::{CancelKind, CancelReason}};
let cx = Cx::for_testing();
// Create a chained reason for testing
let root = CancelReason::deadline();
let chained = CancelReason::parent_cancelled().with_cause(root);
cx.set_cancel_reason(chained);
assert!(cx.is_cancel_requested());
assert_eq!(cx.cancel_reason().unwrap().kind, CancelKind::ParentCancelled);Sourcepub async fn race<T>(
&self,
futures: Vec<Pin<Box<dyn Future<Output = T> + Send>>>,
) -> Result<T, JoinError>
pub async fn race<T>( &self, futures: Vec<Pin<Box<dyn Future<Output = T> + Send>>>, ) -> Result<T, JoinError>
Races multiple futures, waiting for the first to complete.
This method is used by the race! macro. It runs the provided futures
concurrently (inline, not spawned) and returns the result of the first
one to complete. Losers are dropped (cancelled).
§Cancellation vs Draining
This method drops the losing futures, which cancels them. However,
unlike Scope::race, it does not await the
losers to ensure they have fully cleaned up (“drained”).
If you are racing TaskHandles and require
the “Losers are drained” invariant (parent waits for losers to terminate),
use Scope::race or
Scope::race_all instead.
Sourcepub async fn race_named<T>(
&self,
futures: Vec<(&'static str, Pin<Box<dyn Future<Output = T> + Send>>)>,
) -> Result<T, JoinError>
pub async fn race_named<T>( &self, futures: Vec<(&'static str, Pin<Box<dyn Future<Output = T> + Send>>)>, ) -> Result<T, JoinError>
Races multiple named futures.
Similar to race, but accepts names for tracing purposes.
§Cancellation vs Draining
This method drops the losing futures, which cancels them. However,
unlike Scope::race, it does not await the
losers to ensure they have fully cleaned up (“drained”).
Sourcepub async fn race_timeout<T>(
&self,
duration: Duration,
futures: Vec<Pin<Box<dyn Future<Output = T> + Send>>>,
) -> Result<T, JoinError>where
Caps: HasTime,
pub async fn race_timeout<T>(
&self,
duration: Duration,
futures: Vec<Pin<Box<dyn Future<Output = T> + Send>>>,
) -> Result<T, JoinError>where
Caps: HasTime,
Races multiple futures with a timeout.
If the timeout expires before any future completes, returns a cancellation error.
§Cancellation vs Draining
This method drops the losing futures (or all futures on timeout), which cancels them. However, it does not await the losers to ensure they have fully cleaned up (“drained”).
Sourcepub async fn race_timeout_named<T>(
&self,
duration: Duration,
futures: Vec<(&'static str, Pin<Box<dyn Future<Output = T> + Send>>)>,
) -> Result<T, JoinError>where
Caps: HasTime,
pub async fn race_timeout_named<T>(
&self,
duration: Duration,
futures: Vec<(&'static str, Pin<Box<dyn Future<Output = T> + Send>>)>,
) -> Result<T, JoinError>where
Caps: HasTime,
Races multiple named futures with a timeout.
§Cancellation vs Draining
This method drops the losing futures (or all futures on timeout), which cancels them. However, it does not await the losers to ensure they have fully cleaned up (“drained”).
Sourcepub fn scope(&self) -> Scope<'static>
pub fn scope(&self) -> Scope<'static>
Creates a Scope bound to this context’s region.
The returned Scope can be used to spawn tasks, create child regions,
and register finalizers. All spawned tasks will be owned by this
context’s region.
§Example
// Using the scope! macro (recommended):
scope!(cx, {
let handle = scope.spawn(|cx| async { 42 });
handle.await
});
// Manual scope creation:
let scope = cx.scope();
// Use scope for spawning...§Note
In Phase 0, this creates a scope bound to the current region. In later
phases, the scope! macro will create child regions with proper
quiescence guarantees.
Source§impl Cx
impl Cx
Sourcepub fn for_testing() -> Cx
pub fn for_testing() -> Cx
Creates a capability context for testing purposes.
This constructor creates a Cx with default IDs and an infinite budget, suitable for unit and integration tests. The resulting context is fully functional but not connected to a real runtime.
§Example
use asupersync::Cx;
let cx = Cx::for_testing();
assert!(!cx.is_cancel_requested());
assert!(cx.checkpoint().is_ok());§Note
This API is intended for testing only. Production code should receive Cx instances from the runtime, not construct them directly.
Sourcepub fn for_testing_with_budget(budget: Budget) -> Cx
pub fn for_testing_with_budget(budget: Budget) -> Cx
Creates a test-only capability context with a specified budget.
Similar to Self::for_testing() but allows specifying a custom budget
for testing timeout behavior.
§Example
use asupersync::{Cx, Budget, Time};
// Create a context with a 30-second deadline
let cx = Cx::for_testing_with_budget(
Budget::new().with_deadline(Time::from_secs(30))
);§Note
This API is intended for testing only. Production code should receive Cx instances from the runtime, not construct them directly.
Sourcepub fn for_testing_with_io() -> Cx
pub fn for_testing_with_io() -> Cx
Creates a test-only capability context with lab I/O capability.
This constructor creates a Cx with a LabIoCap for testing I/O code paths
without performing real I/O.
§Example
use asupersync::Cx;
let cx = Cx::for_testing_with_io();
assert!(cx.has_io());
assert!(!cx.io().unwrap().is_real_io());§Note
This API is intended for testing only.
Sourcepub fn for_request_with_budget(budget: Budget) -> Cx
pub fn for_request_with_budget(budget: Budget) -> Cx
Creates a request-scoped capability context with a specified budget.
This is intended for production request handling that needs unique task/region identifiers outside the scheduler.
Sourcepub fn for_request() -> Cx
pub fn for_request() -> Cx
Creates a request-scoped capability context with an infinite budget.