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
use std::sync::Arc;

pub mod support;
use support::{AtomicInstant, LivelinessMonitorFuture};

/// A liveliness monitor for asynchronous runtimes.
///
/// Its only constructor ([`LivelinessMonitor::start()`]) returns it wrapped in an [`Arc`] with strong count 1.
/// Should that strong count reach 0 (due to dropping all the clones you may have made of that [`Arc`], or by
/// using [`Arc::try_unwrap()`]), the associated task spawned in your runtime will end next time upon its next
/// scheduling.
#[non_exhaustive]
pub struct LivelinessMonitor {
    /// The instant of the latest liveliness report.
    pub latest_report: AtomicInstant,
}
impl LivelinessMonitor {
    /// Starts a liveliness monitor on your asynchronous runtime (of which you must pass the `spawn` method),
    /// returning both the handle the runtime may have returned, as well as a reference counted [`LivelinessMonitor`].
    ///
    /// Please refer to the examples to learn more about its usage.
    pub fn start<T, SpawnFunction: Fn(LivelinessMonitorFuture) -> T>(
        spawn: SpawnFunction,
    ) -> (T, Arc<LivelinessMonitor>) {
        let this = Arc::new(LivelinessMonitor {
            latest_report: AtomicInstant::default(),
        });
        (
            spawn(LivelinessMonitorFuture {
                monitor: Arc::downgrade(&this),
            }),
            this,
        )
    }

    /// The instant of the latest liveliness report, as an [`std::time::Instant`].
    ///
    /// Keep in mind its resolution is limited to that of [`crate::support::AtomicDuration`],
    /// and that a busy executor may provide updates at rather low frequencies.
    ///
    /// You can probably expect that if the report hasn't been updated in the last 5 seconds,
    /// your executor is indeed stalled.
    pub fn latest_report(&self) -> std::time::Instant {
        self.latest_report
            .load(std::sync::atomic::Ordering::Relaxed)
    }
}