use loom::{
futures::task::{self, Task},
sync::atomic::AtomicUsize,
sync::CausalCell,
};
use futures::{Async, Future, Poll};
use std::fmt;
use std::mem::{self, ManuallyDrop};
use std::sync::atomic::Ordering::{self, AcqRel, Acquire};
use std::sync::Arc;
#[derive(Debug)]
pub struct Sender<T> {
inner: Option<Arc<Inner<T>>>,
}
#[derive(Debug)]
pub struct Receiver<T> {
inner: Option<Arc<Inner<T>>>,
}
pub mod error {
use std::fmt;
#[derive(Debug)]
pub struct RecvError(pub(super) ());
#[derive(Debug)]
pub struct TryRecvError(pub(super) ());
impl fmt::Display for RecvError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
use std::error::Error;
write!(fmt, "{}", self.description())
}
}
impl ::std::error::Error for RecvError {
fn description(&self) -> &str {
"channel closed"
}
}
impl fmt::Display for TryRecvError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
use std::error::Error;
write!(fmt, "{}", self.description())
}
}
impl ::std::error::Error for TryRecvError {
fn description(&self) -> &str {
"channel closed"
}
}
}
use self::error::*;
struct Inner<T> {
state: AtomicUsize,
value: CausalCell<Option<T>>,
tx_task: CausalCell<ManuallyDrop<Task>>,
rx_task: CausalCell<ManuallyDrop<Task>>,
}
#[derive(Clone, Copy)]
struct State(usize);
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
let inner = Arc::new(Inner {
state: AtomicUsize::new(State::new().as_usize()),
value: CausalCell::new(None),
tx_task: CausalCell::new(ManuallyDrop::new(unsafe { mem::uninitialized() })),
rx_task: CausalCell::new(ManuallyDrop::new(unsafe { mem::uninitialized() })),
});
let tx = Sender {
inner: Some(inner.clone()),
};
let rx = Receiver { inner: Some(inner) };
(tx, rx)
}
impl<T> Sender<T> {
pub fn send(mut self, t: T) -> Result<(), T> {
let inner = self.inner.take().unwrap();
inner.value.with_mut(|ptr| unsafe {
*ptr = Some(t);
});
if !inner.complete() {
return Err(inner
.value
.with_mut(|ptr| unsafe { (*ptr).take() }.unwrap()));
}
Ok(())
}
pub fn poll_close(&mut self) -> Poll<(), ()> {
let inner = self.inner.as_ref().unwrap();
let mut state = State::load(&inner.state, Acquire);
if state.is_closed() {
return Ok(Async::Ready(()));
}
if state.is_tx_task_set() {
let will_notify = inner
.tx_task
.with(|ptr| unsafe { (&*ptr).will_notify_current() });
if !will_notify {
state = State::unset_tx_task(&inner.state);
if state.is_closed() {
State::set_tx_task(&inner.state);
return Ok(Async::Ready(()));
} else {
unsafe { inner.drop_tx_task() };
}
}
}
if !state.is_tx_task_set() {
unsafe {
inner.set_tx_task();
}
state = State::set_tx_task(&inner.state);
if state.is_closed() {
return Ok(Async::Ready(()));
}
}
Ok(Async::NotReady)
}
pub fn is_closed(&self) -> bool {
let inner = self.inner.as_ref().unwrap();
let state = State::load(&inner.state, Acquire);
state.is_closed()
}
}
impl<T> Drop for Sender<T> {
fn drop(&mut self) {
if let Some(inner) = self.inner.as_ref() {
inner.complete();
}
}
}
impl<T> Receiver<T> {
pub fn close(&mut self) {
let inner = self.inner.as_ref().unwrap();
inner.close();
}
pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
let result = if let Some(inner) = self.inner.as_ref() {
let state = State::load(&inner.state, Acquire);
if state.is_complete() {
match unsafe { inner.consume_value() } {
Some(value) => Ok(value),
None => Err(TryRecvError(())),
}
} else if state.is_closed() {
Err(TryRecvError(()))
} else {
return Err(TryRecvError(()));
}
} else {
panic!("called after complete");
};
self.inner = None;
result
}
}
impl<T> Drop for Receiver<T> {
fn drop(&mut self) {
if let Some(inner) = self.inner.as_ref() {
inner.close();
}
}
}
impl<T> Future for Receiver<T> {
type Item = T;
type Error = RecvError;
fn poll(&mut self) -> Poll<T, RecvError> {
use futures::Async::{NotReady, Ready};
let ret = if let Some(inner) = self.inner.as_ref() {
match inner.poll_recv() {
Ok(Ready(v)) => Ok(Ready(v)),
Ok(NotReady) => return Ok(NotReady),
Err(e) => Err(e),
}
} else {
panic!("called after complete");
};
self.inner = None;
ret
}
}
impl<T> Inner<T> {
fn complete(&self) -> bool {
let prev = State::set_complete(&self.state);
if prev.is_closed() {
return false;
}
if prev.is_rx_task_set() {
self.rx_task.with(|ptr| unsafe { (&*ptr).notify() });
}
true
}
fn poll_recv(&self) -> Poll<T, RecvError> {
use futures::Async::{NotReady, Ready};
let mut state = State::load(&self.state, Acquire);
if state.is_complete() {
match unsafe { self.consume_value() } {
Some(value) => Ok(Ready(value)),
None => Err(RecvError(())),
}
} else if state.is_closed() {
Err(RecvError(()))
} else {
if state.is_rx_task_set() {
let will_notify = self
.rx_task
.with(|ptr| unsafe { (&*ptr).will_notify_current() });
if !will_notify {
state = State::unset_rx_task(&self.state);
if state.is_complete() {
State::set_rx_task(&self.state);
return match unsafe { self.consume_value() } {
Some(value) => Ok(Ready(value)),
None => Err(RecvError(())),
};
} else {
unsafe { self.drop_rx_task() };
}
}
}
if !state.is_rx_task_set() {
unsafe {
self.set_rx_task();
}
state = State::set_rx_task(&self.state);
if state.is_complete() {
match unsafe { self.consume_value() } {
Some(value) => Ok(Ready(value)),
None => Err(RecvError(())),
}
} else {
return Ok(NotReady);
}
} else {
return Ok(NotReady);
}
}
}
fn close(&self) {
let prev = State::set_closed(&self.state);
if prev.is_tx_task_set() && !prev.is_complete() {
self.tx_task.with(|ptr| unsafe { (&*ptr).notify() });
}
}
unsafe fn consume_value(&self) -> Option<T> {
self.value.with_mut(|ptr| (*ptr).take())
}
unsafe fn drop_rx_task(&self) {
self.rx_task.with_mut(|ptr| ManuallyDrop::drop(&mut *ptr))
}
unsafe fn drop_tx_task(&self) {
self.tx_task.with_mut(|ptr| ManuallyDrop::drop(&mut *ptr))
}
unsafe fn set_rx_task(&self) {
self.rx_task
.with_mut(|ptr| *ptr = ManuallyDrop::new(task::current()));
}
unsafe fn set_tx_task(&self) {
self.tx_task
.with_mut(|ptr| *ptr = ManuallyDrop::new(task::current()));
}
}
unsafe impl<T: Send> Send for Inner<T> {}
unsafe impl<T: Send> Sync for Inner<T> {}
impl<T> Drop for Inner<T> {
fn drop(&mut self) {
let state = State(*self.state.get_mut());
if state.is_rx_task_set() {
self.rx_task.with_mut(|ptr| unsafe {
ManuallyDrop::drop(&mut *ptr);
});
}
if state.is_tx_task_set() {
self.tx_task.with_mut(|ptr| unsafe {
ManuallyDrop::drop(&mut *ptr);
});
}
}
}
impl<T: fmt::Debug> fmt::Debug for Inner<T> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
use std::sync::atomic::Ordering::Relaxed;
fmt.debug_struct("Inner")
.field("state", &State::load(&self.state, Relaxed))
.finish()
}
}
const RX_TASK_SET: usize = 0b00001;
const VALUE_SENT: usize = 0b00010;
const CLOSED: usize = 0b00100;
const TX_TASK_SET: usize = 0b01000;
impl State {
fn new() -> State {
State(0)
}
fn is_complete(&self) -> bool {
self.0 & VALUE_SENT == VALUE_SENT
}
fn set_complete(cell: &AtomicUsize) -> State {
let val = cell.fetch_or(VALUE_SENT, AcqRel);
State(val)
}
fn is_rx_task_set(&self) -> bool {
self.0 & RX_TASK_SET == RX_TASK_SET
}
fn set_rx_task(cell: &AtomicUsize) -> State {
let val = cell.fetch_or(RX_TASK_SET, AcqRel);
State(val | RX_TASK_SET)
}
fn unset_rx_task(cell: &AtomicUsize) -> State {
let val = cell.fetch_and(!RX_TASK_SET, AcqRel);
State(val & !RX_TASK_SET)
}
fn is_closed(&self) -> bool {
self.0 & CLOSED == CLOSED
}
fn set_closed(cell: &AtomicUsize) -> State {
let val = cell.fetch_or(CLOSED, Acquire);
State(val)
}
fn set_tx_task(cell: &AtomicUsize) -> State {
let val = cell.fetch_or(TX_TASK_SET, AcqRel);
State(val | TX_TASK_SET)
}
fn unset_tx_task(cell: &AtomicUsize) -> State {
let val = cell.fetch_and(!TX_TASK_SET, AcqRel);
State(val & !TX_TASK_SET)
}
fn is_tx_task_set(&self) -> bool {
self.0 & TX_TASK_SET == TX_TASK_SET
}
fn as_usize(self) -> usize {
self.0
}
fn load(cell: &AtomicUsize, order: Ordering) -> State {
let val = cell.load(order);
State(val)
}
}
impl fmt::Debug for State {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("State")
.field("is_complete", &self.is_complete())
.field("is_closed", &self.is_closed())
.field("is_rx_task_set", &self.is_rx_task_set())
.field("is_tx_task_set", &self.is_tx_task_set())
.finish()
}
}