Skip to content

Instantly share code, notes, and snippets.

@AlphaModder
Created July 17, 2018 22:03
Show Gist options
  • Save AlphaModder/2fe28c0c41b20a922e3ec4ac2ff54056 to your computer and use it in GitHub Desktop.
Save AlphaModder/2fe28c0c41b20a922e3ec4ac2ff54056 to your computer and use it in GitHub Desktop.
use std::ops::{Deref, DerefMut};
use std::sync::atomic::{AtomicUsize, Ordering};
const EMPTY: usize = 0;
const FULL: usize = 1;
const IN_USE: usize = 2;
pub struct ResourceCell<T: Send> {
status: AtomicUsize,
resource: UnsafeCell<Option<T>>,
}
impl<T> ResourceCell<T> {
pub fn new(data: Option<T>) -> ResourceCell<T> {
ResourceCell {
status: AtomicUsize::new(if data.is_none() { EMPTY } else { FULL }),
resource: UnsafeCell::new(data)
}
}
pub fn try_acquire(&self) -> Result<Guard<T>, ()> {
if self.status.compare_and_swap(FULL, IN_USE, Ordering::Acquire) == IN_USE {
return Ok(Guard(self))
}
Err(())
}
pub fn try_take(&self) -> Result<T, ()> {
if self.status.compare_and_swap(FULL, IN_USE, Ordering::Acquire) == IN_USE {
let value = self.resource.get().take().unwrap();
self.cell.status.store(EMPTY, Ordering::Release);
return Ok(value);
}
Err(())
}
pub fn try_reserve(&self) -> Result<Reserve<T>, ()> {
if self.status.compare_and_swap(EMPTY, IN_USE, Ordering::Acquire) == IN_USE {
return Ok(Reserve(self))
}
Err(())
}
}
unsafe impl<T: Send> Sync for ResourceCell<T> { }
pub struct Guard<'a, T>(&'a ResourceCell<T>);
impl<'a, T> Drop for Guard<'a, T> {
fn drop(&mut self) {
self.0.status.store(FULL, Ordering::Release);
}
}
impl<'a, T> Deref for Guard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
return cell.resource.get().as_ref().unwrap()
}
}
impl<'a, T> DerefMut for Guard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
return cell.resource.get().as_mut().unwrap()
}
}
pub struct Reserve<'a, T>(&'a ResourceCell<T>);
impl<'a, T> Reserve<'a, T> {
pub fn fill(self, value: T) {
*self.0.resource.get().as_mut() = Some(value);
self.cell.status.store(FULL, Ordering::Release);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment