fix build.yml, concurrency concerns, build.rs concerns

This commit is contained in:
l1npengtul 2022-11-04 15:36:18 +09:00
parent 80fef5a01c
commit 36edc445d1
6 changed files with 98 additions and 165 deletions

View File

@ -89,37 +89,6 @@ jobs:
command: test command: test
args: ${{matrix.flags}} 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 builds are a bit more extensive to test
no_std_build: no_std_build:
name: NoStdBuild name: NoStdBuild

View File

@ -17,10 +17,10 @@ fn main() {
let seed = env::var("RHAI_AHASH_SEED").map_or_else(|_| "None".into(), |s| format!("Some({s})")); 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`") .expect("cannot create `config.rs`")
.write_all(contents.as_bytes()) .write_all(contents.as_bytes())
.expect("cannot write to `config/hashing.rs`"); .expect("cannot write to `config/hashing_env.rs`");
} }

View File

@ -1,112 +1,2 @@
//! Fixed hashing seeds for stable hashing. // This file is automatically set during build time by build.rs and build.template.
//! pub(crate) const AHASH_SEED: Option<[u64; 4]> = {{AHASH_SEED}};
//! 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<T>
where
T: 'static,
{
initalized: AtomicBool,
data: UnsafeCell<MaybeUninit<T>>,
_marker: PhantomData<T>,
}
impl<T> SusLock<T> {
pub const fn new() -> SusLock<T> {
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<T: Sync + Send> Sync for SusLock<T> {}
unsafe impl<T: Send> Send for SusLock<T> {}
impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for SusLock<T> {}
impl<T> Drop for SusLock<T> {
fn drop(&mut self) {
if self.initalized.load(Ordering::SeqCst) {
unsafe { (&mut *self.data.get()).assume_init_drop() };
}
}
}
static AHASH_SEED: SusLock<Option<[u64; 4]>> = 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()
}

View File

@ -4,31 +4,94 @@
//! //!
//! See [`set_rhai_ahash_seed`] for more. //! 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. //! environment variable instead.
//! //!
//! E.g. `env RHAI_AHASH_SEED ="[236,800,954,213]"` //! 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 // [236,800,954,213], haha funny yume nikki reference epic uboachan face numberworld nexus moment 100
use crate::config::hashing_env;
use core::{ use core::{
cell::UnsafeCell, cell::UnsafeCell,
marker::PhantomData, marker::PhantomData,
mem::MaybeUninit, mem::MaybeUninit,
panic::{RefUnwindSafe, UnwindSafe}, 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<T>"
struct SusLock<T> struct SusLock<T>
where where
T: 'static, T: 'static + Copy,
{ {
initalized: AtomicBool, initalized: AtomicBool,
data: UnsafeCell<MaybeUninit<T>>, data: UnsafeCell<MaybeUninit<T>>,
_marker: PhantomData<T>, _marker: PhantomData<T>,
} }
impl<T> SusLock<T> { impl<T> SusLock<T>
where
T: 'static + Copy,
{
pub const fn new() -> SusLock<T> { pub const fn new() -> SusLock<T> {
SusLock { SusLock {
initalized: AtomicBool::new(false), initalized: AtomicBool::new(false),
@ -37,21 +100,31 @@ impl<T> SusLock<T> {
} }
} }
pub fn get(&self) -> Option<&T> { pub fn get(&self) -> Option<T> {
if self.initalized.load(Ordering::SeqCst) { 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 { } else {
return None; 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<T> {
let value = f(); let value = f();
if !self.initalized.load(Ordering::SeqCst) { 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 { unsafe {
self.data.get().write(MaybeUninit::new(value)); self.data.get().write(MaybeUninit::new(value));
} }
self.initalized.store(true, Ordering::SeqCst);
} }
self.get() self.get()
@ -67,11 +140,14 @@ impl<T> SusLock<T> {
} }
} }
unsafe impl<T: Sync + Send> Sync for SusLock<T> {} unsafe impl<T: Sync + Send> Sync for SusLock<T> where T: 'static + Copy {}
unsafe impl<T: Send> Send for SusLock<T> {} unsafe impl<T: Send> Send for SusLock<T> where T: 'static + Copy {}
impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for SusLock<T> {} impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for SusLock<T> where T: 'static + Copy {}
impl<T> Drop for SusLock<T> { impl<T> Drop for SusLock<T>
where
T: 'static + Copy,
{
fn drop(&mut self) { fn drop(&mut self) {
if self.initalized.load(Ordering::SeqCst) { if self.initalized.load(Ordering::SeqCst) {
unsafe { (&mut *self.data.get()).assume_init_drop() }; 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. /// See [`set_rhai_ahash_seed`] for more.
pub fn get_ahash_seed() -> Option<[u64; 4]> { pub fn get_ahash_seed() -> Option<[u64; 4]> {
const FUNNY_YUMENIKKI_REFERENCE: Option<[u64; 4]> = None; AHASH_SEED.get_or_init(|| hashing_env::AHASH_SEED).flatten()
AHASH_SEED
.get_or_init(|| FUNNY_YUMENIKKI_REFERENCE)
.map(|x| *x)
.flatten()
} }

View File

@ -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;

View File

@ -1,3 +1,4 @@
//! Contains Configuration for Rhai. //! Contains Configuration for Rhai.
pub mod hashing; pub mod hashing;
mod hashing_env;