use std::borrow::Borrow;
use std::fmt::{Debug, Formatter};
use std::ptr;
use std::sync::atomic::{AtomicPtr, Ordering};
use std::sync::Arc;
use crossbeam_utils::atomic::AtomicCell;
use generator::Generator;
pub struct AtomicOption<T> {
inner: AtomicCell<Option<T>>,
}
impl<T: std::fmt::Debug> Debug for AtomicOption<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self.get() {
None => {
f.debug_struct("AtomicOption")
.field("inner", &Option::<T>::None)
.finish()
}
Some(s) => {
f.debug_struct("AtomicOption")
.field("inner", s)
.finish()
}
}
}
}
unsafe impl<T> Send for AtomicOption<T> {}
unsafe impl<T> Sync for AtomicOption<T> {}
impl<T> AtomicOption<T> {
pub fn none() -> AtomicOption<T> {
AtomicOption {
inner: AtomicCell::new(None),
}
}
pub fn some(t: T) -> AtomicOption<T> {
AtomicOption {
inner: AtomicCell::new(Some(t)),
}
}
#[inline]
pub fn store(&self, t: T) {
self.inner.store(Some(t))
}
#[inline]
pub fn swap(&self, t: T) -> Option<T> {
self.inner.swap(Some(t))
}
#[inline]
pub fn take(&self) -> Option<T> {
self.inner.take()
}
#[inline]
pub fn is_none(&self) -> bool {
unsafe {
(&(*self.inner.borrow().as_ptr())).is_none()
}
}
#[inline]
pub fn is_some(&self) -> bool {
unsafe {
(&(*self.inner.borrow().as_ptr())).is_some()
}
}
#[inline]
pub fn get(&self) -> Option<&T> {
match unsafe { (&(*self.inner.borrow().as_ptr())) } {
None => {
None
}
Some(v) => {
Some(v)
}
}
}
}
impl<T> Default for AtomicOption<T> {
fn default() -> Self {
Self::none()
}
}
impl<T> Drop for AtomicOption<T> {
fn drop(&mut self) {
self.inner.store(None)
}
}