use std::sync::Arc;
use parking_lot::{Mutex, MutexGuard};
use futures::{Async, Future, Poll};
use std::mem;
#[derive(Debug)]
pub struct MultiLock<T> {
inner: Arc<Mutex<T>>,
}
impl<T> MultiLock<T> {
pub fn new(t: T) -> Self {
let inner = Arc::new(Mutex::new(t));
MultiLock { inner }
}
pub fn poll_lock(&self) -> Async<MutexGuard<T>> {
match self.inner.try_lock() {
None => Async::NotReady,
Some(lock) => Async::Ready(lock),
}
}
pub fn lock(self) -> MultiLockAcquire<T> {
MultiLockAcquire {
inner: Some(self),
}
}
unsafe fn force_unlock(&self) {
self.inner.force_unlock()
}
}
impl<T> Clone for MultiLock<T> {
#[inline]
fn clone(&self) -> Self {
MultiLock {
inner: self.inner.clone()
}
}
}
#[derive(Debug)]
pub struct MultiLockAcquire<T> {
inner: Option<MultiLock<T>>,
}
impl<T> Future for MultiLockAcquire<T> {
type Item = MultiLockAcquired<T>;
type Error = ();
fn poll(&mut self) -> Poll<MultiLockAcquired<T>, ()> {
match self.inner.as_ref().expect("cannot poll after Ready").poll_lock() {
Async::Ready(r) => {
mem::forget(r);
},
Async::NotReady => return Ok(Async::NotReady),
}
Ok(Async::Ready(MultiLockAcquired { inner: self.inner.take() }))
}
}
#[derive(Debug)]
pub struct MultiLockAcquired<T> {
inner: Option<MultiLock<T>>,
}
impl<T> MultiLockAcquired<T> {
pub fn unlock(mut self) -> MultiLock<T> {
let multi_lock = self.inner.take().unwrap();
unsafe { multi_lock.force_unlock() };
multi_lock
}
}