diff --git a/CHANGELOG.md b/CHANGELOG.md index c123b440..1772d4f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,7 @@ New features ### Static hashing -* It is now possible to specify a fixed _seed_ for use with the `ahash` hasher, via a static function `rhai::config::hashing::set_ahash_seed` or an environment variable, in order to force static (i.e. deterministic) hashes for function signatures. +* It is now possible to specify a fixed _seed_ for use with the `ahash` hasher, via a static function `rhai::config::hashing::set_ahash_seed` or an environment variable (`RHAI_AHASH_SEED`), in order to force static (i.e. deterministic) hashes for function signatures. * This is necessary when using Rhai across shared-library boundaries. * A build script is used to extract the environment variable (`RHAI_AHASH_SEED`, if any) and splice it into the source code before compilation. diff --git a/src/config/hashing.rs b/src/config/hashing.rs index dd93e812..671b6664 100644 --- a/src/config/hashing.rs +++ b/src/config/hashing.rs @@ -94,7 +94,7 @@ fn hokmalock(address: usize) -> &'static HokmaLock { &RECORDS[address % LEN] } -// Safety: lol, there is a reason its called "SusLock" +// Safety: lol, there is a reason its called `SusLock` #[must_use] struct SusLock where @@ -118,36 +118,39 @@ where } } + #[inline(always)] + #[must_use] + pub fn is_initialized(&self) -> bool { + self.initialized.load(Ordering::SeqCst) + } + #[must_use] pub fn get(&self) -> Option<&'static T> { if self.initialized.load(Ordering::SeqCst) { let hokma = hokmalock(unsafe { mem::transmute(self.data.get()) }); // we forgo the optimistic read, because we don't really care let guard = hokma.write(); - let val = { - let cast: *const T = self.data.get().cast(); - unsafe { mem::transmute::<*const T, &'static T>(cast) } - }; + let cast: *const T = self.data.get().cast(); + let val = unsafe { mem::transmute::<*const T, &'static T>(cast) }; guard.the_price_of_silence(); Some(val) } else { - return None; + None } } #[must_use] - pub fn get_or_init(&self, f: impl FnOnce() -> T) -> Option<&'static T> { + pub fn get_or_init(&self, f: impl FnOnce() -> T) -> &'static T { if !self.initialized.load(Ordering::SeqCst) { - let value = f(); self.initialized.store(true, Ordering::SeqCst); let hokma = hokmalock(unsafe { mem::transmute(self.data.get()) }); hokma.write(); unsafe { - self.data.get().write(MaybeUninit::new(value)); + self.data.get().write(MaybeUninit::new(f())); } } - self.get() + self.get().unwrap() } pub fn set(&self, value: T) -> Result<(), T> { @@ -217,10 +220,9 @@ pub fn set_ahash_seed(new_seed: Option<[u64; 4]>) -> Result<(), Option<[u64; 4]> #[inline] #[must_use] pub fn get_ahash_seed() -> &'static Option<[u64; 4]> { - const NONE: &'static Option<[u64; 4]> = &None; - - match AHASH_SEED.get_or_init(|| hashing_env::AHASH_SEED) { - Some(ash) => ash, - None => NONE, + if !AHASH_SEED.is_initialized() { + return &hashing_env::AHASH_SEED; } + + AHASH_SEED.get().unwrap_or(&hashing_env::AHASH_SEED) } diff --git a/src/func/hashing.rs b/src/func/hashing.rs index 83b2fed1..9752196b 100644 --- a/src/func/hashing.rs +++ b/src/func/hashing.rs @@ -74,12 +74,12 @@ impl BuildHasher for StraightHasherBuilder { } /// Create an instance of the default hasher. -#[inline(always)] +#[inline] #[must_use] pub fn get_hasher() -> ahash::AHasher { match config::hashing::get_ahash_seed() { - Some([seed1, seed2, seed3, seed4]) if seed1 | seed2 | seed3 | seed4 != 0 => { - ahash::RandomState::with_seeds(*seed1, *seed2, *seed3, *seed4).build_hasher() + &Some([seed1, seed2, seed3, seed4]) if (seed1 | seed2 | seed3 | seed4) != 0 => { + ahash::RandomState::with_seeds(seed1, seed2, seed3, seed4).build_hasher() } _ => ahash::AHasher::default(), }