saluki_common/
time.rs

1//! Time-related functions.
2
3use std::{
4    sync::{
5        atomic::{AtomicU64, Ordering::Relaxed},
6        Once,
7    },
8    thread,
9    time::{Duration, SystemTime},
10};
11
12static COARSE_TIME_INITIALIZED: Once = Once::new();
13static COARSE_TIME: AtomicU64 = AtomicU64::new(0);
14const COARSE_TIME_UPDATE_INTERVAL: Duration = Duration::from_millis(250);
15
16/// Get the current Unix timestamp, in seconds.
17///
18/// This function is accurate, as it always retrieves the current time for each call. In scenarios where this function
19/// is being called frequently, it may pose an unacceptable performance overhead. In such cases, consider using
20/// `get_coarse_unix_timestamp`, which provides a cached value that is updated periodically.
21pub fn get_unix_timestamp() -> u64 {
22    let since_unix_epoch = SystemTime::now()
23        .duration_since(SystemTime::UNIX_EPOCH)
24        .unwrap_or_default();
25    since_unix_epoch.as_secs()
26}
27
28/// Get the current coarse Unix timestamp, in seconds.
29///
30/// In scenarios where the current Unix timestamp is needed frequently, this function provides a cached value that is
31/// updated periodically. As the precision of the timestamp is one second, this function allows trading off accuracy
32/// (see below) for reduced overhead. The resulting value is considered "coarse", because it might be off by significant
33/// percentage of the overall precision.
34///
35/// # Accuracy
36///
37/// The underlying coarse time is updated roughly every 250 milliseconds, so the value returned by this function may be
38/// behind by up to 250 milliseconds. This means that if calling the function at true time `t` (where `t` is in
39/// seconds), the value returned may be `t-1` _or_ `t`, but will never be behind by more than 250 milliseconds, and
40/// never _ahead_ of `t`.
41pub fn get_coarse_unix_timestamp() -> u64 {
42    // Initialize a background thread to update the coarse time if it hasn't been initialized yet.
43    COARSE_TIME_INITIALIZED.call_once(|| {
44        // Initialize the coarse time with the current Unix timestamp.
45        COARSE_TIME.store(get_unix_timestamp(), Relaxed);
46
47        thread::spawn(|| {
48            loop {
49                // Sleep for 250 milliseconds.
50                thread::sleep(COARSE_TIME_UPDATE_INTERVAL);
51
52                // Update the coarse time with the current Unix timestamp.
53                COARSE_TIME.store(get_unix_timestamp(), Relaxed);
54            }
55        });
56    });
57
58    COARSE_TIME.load(Relaxed)
59}