operation_queue/lib.rs
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5//! This crate contains the queueing logic for asynchronous operations.
6//!
7//! It also contains helpers for synchronizing operations such as error handling
8//! across futures, in the [`line_token`] module.
9//!
10//! # The operation queue
11//!
12//! The queueing of operations is handled by the [`OperationQueue`] struct. It
13//! runs a given number of parallel runners, to which it dispatches operations
14//! on a "first come, first served" basis.
15//!
16//! An operation is a data structure that implements the [`QueuedOperation`]
17//! trait, and is started by the queue calling its `perform` method. Because
18//! this method is asynchronous, thus breaking [dyn compatibility], another
19//! trait that is dyn-compatible ([`ErasedQueuedOperation`]) is used by the
20//! queue. However, `ErasedQueuedOperation` is implemented by any type that
21//! implements `QueuedOperation`, so consumers usually don't need to bother with
22//! it.
23//!
24//! [`OperationQueue`] is runtime-agnostic, meaning it is not designed to work
25//! only with a specific asynchronous runtime. However, it still needs to spawn
26//! a task for each of its runners. This is why [`OperationQueue::new`] takes a
27//! function as its sole argument, which is given the future for a runner's
28//! loop. For example, creating a new queue with the `tokio` crate could look
29//! like this:
30//!
31//! ```
32//! # use operation_queue::OperationQueue;
33//! let queue = OperationQueue::new(|fut| {
34//! let _ = tokio::task::spawn_local(fut);
35//! });
36//! ```
37//!
38//! The queue is started by [`OperationQueue::start`], and stopped by
39//! [`OperationQueue::stop`]. When starting the queue, the number of runners
40//! provided as the function's argument are created and started. A runner is a
41//! small stateful `struct` with an infinite asynchronous loop. Upon stopping,
42//! the queue terminates and clears all current runners. Note that, once
43//! stopped, a queue cannot be started again.
44//!
45//! Queuing operations is done with [`OperationQueue::enqueue`]. The operation
46//! is pushed to the back of the queue, and will be performed whenenever the
47//! previous operations have also been performed and a runner becomes available.
48//!
49//! # Multithreading
50//!
51//! In order to maintain compatibility with the current Thunderbird code-base,
52//! neither the operation queue's runner, nor the synchronization helpers in the
53//! [`line_token`] module, can be sent between threads. This is something we
54//! plan to address in the future.
55//!
56//! [dyn compatibility]:
57//! <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
58
59#[cfg(feature = "line_token")]
60pub mod line_token;
61
62// The queue is the main feature from this crate, so expose it at the top-level.
63mod error;
64mod operation_queue;
65pub use error::*;
66pub use operation_queue::*;