use std::sync::{
atomic::{AtomicPtr, Ordering},
Mutex, MutexGuard,
};
pub fn u64_from_time() -> u64 {
use std::time::{SystemTime, UNIX_EPOCH};
let unix_delta = match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(duration) => duration,
Err(system_time_error) => system_time_error.duration(),
};
if unix_delta.subsec_nanos() != 0 {
unix_delta.as_secs().wrapping_mul(unix_delta.subsec_nanos() as u64)
} else {
unix_delta.as_secs()
}
}
#[macro_export]
macro_rules! make_global_generator {
($global:ident, $generator:ty, $getter:ident) => {
static $global: AtomicPtr<Mutex<$generator>> = AtomicPtr::new(null_mut());
pub fn $getter() -> MutexGuard<'static, $generator> {
let mutex_ref = match unsafe { $global.load(Ordering::SeqCst).as_ref() } {
Some(mutex_ref) => mutex_ref,
None => {
let u = randomize::std::u64_from_time();
let mutex_box_raw: *mut $generator = Box::into_raw(Box::new(Mutex::new($generator::from(u))));
match unsafe { $global.compare_and_swap(null_mut(), mutex_box_raw, Ordering::SeqCst).as_ref() } {
Some(mutex_ref) => {
let _mutex_box_reconstructed = Box::from_raw(mutex_box_raw);
mutex_ref
}
None => mutex_box_raw.as_ref().unwrap(),
}
}
};
match mutex_ref.lock() {
Ok(guard) => guard,
Err(poison_error_guard) => poison_error_guard.into_inner(),
}
}
};
}