use std::mem;
use std::sync::{Arc, Weak, Mutex};
use futures::task::{self, Task};
use futures::{Sink, Stream, AsyncSink, Async, Poll, StartSend};
use SendError;
#[derive(Debug)]
pub struct Sender<T> {
inner: Weak<Mutex<Inner<T>>>,
}
#[derive(Debug)]
pub struct Receiver<T> {
inner: Arc<Mutex<Inner<T>>>,
}
#[derive(Debug)]
struct Inner<T> {
value: Option<T>,
read_task: Option<Task>,
cancel_task: Option<Task>,
}
trait AssertKindsSender: Send + Sync {}
impl AssertKindsSender for Sender<u32> {}
trait AssertKindsReceiver: Send + Sync {}
impl AssertKindsReceiver for Receiver<u32> {}
impl<T> Sender<T> {
pub fn swap(&self, value: T) -> Result<Option<T>, SendError<T>> {
let result;
let task = {
if let Some(ref lock) = self.inner.upgrade() {
let mut inner = lock.lock().unwrap();
result = inner.value.take();
inner.value = Some(value);
inner.read_task.take()
} else {
return Err(SendError(value));
}
};
if let Some(task) = task {
task.notify();
}
return Ok(result);
}
pub fn poll_cancel(&mut self) -> Poll<(), ()> {
if let Some(ref lock) = self.inner.upgrade() {
let mut inner = lock.lock().unwrap();
inner.cancel_task = Some(task::current());
Ok(Async::NotReady)
} else {
Ok(Async::Ready(()))
}
}
pub fn is_canceled(&self) -> bool {
self.inner.upgrade().is_none()
}
}
impl<T> Sink for Sender<T> {
type SinkItem = T;
type SinkError = SendError<T>;
fn start_send(&mut self, item: T) -> StartSend<T, SendError<T>> {
self.swap(item)?;
Ok(AsyncSink::Ready)
}
fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
Ok(Async::Ready(()))
}
fn close(&mut self) -> Poll<(), Self::SinkError> {
let task = {
let weak = mem::replace(&mut self.inner, Weak::new());
if let Some(ref lock) = weak.upgrade() {
drop(weak);
let mut inner = lock.lock().unwrap();
inner.read_task.take()
} else {
None
}
};
if let Some(task) = task {
task.notify();
}
Ok(Async::Ready(()))
}
}
impl<T> Drop for Sender<T> {
fn drop(&mut self) {
self.close().ok();
}
}
impl<T> Stream for Receiver<T> {
type Item = T;
type Error = (); fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
let result = {
let mut inner = self.inner.lock().unwrap();
if inner.value.is_none() {
if Arc::weak_count(&self.inner) == 0 {
return Ok(Async::Ready(None));
} else {
inner.read_task = Some(task::current());
}
}
inner.value.take()
};
match result {
Some(value) => Ok(Async::Ready(Some(value))),
None => Ok(Async::NotReady),
}
}
}
impl<T> SendError<T> {
pub fn into_inner(self) -> T {
self.0
}
}
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
let inner = Arc::new(Mutex::new(Inner {
value: None,
read_task: None,
cancel_task: None,
}));
return (Sender { inner: Arc::downgrade(&inner) },
Receiver { inner: inner });
}