async_liveliness_monitor/lib.rs
1use std::sync::Arc;
2
3pub mod support;
4use support::{AtomicInstant, LivelinessMonitorFuture};
5
6/// A liveliness monitor for asynchronous runtimes.
7///
8/// Its only constructor ([`LivelinessMonitor::start()`]) returns it wrapped in an [`Arc`] with strong count 1.
9/// Should that strong count reach 0 (due to dropping all the clones you may have made of that [`Arc`], or by
10/// using [`Arc::try_unwrap()`]), the associated task spawned in your runtime will end next time upon its next
11/// scheduling.
12#[non_exhaustive]
13pub struct LivelinessMonitor {
14 /// The instant of the latest liveliness report.
15 pub latest_report: AtomicInstant,
16}
17impl LivelinessMonitor {
18 /// Starts a liveliness monitor on your asynchronous runtime (of which you must pass the `spawn` method),
19 /// returning both the handle the runtime may have returned, as well as a reference counted [`LivelinessMonitor`].
20 ///
21 /// Please refer to the examples to learn more about its usage.
22 pub fn start<T, SpawnFunction: Fn(LivelinessMonitorFuture) -> T>(
23 spawn: SpawnFunction,
24 ) -> (T, Arc<LivelinessMonitor>) {
25 let this = Arc::new(LivelinessMonitor {
26 latest_report: AtomicInstant::default(),
27 });
28 (
29 spawn(LivelinessMonitorFuture {
30 monitor: Arc::downgrade(&this),
31 }),
32 this,
33 )
34 }
35
36 /// The instant of the latest liveliness report, as an [`std::time::Instant`].
37 ///
38 /// Keep in mind its resolution is limited to that of [`crate::support::AtomicDuration`],
39 /// and that a busy executor may provide updates at rather low frequencies.
40 ///
41 /// You can probably expect that if the report hasn't been updated in the last 5 seconds,
42 /// your executor is indeed stalled.
43 pub fn latest_report(&self) -> std::time::Instant {
44 self.latest_report
45 .load(std::sync::atomic::Ordering::Relaxed)
46 }
47}