use std::rc::{Rc, Weak};
use std::cell::RefCell;
use futures::task::{self, Task};
use futures::{Sink, Stream, AsyncSink, Async, Poll, StartSend};
use SendError;
#[derive(Debug)]
pub struct Sender<T> {
inner: Weak<RefCell<Inner<T>>>,
}
#[derive(Debug)]
pub struct Receiver<T> {
inner: Rc<RefCell<Inner<T>>>,
}
#[derive(Debug)]
struct Inner<T> {
value: Option<T>,
read_task: Option<Task>,
cancel_task: Option<Task>,
}
impl<T> Sender<T> {
pub fn swap(&self, value: T) -> Result<Option<T>, SendError<T>> {
let result;
let task = {
if let Some(ref cell) = self.inner.upgrade() {
let mut inner = cell.borrow_mut();
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 cell) = self.inner.upgrade() {
let mut inner = cell.borrow_mut();
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 = self.inner.upgrade()
.and_then(|inner| inner.borrow_mut().read_task.take());
self.inner = Weak::new();
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.borrow_mut();
if inner.value.is_none() {
if Rc::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),
}
}
}
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
let inner = Rc::new(RefCell::new(Inner {
value: None,
read_task: None,
cancel_task: None,
}));
return (Sender { inner: Rc::downgrade(&inner) },
Receiver { inner: inner });
}