#[cfg(test)]
mod test;
struct DualInner<T, F> {
value: T,
flag: F
}
impl<T, F> DualInner<T, F> {
fn new(value: T, flag: F) -> *mut Self {
Box::into_raw(Box::new(DualInner { value, flag }))
}
}
mod cell {
use std::cell::Cell;
use std::fmt::{Debug, Formatter};
use std::ops::Deref;
use crate::DualInner;
pub struct Dual<T> {
inner: *mut DualInner<T, Cell<bool>>
}
impl<T> Dual<T> {
pub fn new(value: T) -> (Self, Self) {
let inner = DualInner::new(value, Cell::new(true));
(Self { inner }, Self { inner })
}
pub fn other_exists(&self) -> bool {
unsafe { (*self.inner).flag.get() }
}
pub fn take(&self) -> T where T: Clone {
unsafe {
(&*self.inner).value.clone()
}
}
}
impl<T> Deref for Dual<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &(*self.inner).value }
}
}
impl<T> Drop for Dual<T> {
fn drop(&mut self) {
unsafe {
if !(*self.inner).flag.take() {
drop(Box::from_raw(self.inner));
}
}
}
}
impl<T> Debug for Dual<T> where T: Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.deref().fmt(f)
}
}
unsafe impl<T> Send for Dual<T> where T: Send {}
}
mod atomic {
use std::fmt::{Debug, Formatter};
use std::ops::Deref;
use std::sync::atomic::{AtomicBool, Ordering};
use crate::DualInner;
pub struct ADual<T> {
inner: *mut DualInner<T, AtomicBool>
}
impl<T> ADual<T> {
pub fn new(value: T) -> (Self, Self) {
let inner = DualInner::new(value, AtomicBool::new(true));
(Self { inner }, Self { inner })
}
pub fn other_exists(&self) -> bool {
unsafe { (*self.inner).flag.load(Ordering::SeqCst) }
}
pub fn take(&self) -> T where T: Clone {
unsafe {
(&*self.inner).value.clone()
}
}
}
impl<T> Deref for ADual<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &(*self.inner).value }
}
}
impl<T> Drop for ADual<T> {
fn drop(&mut self) {
unsafe {
if !(*self.inner).flag.fetch_and(false, Ordering::SeqCst) {
drop(Box::from_raw(self.inner));
}
}
}
}
impl<T> Debug for ADual<T> where T: Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.deref().fmt(f)
}
}
unsafe impl<T> Send for ADual<T> where T: Send {}
unsafe impl<T> Sync for ADual<T> where T: Sync {}
}
pub use cell::Dual;
pub use atomic::ADual;