async_slot/unsync.rs
1//! A single-thread variant of an unbounded channel that only stores
2//! last value sent
3
4use std::rc::{Rc, Weak};
5use std::cell::RefCell;
6
7use futures::task::{self, Task};
8use futures::{Sink, Stream, AsyncSink, Async, Poll, StartSend};
9
10use SendError;
11
12/// Slot is very similar to unbounded channel but only stores last value sent
13///
14/// I.e. if you want to send some value between from producer to a consumer
15/// and if consumer is slow it should skip old values, the slot is
16/// a structure for the task.
17
18/// The transmission end of a channel which is used to send values
19///
20/// If the receiver is not fast enough only the last value is preserved and
21/// other ones are discarded.
22#[derive(Debug)]
23pub struct Sender<T> {
24 inner: Weak<RefCell<Inner<T>>>,
25}
26
27/// The receiving end of a channel which preserves only the last value
28#[derive(Debug)]
29pub struct Receiver<T> {
30 inner: Rc<RefCell<Inner<T>>>,
31}
32
33#[derive(Debug)]
34struct Inner<T> {
35 value: Option<T>,
36 read_task: Option<Task>,
37 cancel_task: Option<Task>,
38}
39
40impl<T> Sender<T> {
41 /// Sets the new new value of the stream and notifies the consumer if any.
42 ///
43 /// This function will store the `value` provided as the current value for
44 /// this channel, replacing any previous value that may have been there. If
45 /// the receiver may still be able to receive this message, then `Ok` is
46 /// returned with the previous value that was in this channel.
47 ///
48 /// If `Ok(Some)` is returned then this value overwrote a previous value,
49 /// and the value was never received by the receiver. If `Ok(None)` is
50 /// returned, then no previous value was found and the `value` is queued up
51 /// to be received by the receiver.
52 ///
53 /// # Errors
54 ///
55 /// This function will return an `Err` if the receiver has gone away and
56 /// it's impossible to send this value to the receiver. The error returned
57 /// retains ownership of the `value` provided and can be extracted, if
58 /// necessary.
59 pub fn swap(&self, value: T) -> Result<Option<T>, SendError<T>> {
60 let result;
61 // Do this step first so that the cell is dropped when
62 // `unpark` is called
63 let task = {
64 if let Some(ref cell) = self.inner.upgrade() {
65 let mut inner = cell.borrow_mut();
66 result = inner.value.take();
67 inner.value = Some(value);
68 inner.read_task.take()
69 } else {
70 return Err(SendError(value));
71 }
72 };
73 if let Some(task) = task {
74 task.notify();
75 }
76 return Ok(result);
77 }
78 /// Polls this `Sender` half to detect whether the `Receiver` this has
79 /// paired with has gone away.
80 ///
81 /// This function can be used to learn about when the `Receiver` (consumer)
82 /// half has gone away and nothing will be able to receive a message sent
83 /// from `send` (or `swap`).
84 ///
85 /// If `Ready` is returned then it means that the `Receiver` has disappeared
86 /// and the result this `Sender` would otherwise produce should no longer
87 /// be produced.
88 ///
89 /// If `NotReady` is returned then the `Receiver` is still alive and may be
90 /// able to receive a message if sent. The current task, however, is
91 /// scheduled to receive a notification if the corresponding `Receiver` goes
92 /// away.
93 ///
94 /// # Panics
95 ///
96 /// Like `Future::poll`, this function will panic if it's not called from
97 /// within the context of a task. In other words, this should only ever be
98 /// called from inside another future.
99 ///
100 /// If you're calling this function from a context that does not have a
101 /// task, then you can use the `is_canceled` API instead.
102 pub fn poll_cancel(&mut self) -> Poll<(), ()> {
103 if let Some(ref cell) = self.inner.upgrade() {
104 let mut inner = cell.borrow_mut();
105 inner.cancel_task = Some(task::current());
106 Ok(Async::NotReady)
107 } else {
108 Ok(Async::Ready(()))
109 }
110 }
111
112 /// Tests to see whether this `Sender`'s corresponding `Receiver`
113 /// has gone away.
114 ///
115 /// This function can be used to learn about when the `Receiver` (consumer)
116 /// half has gone away and nothing will be able to receive a message sent
117 /// from `send`.
118 ///
119 /// Note that this function is intended to *not* be used in the context of a
120 /// future. If you're implementing a future you probably want to call the
121 /// `poll_cancel` function which will block the current task if the
122 /// cancellation hasn't happened yet. This can be useful when working on a
123 /// non-futures related thread, though, which would otherwise panic if
124 /// `poll_cancel` were called.
125 pub fn is_canceled(&self) -> bool {
126 self.inner.upgrade().is_none()
127 }
128}
129
130impl<T> Sink for Sender<T> {
131 type SinkItem = T;
132 type SinkError = SendError<T>;
133 fn start_send(&mut self, item: T) -> StartSend<T, SendError<T>> {
134 self.swap(item)?;
135 Ok(AsyncSink::Ready)
136 }
137 fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
138 Ok(Async::Ready(()))
139 }
140 fn close(&mut self) -> Poll<(), Self::SinkError> {
141 // Do this step first so that the cell is dropped *and*
142 // weakref is dropped when `unpark` is called
143 let task = self.inner.upgrade()
144 .and_then(|inner| inner.borrow_mut().read_task.take());
145 self.inner = Weak::new();
146 // notify on any drop of a sender, so eventually receiver wakes up
147 // when there are no senders and closes the stream
148 if let Some(task) = task {
149 task.notify();
150 }
151 Ok(Async::Ready(()))
152 }
153}
154
155impl<T> Drop for Sender<T> {
156 fn drop(&mut self) {
157 self.close().ok();
158 }
159}
160
161impl<T> Stream for Receiver<T> {
162 type Item = T;
163 type Error = (); // actually void
164 fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
165 let result = {
166 let mut inner = self.inner.borrow_mut();
167 if inner.value.is_none() {
168 if Rc::weak_count(&self.inner) == 0 {
169 // no senders, terminate the stream
170 return Ok(Async::Ready(None));
171 } else {
172 inner.read_task = Some(task::current());
173 }
174 }
175 inner.value.take()
176 };
177 match result {
178 Some(value) => Ok(Async::Ready(Some(value))),
179 None => Ok(Async::NotReady),
180 }
181 }
182}
183
184/// Creates an in-memory Stream which only preserves last value
185///
186/// This method is somewhat similar to `channel(1)` but instead of preserving
187/// first value sent (and erroring on sender side) it replaces value if
188/// consumer is not fast enough and preserves last values sent on any
189/// poll of a stream.
190///
191/// # Example
192///
193/// ```
194/// extern crate futures;
195/// extern crate async_slot;
196///
197/// use futures::prelude::*;
198/// use futures::stream::iter_ok;
199///
200/// # fn main() {
201/// let (tx, rx) = async_slot::unsync::channel::<i32>();
202///
203/// tx.send_all(iter_ok(vec![1, 2, 3])).wait();
204///
205/// let received = rx.collect().wait().unwrap();
206/// assert_eq!(received, vec![3]);
207/// # }
208/// ```
209pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
210 let inner = Rc::new(RefCell::new(Inner {
211 value: None,
212 read_task: None,
213 cancel_task: None,
214 }));
215 return (Sender { inner: Rc::downgrade(&inner) },
216 Receiver { inner: inner });
217}