use std::{cell::Cell, ops::Add}; thread_local! { /// The constant time used by the stable-commit-ids feature. pub static STABLE_TIME: Cell = const { Cell::new(1514817556) }; /// An incrementing counter to advance the `STABLE_TIME` value with in /// [`with_advanced_timestamp`]. pub static STEP: Cell = Cell::new(Step::default()); } #[derive(Clone, Copy)] struct Step(i64); impl Default for Step { fn default() -> Self { Self(1) } } impl Add for i64 { type Output = i64; fn add(self, rhs: Step) -> Self::Output { self + rhs.0 } } impl Add for Step { type Output = Step; fn add(self, rhs: i64) -> Self::Output { Step(self.0 + rhs) } } /// Read the current value of `STABLE_TIME`. /// /// # Panics /// /// The `STABLE_TIME` is declared in `thread_local`, and so the panic /// information is repeated here. /// /// Panics if the key currently has its destructor running, and it may panic if /// the destructor has previously been run for this thread. #[allow(clippy::unwrap_used)] pub fn read_timestamp() -> i64 { STABLE_TIME.get() } /// Perform an action `f` that would rely on the `STABLE_TIME` value. This will /// advance the `STABLE_TIME` by an increment of `1` for each time it is called, /// within the same thread. /// /// # Usage /// /// ```rust, ignore /// let oid1 = with_advanced_timestamp(|| cob.update("New revision OID")); /// let oid2 = with_advanced_timestamp(|| cob.update("Another revision OID")); /// ``` /// /// # Panics /// /// The `STABLE_TIME` is declared in `thread_local`, and so the panic /// information is repeated here. /// /// Panics if the key currently has its destructor running, and it may panic if /// the destructor has previously been run for this thread. #[allow(clippy::unwrap_used)] pub fn with_advanced_timestamp(f: F) -> T where F: FnOnce() -> T, { let step = STEP.get(); let original = read_timestamp(); STABLE_TIME.replace(original + step); let result = f(); STEP.replace(step + 1); result }