Skip to main content

Executor

Struct Executor 

Source
pub struct Executor { /* private fields */ }
Expand description

The async task executor for a single thread.

Its purpose is to continuously poll tasks to ensure the tasks make progress, as well as to provide highly efficient task wake-up services for when tasks are unblocked by the asynchronous operations they are waiting on.

The executor is single-threaded and does not own or manage threads - it is up to the caller to decide what thread to run it on and what else to do on that thread. This caller is intended to be the Arty Runtime, which combines async task execution, I/O and other fundamental capabilities into a single package of features offered to each thread in an Arty-based application.

§Reentrancy and mutability

The executor calls out into external code (futures of the tasks it executes), which may call back into specific methods on the executor (e.g. to enqueue more tasks). Therefore, it operates using internal mutability.

Not every method can be called in a reentrant manner - see API documentation of individual methods for details.

§Integration

The executor is designed to be exclusively owned and operated by the runtime that it services. Instances of TaskSet obtained from tasks() may be shared to user code to facilitate registering additional tasks with the executor. This may be done even from within the futures of existing tasks running on the same executor.

The runtime that owns the executor is expected to call execute_cycle() as part of its main event loop. When exactly the next call should take place is determined by the CycleOutcome returned from each call.

The owner may, at any point (regardless of what any registered tasks are doing), initiate the shutdown process. Any active tasks are aborted and their futures dropped when shutdown starts. Submissions through remaining TaskSets resolve to JoinError.

§Shutdown process

Graceful shutdown lets the owner observe when cancellation is complete:

  1. Call begin_shutdown() to start the shutdown process.
  2. Keep calling execute_cycle() until it returns CycleOutcome::Shutdown.
  3. Drop the executor when convenient.

Dropping the executor without this sequence is also safe and synchronously cancels remaining tasks. Retained join handles and task wakers own independent pooled metadata, so they may outlive the executor and report shutdown or become inert respectively.

§Process termination

Plain executor tasks terminate the process if their futures panic. Runtime integrations can register a remote result target that receives captured panics without unwinding the worker.

Implementations§

Source§

impl Executor

Source

pub fn builder() -> ExecutorBuilder

Starts building a new instance of Executor.

Source

pub fn tasks(&self) -> TaskSet

Creates a new handle to the set of tasks registered with the executor. You can use this to register additional tasks.

Source

pub fn has_tasks(&self) -> bool

Returns whether the executor still owns any registered tasks.

Completed tasks stop counting during the cycle that observes their completion. Join handles and retained wakers do not count as tasks and may remain alive after this returns false.

Source

pub fn execute_cycle(&self) -> CycleOutcome

Executes one processing cycle to progress registered tasks.

More work may remain after a cycle completes. The return value will indicate whether the executor believes it has more work to do, in which case it should be called again as soon as possible.

This function is not safe to call in a reentrant manner - only the owner may call it in an exclusive context.

§Panics

Panics if called in a reentrant manner (e.g. from external code called from within execute_cycle()).

Source

pub fn begin_shutdown(&self)

Starts the executor shutdown process.

The next execute_cycle() returns CycleOutcome::Shutdown after releasing cancelled task storage. Retained join handles resolve independently and do not delay shutdown.

This function is not safe to call in a reentrant manner - only the owner may call it in an exclusive context.

§Panics

Panics if called in a reentrant manner (e.g. from external code called from within execute_cycle()).

Trait Implementations§

Source§

impl Debug for Executor

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for Executor

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.