arty 0.5.0

Single-threaded, thread-aware application runtime.
Documentation
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

//! Runtime construction, configuration, and task capabilities.
//!
//! Use [`Runtime`] to run async work from synchronous code and control
//! when workers stop. [`Runtime::new`] starts the default configuration;
//! [`Runtime::builder`] lets you choose workers, blocking pools, clocks, and
//! a telemetry sink before they start.
//!
//! Each task receives [`Builtins`](crate::task::Builtins) with its worker's
//! scheduler and clock. [`Runtime::scheduler`] lets the runtime place new
//! tasks, while [`Builtins::scheduler`](crate::task::Builtins::scheduler)
//! keeps children on their parent's worker. [`RuntimeOperations`] can request
//! shutdown without consuming the runtime owner.
//!
//! Keep the runtime owner alive until required work completes. Shutdown cancels
//! pending tasks and waits for blocking callbacks that have already started;
//! keeping a scheduler does not keep the runtime running.
//!
//! # Examples
//!
//! Let the entry-point attribute manage the runtime's lifetime:
//!
//! ```
//! # #[cfg(all(feature = "macros", feature = "rt"))]
//! #[arty::main]
//! async fn main(cx: arty::task::Builtins) -> Result<(), arty::task::JoinError> {
//!     assert_eq!(cx.scheduler().spawn(async |_| 42).await?, 42);
//!     Ok(())
//! }
//! # #[cfg(not(all(feature = "macros", feature = "rt")))] fn main() {}
//! ```
//!
//! See the [configuration](crate::documentation::configuration) and
//! [shutdown](crate::documentation::shutdown) guides for more.

pub(crate) mod blocking_worker;
mod bootstrap;
mod builder;
pub(crate) mod config;
pub(crate) mod dispatch;
mod error;
mod handle;
mod operations;
pub(crate) mod telemetry;
pub(crate) mod thread;
mod worker;

#[doc(inline)]
pub use builder::RuntimeBuilder;
#[doc(inline)]
pub use config::{BlockingPoolPolicy, WorkersPolicy};
#[doc(inline)]
pub use error::Error;
#[doc(inline)]
pub use handle::Runtime;
#[doc(inline)]
pub use operations::RuntimeOperations;

/// Implementation details for the runtime entry-point macros.
#[cfg(feature = "macros")]
pub mod __private {
    #[cfg(any(test, feature = "test-util"))]
    pub use crate::time::ClockControl;

    /// Preserves an entry point's return type while reporting root-task failure.
    ///
    /// # Panics
    ///
    /// Resumes a captured root-task panic or starts an unwind carrying the runtime failure.
    pub fn resume_error(error: super::Error) -> ! {
        match error.into_source().downcast::<crate::task::JoinError>() {
            Ok(error) if error.is_panic() => {
                std::panic::resume_unwind(error.into_panic().expect("the join error was checked as a panic"));
            }
            Ok(_) => std::panic::resume_unwind(Box::new("runtime is shutting down")),
            Err(error) => std::panic::resume_unwind(Box::new(error.to_string())),
        }
    }

    #[cfg(test)]
    #[cfg_attr(coverage_nightly, coverage(off))]
    mod tests {
        #[test]
        fn non_join_failure_preserves_its_diagnostic_payload() {
            let payload = std::panic::catch_unwind(|| {
                super::resume_error(crate::runtime::Error::new("runtime control failed"));
            })
            .unwrap_err();
            assert_eq!(*payload.downcast::<String>().unwrap(), "runtime control failed");
        }
    }
}