mod multi; pub use multi::*;
use std::{
mem::MaybeUninit,
sync::Weak,
};
use crate::types::{
sync::{
atomic::{ AtomicBool, Ordering },
Arc,
},
cell::UnsafeCell,
};
pub type Fuze<T> = Fuse<T>;
pub type Fire = Flame;
struct OneTime<T> {
has_value: AtomicBool,
cell: UnsafeCell<MaybeUninit<T>>,
}
impl<T> OneTime<T> {
pub fn new() -> Self {
Self {
has_value: AtomicBool::new(false),
cell: UnsafeCell::new(MaybeUninit::uninit()),
}
}
}
impl<T> Drop for OneTime<T> {
fn drop(&mut self) {
if self.has_value.load(Ordering::Relaxed) {
unsafe {
#[cfg(not(loom))]
let value = self.cell.get().replace(MaybeUninit::uninit());
#[cfg(loom)]
let value = self.cell.get_mut().with(|p| p.replace(MaybeUninit::uninit()));
value.assume_init();
}
}
}
}
pub struct Bomb<T> {
data: Arc<OneTime<T>>,
#[cfg(not(loom))] _counter: Arc<()>,
}
unsafe impl<T: Send + Sync> Send for Bomb<T> { }
unsafe impl<T: Send + Sync> Sync for Bomb<T> { }
impl<T> Clone for Bomb<T> {
fn clone(&self) -> Self {
Self { data: self.data.clone(), #[cfg(not(loom))] _counter: self._counter.clone() }
}
}
pub struct Fuse<T> {
data: Arc<OneTime<T>>,
#[cfg(not(loom))] _counter: Weak<()>
}
unsafe impl<T: Send + Sync> Send for Fuse<T> { }
unsafe impl<T> Sync for Fuse<T> { }
pub struct Flame {
#[cfg(not(loom))] counter: Weak<()>,
}
impl<T> Bomb<T> {
pub fn new() -> (Fuse<T>, Bomb<T>) {
#[cfg(not(loom))] let _counter = Arc::new(());
let fuse = Fuse::new(#[cfg(not(loom))] &_counter);
let bomb = Self {
data: fuse.data.clone(),
#[cfg(not(loom))] _counter,
};
(fuse, bomb)
}
pub fn exploded(&self) -> Option<&T> {
if !self.data.has_value.load(Ordering::Acquire) {
None
}
else {
#[cfg(not(loom))]
unsafe { Some(self.data.cell.get().as_ref().unwrap().assume_init_ref()) }
#[cfg(loom)]
unsafe { Some(self.data.cell.get().with(|p| p.as_ref().unwrap().assume_init_ref())) }
}
}
}
impl<T> Fuse<T> {
fn new(#[cfg(not(loom))] _counter: &Arc<()>) -> Self {
Self {
data: Arc::new(OneTime::new()),
#[cfg(not(loom))] _counter: Arc::downgrade(&_counter),
}
}
pub fn ignite(self, value: T) -> Flame {
self.light(value)
}
pub fn light(self, value: T) -> Flame {
#[cfg(not(loom))]
unsafe { *self.data.cell.get() = MaybeUninit::new(value); }
#[cfg(loom)]
unsafe { self.data.cell.get_mut().with(|p| { *p = MaybeUninit::new(value); }); }
self.data.has_value.store(true, Ordering::Release);
Flame {
#[cfg(not(loom))] counter: self._counter
}
}
}
impl Flame {
pub fn extinguished(&self) -> bool {
#[cfg(not(loom))] { self.counter.strong_count() == 0 }
#[cfg(loom)]
unimplemented!("std::sync::Weak not implemented in loom.");
}
}