#![allow(unused)]
use std::any::Any;
use std::boxed::Box;
use std::cell::UnsafeCell;
use std::error::Error;
use std::fmt;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use futures_core::{Async, Future, Poll};
use futures_core::task::{self, Waker};
#[derive(Debug)]
pub struct BiLock<T> {
inner: Arc<Inner<T>>,
}
#[derive(Debug)]
struct Inner<T> {
state: AtomicUsize,
inner: Option<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: Some(UnsafeCell::new(t)),
});
(BiLock { inner: inner.clone() }, BiLock { inner: inner })
}
pub fn poll_lock(&self, cx: &mut task::Context) -> 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 Waker));
}
}
let me: Box<Waker> = Box::new(cx.waker().clone());
let me = Box::into_raw(me) as usize;
match self.inner.state.compare_exchange(1, me, SeqCst, SeqCst) {
Ok(_) => return Async::Pending,
Err(0) => unsafe {
drop(Box::from_raw(me as *mut Waker));
},
Err(n) => panic!("invalid state: {}", n),
}
}
}
pub fn lock(self) -> BiLockAcquire<T> {
BiLockAcquire {
inner: Some(self),
}
}
pub fn reunite(self, other: Self) -> Result<T, ReuniteError<T>> {
if &*self.inner as *const _ == &*other.inner as *const _ {
drop(other);
let inner = Arc::try_unwrap(self.inner)
.ok()
.expect("futures: try_unwrap failed in BiLock<T>::reunite");
Ok(unsafe { inner.into_inner() })
} else {
Err(ReuniteError(self, other))
}
}
fn unlock(&self) {
match self.inner.state.swap(0, SeqCst) {
0 => panic!("invalid unlocked state"),
1 => {}
n => unsafe {
Box::from_raw(n as *mut Waker).wake();
}
}
}
}
impl<T> Inner<T> {
unsafe fn into_inner(mut self) -> T {
mem::replace(&mut self.inner, None).unwrap().into_inner()
}
}
impl<T> Drop for Inner<T> {
fn drop(&mut self) {
assert_eq!(self.state.load(SeqCst), 0);
}
}
pub struct ReuniteError<T>(pub BiLock<T>, pub BiLock<T>);
impl<T> fmt::Debug for ReuniteError<T> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_tuple("ReuniteError")
.field(&"...")
.finish()
}
}
impl<T> fmt::Display for ReuniteError<T> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "tried to reunite two BiLocks that don't form a pair")
}
}
impl<T: Any> Error for ReuniteError<T> {
fn description(&self) -> &str {
"tried to reunite two BiLocks that don't form a pair"
}
}
#[derive(Debug)]
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.as_ref().unwrap().get() }
}
}
impl<'a, T> DerefMut for BiLockGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.inner.inner.inner.as_ref().unwrap().get() }
}
}
impl<'a, T> Drop for BiLockGuard<'a, T> {
fn drop(&mut self) {
self.inner.unlock();
}
}
#[must_use = "futures do nothing unless polled"]
#[derive(Debug)]
pub struct BiLockAcquire<T> {
inner: Option<BiLock<T>>,
}
impl<T> Future for BiLockAcquire<T> {
type Item = BiLockAcquired<T>;
type Error = ();
fn poll(&mut self, cx: &mut task::Context) -> Poll<BiLockAcquired<T>, ()> {
match self.inner.as_ref().expect("cannot poll after Ready").poll_lock(cx) {
Async::Ready(r) => {
mem::forget(r);
}
Async::Pending => return Ok(Async::Pending),
}
Ok(Async::Ready(BiLockAcquired { inner: self.inner.take() }))
}
}
#[derive(Debug)]
pub struct BiLockAcquired<T> {
inner: Option<BiLock<T>>,
}
impl<T> BiLockAcquired<T> {
pub fn unlock(mut self) -> BiLock<T> {
let bi_lock = self.inner.take().unwrap();
bi_lock.unlock();
bi_lock
}
}
impl<T> Deref for BiLockAcquired<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.inner.as_ref().unwrap().inner.inner.as_ref().unwrap().get() }
}
}
impl<T> DerefMut for BiLockAcquired<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.inner.as_mut().unwrap().inner.inner.as_ref().unwrap().get() }
}
}
impl<T> Drop for BiLockAcquired<T> {
fn drop(&mut self) {
if let Some(ref bi_lock) = self.inner {
bi_lock.unlock();
}
}
}