future_handles 0.2.0

A library crate to complete futures via handles
Documentation
//! # Overview
//!
//! A crate to complete futures via a remote handle.
//!
//! Although it's design shouldn't restrain `future_handles` use cases, this crate was primarily
//! conceived to bridge asynchronous functions running callbacks at competition with rust's
//! async/await paradigm.
//!
//! # Features
//! - No locking overhead for single-threaded environments.
//! - Optional thread-safety with spin-locks.
//! - Futures always complete with an error if the handle is dropped.
//! - Both channel-like and scoped APIs.
//!
//! ## Examples
//!
//! Channel-like API:
//! ```rust
//! # use future_handles::unsync;
//! async fn func() -> Option<u32> {
//!     let (future, handle) = unsync::create();
//!
//!     func_with_callback(|res| {
//!         handle.complete(res);
//!     });
//!
//!     future.await.ok()
//! }
//! # fn func_with_callback<F>(func: F)
//! #    where F: FnOnce(u32) {
//! #    func(1);
//! # }
//! ```
//!
//! Scoped API:
//! ```rust
//! # use future_handles::unsync;
//! async fn func() -> Option<u32> {
//!     let future = unsync::scoped(|handle| {
//!         func_with_callback(|res| {
//!             handle.complete(res);
//!         });
//!     });
//!
//!     future.await.ok()
//! }
//! # fn func_with_callback<F>(func: F)
//! #    where F: FnOnce(u32) {
//! #    func(1);
//! # }
//! ```
//!
//! ## Thread safety
//!
//! This crate comes a non thread-safe [`unsync`] implementation by default. To make the [`sync`]
//! thread-safe implementation available, enable the `sync` feature.
//!
//! [`unsync`]: unsync
//! [`sync`]: sync
//!
//! # Danger!
//!
//! Do **NOT** do this!
//! ```rust
//! # use future_handles::unsync;
//! async fn func() {
//!     let (future, handle) = unsync::create();
//!
//!     // Start awaiting here...
//!     future.await.unwrap();
//!     // Now we'll never be able set the result!
//!     handle.complete(1);
//! }
//! ```
//! Awaiting a `CompletableFuture` before setting the result or dropping the associated
//! `CompleteHandle` will cause a **deadlock**!

// Enable nightly feature doc_cfg.
#![cfg_attr(docsrs, feature(doc_cfg))]

mod state;
#[cfg(feature = "sync")]
#[cfg_attr(docsrs, doc(cfg(feature = "sync")))]
pub mod sync;
pub mod unsync;

use thiserror::Error;

/// The error returned by `CompletableFuture`s.
#[derive(Error, Debug)]
pub enum HandleError {
    /// The `CompleteHandle` has been dropped before setting a value as result.
    #[error("the completer has been dropped before it was assigned a value")]
    DroppedBeforeComplete,
}

/// A convenience type to wrap a [`HandleError`] in a [`Result`].
///
/// [`HandleError`]: crate::HandleError
/// [`Result`]: std::result::Result
pub type HandleResult<T> = Result<T, HandleError>;