use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex};
pub struct Cell<T> {
inner: Arc<Mutex<Option<T>>>,
}
pub struct Borrowed<T> {
ret: Arc<Mutex<Option<T>>>,
value: Option<T>,
}
impl<T> Cell<T> {
pub fn new(value: T) -> Self {
Self {
inner: Arc::new(Mutex::new(Some(value))),
}
}
#[must_use]
pub fn is_available(&self) -> bool {
self.inner.lock().unwrap().is_some()
}
#[must_use]
pub fn try_borrow(&self) -> Option<Borrowed<T>> {
self.inner.lock().unwrap().take().map(|value| Borrowed {
ret: self.inner.clone(),
value: Some(value),
})
}
}
impl<T: Clone> Cell<T> {
#[must_use]
pub fn fork(&self) -> Option<Cell<T>> {
if let Some(inner) = self.try_borrow() {
return Some(Cell::new(inner.clone()));
}
None
}
}
impl<T> Drop for Borrowed<T> {
fn drop(&mut self) {
let value = self.value.take().expect("can only be dropped once");
self.ret.lock().unwrap().replace(value);
}
}
impl<T> Deref for Borrowed<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.value.as_ref().expect("already dropped")
}
}
impl<T> DerefMut for Borrowed<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.value.as_mut().expect("already dropped")
}
}