pub struct Scope { /* private fields */ }
Expand description
A scope for managing async tasks. This scope is cancelled when dropped.
Scopes are how fuchsia-async implements structured concurrency. Every task is spawned on a scope, and runs until either the task completes or the scope is cancelled. In addition to owning tasks, scopes may own child scopes, forming a nested structure.
Scopes are usually joined or cancelled when the owning code is done with them. This makes it easier to reason about when a background task might still be running. Note that in multithreaded contexts it is safer to cancel and await a scope explicitly than to drop it, because the destructor is not synchronized with other threads that might be running a task.
Task::spawn
and related APIs spawn on the root scope
of the executor. New code is encouraged to spawn directly on scopes instead,
passing their handles as a way of documenting when a function might spawn
tasks that run in the background and reasoning about their side effects.
§Scope lifecycle
When a scope is created it is open, meaning it accepts new tasks. Scopes are closed when one of the following happens:
- When
close()
is called. - When the scope is cancelled or dropped, the scope is closed immediately.
- When the scope is joined and all tasks complete, the scope is closed before the join future resolves.
When a scope is closed it no longer accepts tasks. Tasks spawned on the
scope are dropped immediately, and their Task
or
JoinHandle
futures never resolve. This applies
transitively to all child scopes. Closed scopes cannot currently be
reopened.
Scopes can also be detached, in which case they are never closed, and run until the completion of all tasks.
Implementations§
Source§impl Scope
impl Scope
Sourcepub fn current() -> ScopeHandle
pub fn current() -> ScopeHandle
Sourcepub fn global() -> ScopeHandle
pub fn global() -> ScopeHandle
Get the global scope of the executor.
This can be used to spawn tasks that live as long as the executor. Usually, this means until the end of the program or test. This should only be done for tasks where this is expected. If in doubt, spawn on a shorter lived scope instead.
In code that uses scopes, you are strongly encouraged to use this API
instead of the spawn APIs on Task
.
All scopes are descendants of the global scope.
§Panics
May panic if not called in the context of an executor (e.g. within a
call to run
).
Sourcepub fn to_handle(&self) -> ScopeHandle
pub fn to_handle(&self) -> ScopeHandle
Create a ScopeHandle
that may be used to spawn tasks on this scope.
This is a shorthand for scope.as_handle().clone()
.
Scope holds a ScopeHandle
and implements Deref to make its methods
available. Note that you should not call scope.clone()
, even though
the compiler allows it due to the Deref impl. Call this method instead.
Sourcepub fn as_handle(&self) -> &ScopeHandle
pub fn as_handle(&self) -> &ScopeHandle
Get a reference to a ScopeHandle
that may be used to spawn tasks on
this scope.
Scope holds a ScopeHandle
and implements Deref to make its methods
available. If you have a Scope
but need a &ScopeHandle
, prefer
calling this method over the less readable &*scope
.
Sourcepub fn join(self) -> Join ⓘ
pub fn join(self) -> Join ⓘ
Wait for all tasks in the scope and its children to complete.
New tasks will be accepted on the scope until every task completes and this future resolves.
Note that you can await a scope directly because it implements
IntoFuture
. scope.join().await
is a more explicit form of
scope.await
.
Sourcepub fn close(self) -> Join ⓘ
pub fn close(self) -> Join ⓘ
Stop accepting new tasks on the scope. Returns a future that waits for every task on the scope to complete.
Sourcepub fn cancel(self) -> impl Future<Output = ()>
pub fn cancel(self) -> impl Future<Output = ()>
Cancel all tasks in the scope and its children recursively.
Once the returned future resolves, no task on the scope will be polled again.
When a scope is cancelled it immediately stops accepting tasks. Handles of tasks spawned on the scope will pend forever.
Dropping the Scope
object is equivalent to calling this method and
discarding the returned future. Awaiting the future is preferred because
it eliminates the possibility of a task poll completing on another
thread after the scope object has been dropped, which can sometimes
result in surprising behavior.
Methods from Deref<Target = ScopeHandle>§
Sourcepub fn spawn(
&self,
future: impl Future<Output = ()> + Send + 'static,
) -> JoinHandle<()> ⓘ
pub fn spawn( &self, future: impl Future<Output = ()> + Send + 'static, ) -> JoinHandle<()> ⓘ
Spawn a new task on the scope.
Sourcepub fn spawn_local(
&self,
future: impl Future<Output = ()> + 'static,
) -> JoinHandle<()> ⓘ
pub fn spawn_local( &self, future: impl Future<Output = ()> + 'static, ) -> JoinHandle<()> ⓘ
Spawn a new task on the scope of a thread local executor.
NOTE: This is not supported with a SendExecutor
and will cause a runtime panic. Use ScopeHandle::spawn
instead.
Sourcepub fn compute<T: Send + 'static>(
&self,
future: impl Future<Output = T> + Send + 'static,
) -> Task<T> ⓘ
pub fn compute<T: Send + 'static>( &self, future: impl Future<Output = T> + Send + 'static, ) -> Task<T> ⓘ
Like spawn
, but for tasks that return a result.
NOTE: Unlike spawn
, when tasks are dropped, the future will be
cancelled.
Sourcepub fn compute_local<T: 'static>(
&self,
future: impl Future<Output = T> + 'static,
) -> Task<T> ⓘ
pub fn compute_local<T: 'static>( &self, future: impl Future<Output = T> + 'static, ) -> Task<T> ⓘ
Like spawn
, but for tasks that return a result.
NOTE: Unlike spawn
, when tasks are dropped, the future will be
cancelled.
NOTE: This is not supported with a SendExecutor
and will cause a runtime panic. Use ScopeHandle::spawn
instead.
Sourcepub fn close(&self)
pub fn close(&self)
Stop the scope from accepting new tasks.
Note that unlike Scope::close
, this does not return a future that
waits for all tasks to complete. This could lead to resource leaks
because it is not uncommon to access a TaskGroup from a task running on
the scope itself. If such a task were to await a future returned by this
method it would suspend forever waiting for itself to complete.
Sourcepub async fn on_no_tasks(&self)
pub async fn on_no_tasks(&self)
Wait for there to be no tasks. This is racy: as soon as this returns it is possible for another task to have been spawned on this scope.
Trait Implementations§
Source§impl Borrow<ScopeHandle> for Scope
impl Borrow<ScopeHandle> for Scope
Source§fn borrow(&self) -> &ScopeHandle
fn borrow(&self) -> &ScopeHandle
Source§impl Drop for Scope
impl Drop for Scope
Cancel the scope and all of its tasks. Prefer using the Scope::cancel
or Scope::join
methods.