From 20911bddf50633aabc12162a2daf0294d5a7bc7a Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 25 Jun 2024 07:39:12 +1000 Subject: [PATCH] avoid taking the shared lock when getting usable bits in Uuid::now_v7 --- Cargo.toml | 2 +- src/timestamp.rs | 50 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e8600c59..9d6b4497 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,7 @@ v3 = ["md5"] v4 = ["rng"] v5 = ["sha1"] v6 = ["atomic"] -v7 = ["atomic", "rng"] +v7 = ["rng"] v8 = [] js = ["dep:wasm-bindgen", "getrandom?/js"] diff --git a/src/timestamp.rs b/src/timestamp.rs index c76f7d0b..6fb56a6e 100644 --- a/src/timestamp.rs +++ b/src/timestamp.rs @@ -654,13 +654,23 @@ pub mod context { use core::{cell::Cell, panic::RefUnwindSafe}; #[cfg(feature = "std")] - static CONTEXT_V7: std::sync::Mutex = std::sync::Mutex::new(ContextV7::new()); + static CONTEXT_V7: SharedContextV7 = + SharedContextV7(std::sync::Mutex::new(ContextV7::new())); #[cfg(feature = "std")] - pub(crate) fn shared_context_v7() -> &'static std::sync::Mutex { + pub(crate) fn shared_context_v7() -> &'static SharedContextV7 { &CONTEXT_V7 } + const USABLE_BITS: usize = 42; + + // Leave the most significant bit unset + // This guarantees the counter has at least 2,199,023,255,552 + // values before it will overflow, which is exceptionally unlikely + // even in the worst case + const RESEED_MASK: u64 = u64::MAX >> 23; + const MAX_COUNTER: u64 = u64::MAX >> 22; + /// An unsynchronized, reseeding counter that produces 42-bit values. /// /// This type works by: @@ -729,13 +739,6 @@ pub mod context { seconds: u64, subsec_nanos: u32, ) -> (Self::Output, u64, u32) { - // Leave the most significant bit unset - // This guarantees the counter has at least 2,199,023,255,552 - // values before it will overflow, which is exceptionally unlikely - // even in the worst case - const RESEED_MASK: u64 = u64::MAX >> 23; - const MAX_COUNTER: u64 = u64::MAX >> 22; - let millis = (seconds * 1_000).saturating_add(subsec_nanos as u64 / 1_000_000); let last_reseed = self.last_reseed.get(); @@ -785,7 +788,34 @@ pub mod context { } fn usable_bits(&self) -> usize { - 42 + USABLE_BITS + } + } + + #[cfg(feature = "std")] + pub(crate) struct SharedContextV7(std::sync::Mutex); + + #[cfg(feature = "std")] + impl ClockSequence for SharedContextV7 { + type Output = u64; + + fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output { + self.0.generate_sequence(seconds, subsec_nanos) + } + + fn generate_timestamp_sequence( + &self, + seconds: u64, + subsec_nanos: u32, + ) -> (Self::Output, u64, u32) { + self.0.generate_timestamp_sequence(seconds, subsec_nanos) + } + + fn usable_bits(&self) -> usize + where + Self::Output: Sized, + { + USABLE_BITS } }