pub struct Scope { /* private fields */ }
Expand description
A scope for managing async tasks. This scope is aborted 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 or aborted. 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 aborted or dropped, the scope is closed immediately.
- When the scope is cancelled, the scope is closed when all active guards are dropped.
- 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 new_with_name(name: impl Into<String>) -> Scope
pub fn new_with_name(name: impl Into<String>) -> 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 new_child_with_name(&self, name: impl Into<String>) -> Scope
pub fn new_child_with_name(&self, name: impl Into<String>) -> Scope
Create a child scope with a name.
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) -> Join ⓘ
pub fn cancel(self) -> Join ⓘ
Cancel all tasks cooperatively in the scope and its children recursively.
cancel
first gives a chance to all child tasks (including tasks of
child scopes) to shutdown cleanly if they’re holding on to a
ScopeActiveGuard
. Once no child tasks are holding on to guards, then
cancel
behaves like Scope::abort
, dropping all tasks and stopping
them from running at the next yield point. A ScopeActiveGuard
provides a cooperative cancellation signal that is triggered by this
call, see its documentation for more details.
Once the returned future resolves, no task on the scope will be polled again.
Cancelling a scope does not immediately prevent new tasks from being
accepted. New tasks are accepted as long as there are
ScopeActiveGuard
s for this scope.
Sourcepub fn abort(self) -> impl Future<Output = ()>
pub fn abort(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. Unlike Scope::cancel
, this doesn’t send a cooperative
cancellation signal to tasks or child scopes.
When a scope is aborted 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 new_child_with_name(&self, name: impl Into<String>) -> Scope
pub fn new_child_with_name(&self, name: impl Into<String>) -> Scope
Create a child scope.
Sourcepub fn spawn(&self, future: impl Spawnable<Output = ()>) -> JoinHandle<()> ⓘ
pub fn spawn(&self, future: impl Spawnable<Output = ()>) -> 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 Spawnable<Output = T> + Send + 'static,
) -> Task<T> ⓘ
pub fn compute<T: Send + 'static>( &self, future: impl Spawnable<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 fn active_guard(&self) -> Option<ScopeActiveGuard>
pub fn active_guard(&self) -> Option<ScopeActiveGuard>
Retrieves a ScopeActiveGuard
for this scope.
Note that this may fail if cancellation has already started for this scope. In that case, the caller must assume any tasks from this scope may be dropped at any yield point.
Creating a ScopeActiveGuard
is substantially more expensive than
just polling it, so callers should maintain the returned guard when
success is observed from this call for best performance.
See Scope::cancel
for details on cooperative cancellation behavior.
Sourcepub fn is_cancelled(&self) -> bool
pub fn is_cancelled(&self) -> bool
Returns true if the scope has been signaled to exit via
Scope::cancel
or Scope::abort
.
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
Abort the scope and all of its tasks. Prefer using the Scope::abort
or Scope::join
methods.
impl Drop for Scope
Abort the scope and all of its tasks. Prefer using the Scope::abort
or Scope::join
methods.