use std::boxed::Box;
use std::cell::UnsafeCell;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use {Async, Future, Poll};
use task::{self, Task};
pub struct BiLock<T> {
inner: Arc<Inner<T>>,
}
struct Inner<T> {
state: AtomicUsize,
inner: UnsafeCell<T>,
}
unsafe impl<T: Send> Send for Inner<T> {}
unsafe impl<T: Send> Sync for Inner<T> {}
impl<T> BiLock<T> {
pub fn new(t: T) -> (BiLock<T>, BiLock<T>) {
let inner = Arc::new(Inner {
state: AtomicUsize::new(0),
inner: UnsafeCell::new(t),
});
(BiLock { inner: inner.clone() }, BiLock { inner: inner })
}
pub fn poll_lock(&self) -> Async<BiLockGuard<T>> {
loop {
match self.inner.state.swap(1, SeqCst) {
0 => return Async::Ready(BiLockGuard { inner: self }),
1 => {}
n => unsafe {
drop(Box::from_raw(n as *mut Task));
}
}
let me = Box::new(task::park());
let me = Box::into_raw(me) as usize;
match self.inner.state.compare_exchange(1, me, SeqCst, SeqCst) {
Ok(_) => return Async::NotReady,
Err(0) => unsafe {
drop(Box::from_raw(me as *mut Task));
},
Err(n) => panic!("invalid state: {}", n),
}
}
}
pub fn lock(self) -> BiLockAcquire<T> {
BiLockAcquire {
inner: self,
}
}
fn unlock(&self) {
match self.inner.state.swap(0, SeqCst) {
0 => panic!("invalid unlocked state"),
1 => {}
n => unsafe {
Box::from_raw(n as *mut Task).unpark();
}
}
}
}
impl<T> Drop for Inner<T> {
fn drop(&mut self) {
assert_eq!(self.state.load(SeqCst), 0);
}
}
pub struct BiLockGuard<'a, T: 'a> {
inner: &'a BiLock<T>,
}
impl<'a, T> Deref for BiLockGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.inner.inner.inner.get() }
}
}
impl<'a, T> DerefMut for BiLockGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.inner.inner.inner.get() }
}
}
impl<'a, T> Drop for BiLockGuard<'a, T> {
fn drop(&mut self) {
self.inner.unlock();
}
}
pub struct BiLockAcquire<T> {
inner: BiLock<T>,
}
impl<T> Future for BiLockAcquire<T> {
type Item = BiLockAcquired<T>;
type Error = ();
fn poll(&mut self) -> Poll<BiLockAcquired<T>, ()> {
match self.inner.poll_lock() {
Async::Ready(r) => {
mem::forget(r);
Ok(BiLockAcquired {
inner: BiLock { inner: self.inner.inner.clone() },
}.into())
}
Async::NotReady => Ok(Async::NotReady),
}
}
}
pub struct BiLockAcquired<T> {
inner: BiLock<T>,
}
impl<T> BiLockAcquired<T> {
pub fn unlock(self) -> BiLock<T> {
BiLock { inner: self.inner.inner.clone() }
}
}
impl<T> Deref for BiLockAcquired<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.inner.inner.inner.get() }
}
}
impl<T> DerefMut for BiLockAcquired<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.inner.inner.inner.get() }
}
}
impl<T> Drop for BiLockAcquired<T> {
fn drop(&mut self) {
self.inner.unlock();
}
}