From 36edc445d1afc79493092506badbc2fa713df619 Mon Sep 17 00:00:00 2001 From: l1npengtul Date: Fri, 4 Nov 2022 15:36:18 +0900 Subject: [PATCH] fix build.yml, concurrency concerns, build.rs concerns --- .github/workflows/build.yml | 31 ---------- build.rs | 6 +- build.template | 114 +----------------------------------- src/config/hashing.rs | 109 ++++++++++++++++++++++++++++------ src/config/hashing_env.rs | 2 + src/config/mod.rs | 1 + 6 files changed, 98 insertions(+), 165 deletions(-) create mode 100644 src/config/hashing_env.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cf7f1f7b..d186abb9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -89,37 +89,6 @@ jobs: command: test args: ${{matrix.flags}} -# nightly_features_build: -# name: NightlyFeatureBuild -# runs-on: ${{matrix.os}} -# continue-on-error: ${{matrix.experimental}} -# strategy: -# matrix: -# os: [ubuntu-latest] -# flags: -# - "--features stable_hash" -# toolchain: [ nightly ] -# experimental: [ false ] -# include: -# # smoketests for different toolchains -# - { toolchain: nightly, os: windows-latest, experimental: false, flags: "" } -# - { toolchain: nightly, os: macos-latest, experimental: false, flags: "" } -# fail-fast: false -# steps: -# - name: Checkout -# uses: actions/checkout@v2 -# - name: Setup Toolchain -# uses: actions-rs/toolchain@v1 -# with: -# toolchain: ${{matrix.toolchain}} -# override: true -# - name: Test -# uses: actions-rs/cargo@v1 -# with: -# command: test -# args: ${{matrix.flags}} - - # no-std builds are a bit more extensive to test no_std_build: name: NoStdBuild diff --git a/build.rs b/build.rs index e95b1dc3..39c11238 100644 --- a/build.rs +++ b/build.rs @@ -17,10 +17,10 @@ fn main() { let seed = env::var("RHAI_AHASH_SEED").map_or_else(|_| "None".into(), |s| format!("Some({s})")); - contents = contents.replace("{{ AHASH_SEED }}", &seed); + contents = contents.replace("{{AHASH_SEED}}", &seed); - File::create("src/config/hashing.rs") + File::create("src/config/hashing_env.rs") .expect("cannot create `config.rs`") .write_all(contents.as_bytes()) - .expect("cannot write to `config/hashing.rs`"); + .expect("cannot write to `config/hashing_env.rs`"); } diff --git a/build.template b/build.template index 89b0e403..a165e5ed 100644 --- a/build.template +++ b/build.template @@ -1,112 +1,2 @@ -//! Fixed hashing seeds for stable hashing. -//! -//! Set to [`None`] to disable stable hashing. -//! -//! See [`set_rhai_ahash_seed`] for more. -//! -//! Alternatively, You can also set this at compile time by disabling `stable_hash` and setting the `RHAI_AHASH_SEED` -//! environment variable instead. -//! -//! E.g. `env RHAI_AHASH_SEED ="[236,800,954,213]"` -// [236,800,954,213], haha funny yume nikki reference epic uboachan face numberworld nexus moment 100 - -use core::{ - cell::UnsafeCell, - marker::PhantomData, - mem::MaybeUninit, - panic::{RefUnwindSafe, UnwindSafe}, - sync::atomic::{AtomicBool, Ordering}, -}; - -// Safety: lol -struct SusLock -where - T: 'static, -{ - initalized: AtomicBool, - data: UnsafeCell>, - _marker: PhantomData, -} - -impl SusLock { - pub const fn new() -> SusLock { - SusLock { - initalized: AtomicBool::new(false), - data: UnsafeCell::new(MaybeUninit::uninit()), - _marker: PhantomData, - } - } - - pub fn get(&self) -> Option<&T> { - if self.initalized.load(Ordering::SeqCst) { - Some(unsafe { (&*self.data.get()).assume_init_ref() }) - } else { - return None; - } - } - - pub fn get_or_init(&self, f: impl FnOnce() -> T) -> Option<&T> { - let value = f(); - if !self.initalized.load(Ordering::SeqCst) { - unsafe { - self.data.get().write(MaybeUninit::new(value)); - } - self.initalized.store(true, Ordering::SeqCst); - } - - self.get() - } - - pub fn set(&self, value: T) -> Result<(), T> { - if self.initalized.load(Ordering::SeqCst) { - Err(value) - } else { - let _ = self.get_or_init(|| value); - Ok(()) - } - } -} - -unsafe impl Sync for SusLock {} -unsafe impl Send for SusLock {} -impl RefUnwindSafe for SusLock {} - -impl Drop for SusLock { - fn drop(&mut self) { - if self.initalized.load(Ordering::SeqCst) { - unsafe { (&mut *self.data.get()).assume_init_drop() }; - } - } -} - -static AHASH_SEED: SusLock> = SusLock::new(); - -// #[doc(cfg(feature = "stable_hash"))] -/// Sets the Rhai Ahash seed. This is used to hash functions and the like. -/// -/// This is a global variable, and thus will affect every Rhai instance. -/// This should not be used _unless_ you know you need it. -/// -/// # Warnings -/// - You can only call this function **ONCE** for the whole of your program execution. -/// - You should gracefully handle the `Err(())`. -/// - You **MUST** call this before **ANY** Rhai operation occurs (e.g. creating an [`Engine`]). -/// -/// # Errors -/// This will error if the AHashSeed is already set. -pub fn set_ahash_seed(new_seed: Option<[u64; 4]>) -> Result<(), Option<[u64; 4]>> { - AHASH_SEED.set(new_seed) -} - -/// Gets the current Rhai Ahash Seed. If the seed is not yet defined, this will automatically set a seed. -/// The default seed is not stable and may change between versions. -/// -/// See [`set_rhai_ahash_seed`] for more. -pub fn get_ahash_seed() -> Option<[u64; 4]> { - const FUNNY_YUMENIKKI_REFERENCE: Option<[u64; 4]> = {{ AHASH_SEED }}; - - AHASH_SEED - .get_or_init(|| FUNNY_YUMENIKKI_REFERENCE) - .map(|x| *x) - .flatten() -} +// This file is automatically set during build time by build.rs and build.template. +pub(crate) const AHASH_SEED: Option<[u64; 4]> = {{AHASH_SEED}}; diff --git a/src/config/hashing.rs b/src/config/hashing.rs index 3f318fef..2355a405 100644 --- a/src/config/hashing.rs +++ b/src/config/hashing.rs @@ -4,31 +4,94 @@ //! //! See [`set_rhai_ahash_seed`] for more. //! -//! Alternatively, You can also set this at compile time by disabling `stable_hash` and setting the `RHAI_AHASH_SEED` +//! Alternatively, You can also set this at compile time by setting the `RHAI_AHASH_SEED` //! environment variable instead. //! //! E.g. `env RHAI_AHASH_SEED ="[236,800,954,213]"` // [236,800,954,213], haha funny yume nikki reference epic uboachan face numberworld nexus moment 100 +use crate::config::hashing_env; use core::{ cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit, panic::{RefUnwindSafe, UnwindSafe}, - sync::atomic::{AtomicBool, Ordering}, + sync::atomic::{AtomicBool, AtomicUsize, Ordering}, }; -// Safety: lol +// omg its hokma from record team here to record our locks +// what does this do? +// so what this does is keep track of a global address in memory that acts as a global lock +// i stole this from crossbeam so read their docs for more +struct HokmaLock { + lock: AtomicUsize, +} + +impl HokmaLock { + pub const fn new() -> Self { + Self { + lock: AtomicUsize::new(0), + } + } + + pub fn write(&'static self) -> WhenTheHokmaSupression { + loop { + let previous = self.lock.swap(1, Ordering::SeqCst); + + if previous != 1 { + return WhenTheHokmaSupression { + hokma: self, + state: previous, + }; + } + } + } +} + +struct WhenTheHokmaSupression { + hokma: &'static HokmaLock, + + state: usize, +} + +impl WhenTheHokmaSupression { + pub fn the_price_of_silence(self) { + self.hokma.lock.store(self.state, Ordering::SeqCst); + + core::mem::forget(self) + } +} + +impl Drop for WhenTheHokmaSupression { + fn drop(&mut self) { + self.hokma + .lock + .store(self.state.wrapping_add(2), Ordering::SeqCst) + } +} + +fn hokmalock(address: usize) -> &'static HokmaLock { + const LEN: usize = 787; + const LCK: HokmaLock = HokmaLock::new(); + static RECORDS: [HokmaLock; LEN] = [LCK; LEN]; + + &RECORDS[address % LEN] +} + +// Safety: lol, there is a reason its called "SusLock" struct SusLock where - T: 'static, + T: 'static + Copy, { initalized: AtomicBool, data: UnsafeCell>, _marker: PhantomData, } -impl SusLock { +impl SusLock +where + T: 'static + Copy, +{ pub const fn new() -> SusLock { SusLock { initalized: AtomicBool::new(false), @@ -37,21 +100,31 @@ impl SusLock { } } - pub fn get(&self) -> Option<&T> { + pub fn get(&self) -> Option { if self.initalized.load(Ordering::SeqCst) { - Some(unsafe { (&*self.data.get()).assume_init_ref() }) + let hokma = hokmalock(unsafe { core::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 { cast.read() } + }; + guard.the_price_of_silence(); + Some(val) } else { return None; } } - pub fn get_or_init(&self, f: impl FnOnce() -> T) -> Option<&T> { + pub fn get_or_init(&self, f: impl FnOnce() -> T) -> Option { let value = f(); if !self.initalized.load(Ordering::SeqCst) { + self.initalized.store(true, Ordering::SeqCst); + let hokma = hokmalock(unsafe { core::mem::transmute(self.data.get()) }); + hokma.write(); unsafe { self.data.get().write(MaybeUninit::new(value)); } - self.initalized.store(true, Ordering::SeqCst); } self.get() @@ -67,11 +140,14 @@ impl SusLock { } } -unsafe impl Sync for SusLock {} -unsafe impl Send for SusLock {} -impl RefUnwindSafe for SusLock {} +unsafe impl Sync for SusLock where T: 'static + Copy {} +unsafe impl Send for SusLock where T: 'static + Copy {} +impl RefUnwindSafe for SusLock where T: 'static + Copy {} -impl Drop for SusLock { +impl Drop for SusLock +where + T: 'static + Copy, +{ fn drop(&mut self) { if self.initalized.load(Ordering::SeqCst) { unsafe { (&mut *self.data.get()).assume_init_drop() }; @@ -103,10 +179,5 @@ pub fn set_ahash_seed(new_seed: Option<[u64; 4]>) -> Result<(), Option<[u64; 4]> /// /// See [`set_rhai_ahash_seed`] for more. pub fn get_ahash_seed() -> Option<[u64; 4]> { - const FUNNY_YUMENIKKI_REFERENCE: Option<[u64; 4]> = None; - - AHASH_SEED - .get_or_init(|| FUNNY_YUMENIKKI_REFERENCE) - .map(|x| *x) - .flatten() + AHASH_SEED.get_or_init(|| hashing_env::AHASH_SEED).flatten() } diff --git a/src/config/hashing_env.rs b/src/config/hashing_env.rs new file mode 100644 index 00000000..ee2b35db --- /dev/null +++ b/src/config/hashing_env.rs @@ -0,0 +1,2 @@ +// This file is automatically set during build time by build.rs and build.template. +pub(crate) const AHASH_SEED: Option<[u64; 4]> = None; diff --git a/src/config/mod.rs b/src/config/mod.rs index e2748d4a..db5448f6 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,3 +1,4 @@ //! Contains Configuration for Rhai. pub mod hashing; +mod hashing_env;