#![warn(missing_docs)]
#[cfg(feature = "log")]
#[macro_use]
extern crate log;
#[cfg(feature = "futures")]
extern crate futures;
mod raw;
use std::{mem, ops};
use std::cell::UnsafeCell;
use std::sync::Arc;
#[cfg(feature = "futures")]
use futures::{
Future,
task::{Context, Poll},
};
#[cfg(feature = "futures")]
use std::pin::Pin;
pub struct ReadLockGuard<T> {
_inner: raw::LockGuard,
data: Arc<UnsafeCell<T>>,
}
impl<T> ops::Deref for ReadLockGuard<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe{ mem::transmute(self.data.get()) }
}
}
#[derive(Clone)]
pub struct ReadTicket<T> {
inner: raw::Ticket<raw::Read>,
data: Arc<UnsafeCell<T>>,
}
unsafe impl<T: Send> Send for ReadTicket<T> {}
impl<T> ReadTicket<T> {
pub fn wait(self) -> Result<ReadLockGuard<T>, ()> {
Ok(ReadLockGuard {
_inner: self.inner.wait(),
data: self.data,
})
}
}
#[cfg(feature = "futures")]
impl<T> Future for ReadTicket<T> {
type Output = Result<ReadLockGuard<T>, ()>;
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.inner.check() {
Some(guard) => Poll::Ready(Ok(ReadLockGuard {
_inner: guard,
data: self.data.clone(),
})),
None => Poll::Pending,
}
}
}
pub struct WriteLockGuard<T> {
_inner: raw::LockGuard,
data: Arc<UnsafeCell<T>>,
}
impl<T> ops::Deref for WriteLockGuard<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { mem::transmute(self.data.get()) }
}
}
impl<T> ops::DerefMut for WriteLockGuard<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { mem::transmute(self.data.get()) }
}
}
pub struct WriteTicket<T> {
inner: raw::Ticket<raw::Write>,
data: Arc<UnsafeCell<T>>,
}
unsafe impl<T: Send> Send for WriteTicket<T> {}
impl<T> WriteTicket<T> {
pub fn wait(self) -> Result<WriteLockGuard<T>, ()> {
Ok(WriteLockGuard {
_inner: self.inner.wait(),
data: self.data,
})
}
}
#[cfg(feature = "futures")]
impl<T> Future for WriteTicket<T> {
type Output = Result<WriteLockGuard<T>, ()>;
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.inner.check() {
Some(guard) => Poll::Ready(Ok(WriteLockGuard {
_inner: guard,
data: self.data.clone(),
})),
None => Poll::Pending,
}
}
}
pub struct TicketedLock<T> {
inner: raw::TicketedLock,
data: Arc<UnsafeCell<T>>,
}
unsafe impl<T: Send + Sync> Send for TicketedLock<T> {}
unsafe impl<T: Send + Sync> Sync for TicketedLock<T> {}
impl<T> TicketedLock<T> {
pub fn new(data: T) -> TicketedLock<T> {
TicketedLock {
inner: raw::TicketedLock::new(),
data: Arc::new(UnsafeCell::new(data)),
}
}
pub fn unlock(mut self) -> T {
self.inner.flush();
match Arc::try_unwrap(self.data) {
Ok(data) => data.into_inner(),
Err(_) => panic!("All the locks are supposed to be done after flush()"),
}
}
pub fn read(&mut self) -> ReadTicket<T> {
ReadTicket {
inner: self.inner.read(),
data: self.data.clone(),
}
}
pub fn write(&mut self) -> WriteTicket<T> {
WriteTicket {
inner: self.inner.write(),
data: self.data.clone(),
}
}
}