1use std::cell::RefCell;
5use std::collections::VecDeque;
6use std::future::Future;
7use std::pin::Pin;
8use std::rc::Rc;
9use std::task::{Context, Poll, Waker};
10
11struct QInner<T> {
12 buf: RefCell<VecDeque<T>>,
13 cap: Option<usize>, get_waiters: RefCell<Vec<Waker>>,
15 put_waiters: RefCell<Vec<Waker>>,
16}
17
18impl<T> QInner<T> {
19 fn has_space(&self) -> bool {
20 match self.cap {
21 None => true,
22 Some(c) => self.buf.borrow().len() < c,
23 }
24 }
25 fn wake_getters(&self) {
26 for w in self.get_waiters.borrow_mut().drain(..) {
27 w.wake();
28 }
29 }
30 fn wake_putters(&self) {
31 for w in self.put_waiters.borrow_mut().drain(..) {
32 w.wake();
33 }
34 }
35}
36
37pub struct Queue<T> {
39 inner: Rc<QInner<T>>,
40}
41
42impl<T> Clone for Queue<T> {
43 fn clone(&self) -> Self {
44 Queue {
45 inner: self.inner.clone(),
46 }
47 }
48}
49
50impl<T> Queue<T> {
51 pub fn new(cap: Option<usize>) -> Queue<T> {
53 Queue {
54 inner: Rc::new(QInner {
55 buf: RefCell::new(VecDeque::new()),
56 cap,
57 get_waiters: RefCell::new(Vec::new()),
58 put_waiters: RefCell::new(Vec::new()),
59 }),
60 }
61 }
62
63 pub fn unbounded() -> Queue<T> {
64 Self::new(None)
65 }
66
67 pub fn len(&self) -> usize {
68 self.inner.buf.borrow().len()
69 }
70 pub fn is_empty(&self) -> bool {
71 self.inner.buf.borrow().is_empty()
72 }
73
74 pub fn has_space(&self) -> bool {
77 self.inner.has_space()
78 }
79
80 pub fn try_put(&self, item: T) -> Result<(), T> {
81 if self.inner.has_space() {
82 self.inner.buf.borrow_mut().push_back(item);
83 self.inner.wake_getters();
84 Ok(())
85 } else {
86 Err(item)
87 }
88 }
89
90 pub fn try_get(&self) -> Option<T> {
91 let item = self.inner.buf.borrow_mut().pop_front();
92 if item.is_some() {
93 self.inner.wake_putters();
94 }
95 item
96 }
97
98 pub fn put(&self, item: T) -> Put<T> {
99 Put {
100 inner: self.inner.clone(),
101 item: Some(item),
102 }
103 }
104
105 pub fn get(&self) -> Get<T> {
106 Get {
107 inner: self.inner.clone(),
108 }
109 }
110
111 pub fn wait_for_space(&self) -> Space<T> {
124 Space {
125 inner: self.inner.clone(),
126 }
127 }
128}
129
130pub struct Space<T> {
132 inner: Rc<QInner<T>>,
133}
134
135impl<T> Future for Space<T> {
136 type Output = ();
137 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
138 if self.inner.has_space() {
139 Poll::Ready(())
140 } else {
141 self.inner.put_waiters.borrow_mut().push(cx.waker().clone());
142 Poll::Pending
143 }
144 }
145}
146
147impl<T: Clone> Queue<T> {
148 pub fn try_peek(&self) -> Option<T> {
154 self.inner.buf.borrow().front().cloned()
155 }
156
157 pub fn peek(&self) -> Peek<T> {
159 Peek {
160 inner: self.inner.clone(),
161 }
162 }
163}
164
165pub struct Peek<T> {
166 inner: Rc<QInner<T>>,
167}
168
169impl<T: Clone> Future for Peek<T> {
170 type Output = T;
171 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
172 let item = self.inner.buf.borrow().front().cloned();
173 match item {
174 Some(v) => Poll::Ready(v),
176 None => {
177 self.inner.get_waiters.borrow_mut().push(cx.waker().clone());
178 Poll::Pending
179 }
180 }
181 }
182}
183
184pub struct Put<T> {
185 inner: Rc<QInner<T>>,
186 item: Option<T>,
187}
188
189impl<T> Future for Put<T> {
190 type Output = ();
191 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
192 let this = unsafe { self.get_unchecked_mut() };
196 if this.inner.has_space() {
197 let item = this.item.take().expect("Put polled after completion");
198 this.inner.buf.borrow_mut().push_back(item);
199 this.inner.wake_getters();
200 Poll::Ready(())
201 } else {
202 this.inner.put_waiters.borrow_mut().push(cx.waker().clone());
203 Poll::Pending
204 }
205 }
206}
207
208pub struct Get<T> {
209 inner: Rc<QInner<T>>,
210}
211
212impl<T> Future for Get<T> {
213 type Output = T;
214 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
215 let item = self.inner.buf.borrow_mut().pop_front();
216 match item {
217 Some(v) => {
218 self.inner.wake_putters();
219 Poll::Ready(v)
220 }
221 None => {
222 self.inner.get_waiters.borrow_mut().push(cx.waker().clone());
223 Poll::Pending
224 }
225 }
226 }
227}
228
229#[cfg(test)]
234mod tests {
235 use super::*;
236 use crate::testing::{assert_pending, block_on};
237
238 #[test]
239 fn put_get_round_trips_in_order() {
240 block_on(async {
241 let q: Queue<u8> = Queue::unbounded();
242 for n in 0..5 {
243 q.put(n).await;
244 }
245 for n in 0..5 {
246 assert_eq!(q.get().await, n, "a queue is FIFO");
247 }
248 });
249 }
250
251 #[test]
254 fn try_put_on_a_full_queue_returns_the_item() {
255 block_on(async {
256 let q: Queue<String> = Queue::new(Some(1));
257 assert!(q.try_put(String::from("first")).is_ok());
258 match q.try_put(String::from("second")) {
259 Err(back) => assert_eq!(back, "second", "the item comes home"),
260 Ok(()) => panic!("a depth-1 queue accepted a second item"),
261 }
262 });
263 }
264
265 #[test]
266 fn try_get_on_an_empty_queue_is_none() {
267 block_on(async {
268 let q: Queue<u8> = Queue::unbounded();
269 assert!(q.try_get().is_none());
270 q.put(1).await;
271 assert_eq!(q.try_get(), Some(1));
272 assert!(q.try_get().is_none(), "and it was consumed");
273 });
274 }
275
276 #[test]
277 fn a_blocked_get_wakes_on_a_put() {
278 block_on(async {
279 let q: Queue<u8> = Queue::unbounded();
280 let producer = q.clone();
281 crate::executor::spawn(async move {
282 producer.put(42).await;
283 });
284 assert_eq!(q.get().await, 42, "the get was waiting before the put");
285 });
286 }
287
288 #[test]
289 fn a_blocked_put_wakes_when_space_appears() {
290 block_on(async {
291 let q: Queue<u8> = Queue::new(Some(1));
292 q.put(1).await;
293 let consumer = q.clone();
294 crate::executor::spawn(async move {
295 let _ = consumer.get().await;
296 });
297 q.put(2).await; assert_eq!(q.len(), 1);
299 });
300 }
301
302 #[test]
303 fn a_get_on_an_empty_queue_waits() {
304 let q: Queue<u8> = Queue::unbounded();
305 assert_pending(async move { q.get().await });
306 }
307
308 #[test]
311 fn peek_does_not_consume() {
312 block_on(async {
313 let q: Queue<u8> = Queue::unbounded();
314 q.put(9).await;
315 assert_eq!(q.peek().await, 9);
316 assert_eq!(q.len(), 1, "peek left it there");
317 assert_eq!(q.get().await, 9, "and get takes the same item");
318 });
319 }
320
321 #[test]
322 fn try_peek_is_none_when_empty() {
323 block_on(async {
324 let q: Queue<u8> = Queue::unbounded();
325 assert!(q.try_peek().is_none());
326 q.put(3).await;
327 assert_eq!(q.try_peek(), Some(3));
328 assert_eq!(q.len(), 1);
329 });
330 }
331
332 #[test]
333 fn has_space_agrees_with_len() {
334 block_on(async {
335 let q: Queue<u8> = Queue::new(Some(2));
336 assert!(q.has_space());
337 q.put(1).await;
338 assert!(q.has_space());
339 q.put(2).await;
340 assert!(!q.has_space(), "full at its declared depth");
341 assert_eq!(q.len(), 2);
342 });
343 }
344
345 #[test]
346 fn wait_for_space_returns_when_drained() {
347 block_on(async {
348 let q: Queue<u8> = Queue::new(Some(1));
349 q.put(1).await;
350 let consumer = q.clone();
351 crate::executor::spawn(async move {
352 let _ = consumer.get().await;
353 });
354 q.wait_for_space().await;
355 assert!(q.has_space());
356 });
357 }
358
359 #[test]
360 fn unbounded_never_blocks_a_put() {
361 block_on(async {
362 let q: Queue<u32> = Queue::unbounded();
363 for n in 0..1000 {
364 assert!(q.try_put(n).is_ok(), "an unbounded queue always has room");
365 }
366 assert_eq!(q.len(), 1000);
367 });
368 }
369
370 #[test]
371 fn is_empty_tracks_contents() {
372 block_on(async {
373 let q: Queue<u8> = Queue::unbounded();
374 assert!(q.is_empty());
375 q.put(1).await;
376 assert!(!q.is_empty());
377 let _ = q.get().await;
378 assert!(q.is_empty());
379 });
380 }
381
382 #[test]
385 fn a_dropped_get_consumes_nothing() {
386 block_on(async {
387 let q: Queue<u8> = Queue::unbounded();
388 {
389 let pending = q.get();
390 drop(pending);
391 }
392 q.put(5).await;
393 assert_eq!(q.get().await, 5, "the item survived the dropped get");
394 });
395 }
396}