1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//! Infrastructure for integrating time primitives into async runtimes.
//!
//! This module provides the necessary components to bridge time-based operations
//! with async runtime execution. The primary workflow involves:
//!
//! 1. Start with an [`InactiveClock`] that can be safely moved across threads
//! 2. Activate it using [`InactiveClock::activate`] to get a [`Clock`] and [`ClockDriver`]
//! 3. Use the [`ClockDriver`] to periodically advance timers in your runtime loop
//! 4. Use the [`Clock`] for time operations like creating timers and measuring time
//!
//! # Integration with Runtimes
//!
//! Different runtime architectures can integrate this module as follows:
//!
//! ## Thread-per-core Runtimes
//!
//! In thread-per-core architectures, each thread should own an isolated clock with its own
//! timer storage. This eliminates cross-thread lock contention and scales linearly.
//!
//! The pattern is to clone the [`InactiveClock`], relocate each clone to its target thread
//! using [`ThreadAware::relocate`], and then activate:
//!
//! ```rust
//! # use thread_aware::ThreadAware;
//! # use thread_aware::affinity::pinned_affinities;
//! # use tick::runtime::InactiveClock;
//! # let affinities = pinned_affinities(&[1, 1]);
//! let root = InactiveClock::default();
//!
//! // Clone and relocate to each thread's affinity
//! let mut inactive_1 = root.clone();
//! inactive_1.relocate(Some(affinities[0]), affinities[0]);
//! let mut inactive_2 = root;
//! inactive_2.relocate(Some(affinities[1]), affinities[1]);
//!
//! // On thread 1: activate and drive timers independently
//! let (clock_1, driver_1) = inactive_1.activate();
//!
//! // On thread 2: activate and drive timers independently
//! let (clock_2, driver_2) = inactive_2.activate();
//! ```
//!
//! After relocation, each thread's clock and driver operate on an independent set of timers.
//! Timers registered on `clock_1` are only visible to `driver_1`, and the other way around. Each driver
//! must be advanced independently by its owning thread.
//!
//! ## Multi-threaded Runtimes
//!
//! In multi-threaded runtimes where tasks may run on any thread, activate once and share the
//! clock across threads. The driver should be kept on a dedicated thread or task for timer
//! advancement:
//!
//! ```rust
//! # use tick::runtime::InactiveClock;
//! let (clock, driver) = InactiveClock::default().activate();
//!
//! // Share `clock` across threads (it is Clone + Send + Sync)
//! // Keep `driver` on a single thread to advance timers
//! ```
//!
//! [`Clock`]: crate::Clock
//! [`InactiveClock::activate`]: InactiveClock::activate
//! [`ThreadAware::relocate`]: thread_aware::ThreadAware::relocate
pub use ClockDriver;
pub use ClockGone;
pub use ;