1use core::ops::{Deref, DerefMut};
4use futures::{
5 StreamExt,
6 future::{self, AbortHandle, Abortable, Aborted},
7 stream::{FuturesUnordered, SelectNextSome},
8};
9use pin_project::pin_project;
10use std::{collections::BTreeMap, future::Future, pin::Pin, task::Poll};
11
12type PooledFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
14
15pub struct Pool<'a, T> {
22 pool: FuturesUnordered<PooledFuture<'a, T>>,
23}
24
25impl<'a, T: Send> Default for Pool<'a, T> {
26 fn default() -> Self {
27 let pool = FuturesUnordered::new();
30 pool.push(Self::create_dummy_future());
31 Self { pool }
32 }
33}
34
35impl<'a, T: Send> Pool<'a, T> {
36 pub fn len(&self) -> usize {
38 self.pool.len().checked_sub(1).unwrap()
40 }
41
42 pub fn is_empty(&self) -> bool {
44 self.len() == 0
45 }
46
47 pub fn push(&mut self, future: impl Future<Output = T> + Send + 'a) {
51 self.pool.push(Box::pin(future));
52 }
53
54 pub fn next_completed(&mut self) -> SelectNextSome<'_, FuturesUnordered<PooledFuture<'a, T>>> {
58 self.pool.select_next_some()
59 }
60
61 pub fn cancel_all(&mut self) {
65 self.pool.clear();
66 self.pool.push(Self::create_dummy_future());
67 }
68
69 fn create_dummy_future() -> PooledFuture<'a, T> {
71 Box::pin(async { future::pending::<T>().await })
72 }
73}
74
75pub struct Aborter {
79 inner: AbortHandle,
80}
81
82impl Drop for Aborter {
83 fn drop(&mut self) {
84 self.inner.abort();
85 }
86}
87
88type AbortablePooledFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T, Aborted>> + Send + 'a>>;
90
91pub struct AbortablePool<'a, T> {
99 pool: FuturesUnordered<AbortablePooledFuture<'a, T>>,
100}
101
102impl<'a, T: Send> Default for AbortablePool<'a, T> {
103 fn default() -> Self {
104 let pool = FuturesUnordered::new();
107 pool.push(Self::create_dummy_future());
108 Self { pool }
109 }
110}
111
112impl<'a, T: Send> AbortablePool<'a, T> {
113 pub fn len(&self) -> usize {
115 self.pool.len().checked_sub(1).unwrap()
117 }
118
119 pub fn is_empty(&self) -> bool {
121 self.len() == 0
122 }
123
124 pub fn push(&mut self, future: impl Future<Output = T> + Send + 'a) -> Aborter {
129 let (handle, registration) = AbortHandle::new_pair();
130 let abortable_future = Abortable::new(future, registration);
131 self.pool.push(Box::pin(abortable_future));
132 Aborter { inner: handle }
133 }
134
135 pub fn next_completed(
140 &mut self,
141 ) -> SelectNextSome<'_, FuturesUnordered<AbortablePooledFuture<'a, T>>> {
142 self.pool.select_next_some()
143 }
144
145 fn create_dummy_future() -> AbortablePooledFuture<'a, T> {
147 Box::pin(async { Ok(future::pending::<T>().await) })
148 }
149}
150
151#[pin_project]
157pub struct OptionFuture<F: Future>(#[pin] Option<F>);
158
159impl<F: Future> Default for OptionFuture<F> {
160 fn default() -> Self {
161 Self(None)
162 }
163}
164
165impl<F: Future> From<Option<F>> for OptionFuture<F> {
166 fn from(opt: Option<F>) -> Self {
167 Self(opt)
168 }
169}
170
171impl<F: Future> Deref for OptionFuture<F> {
172 type Target = Option<F>;
173
174 fn deref(&self) -> &Self::Target {
175 &self.0
176 }
177}
178
179impl<F: Future> DerefMut for OptionFuture<F> {
180 fn deref_mut(&mut self) -> &mut Self::Target {
181 &mut self.0
182 }
183}
184
185impl<F: Future> Future for OptionFuture<F> {
186 type Output = F::Output;
187
188 fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
189 let this = self.project();
190 this.0
191 .as_pin_mut()
192 .map_or_else(|| Poll::Pending, |fut| fut.poll(cx))
193 }
194}
195
196pub trait Threaded<T> {
198 type Rest;
200
201 fn split(self) -> (T, Self::Rest);
203}
204
205impl<T> Threaded<T> for T {
206 type Rest = ();
207
208 fn split(self) -> (T, ()) {
209 (self, ())
210 }
211}
212
213impl<T, A> Threaded<T> for (T, A) {
214 type Rest = A;
215
216 fn split(self) -> (T, A) {
217 self
218 }
219}
220
221impl<T, A, B> Threaded<T> for (T, A, B) {
222 type Rest = (A, B);
223
224 fn split(self) -> (T, (A, B)) {
225 let (value, a, b) = self;
226 (value, (a, b))
227 }
228}
229
230pub async fn rebind<T, Out, Fut, E>(
240 slot: &mut Option<T>,
241 op: impl FnOnce(T) -> Fut,
242) -> Result<Out::Rest, E>
243where
244 Out: Threaded<T>,
245 Fut: Future<Output = Result<Out, E>>,
246{
247 let value = slot.take().expect("cannot rebind an empty slot");
248 let (value, rest) = op(value).await?.split();
249 *slot = Some(value);
250 Ok(rest)
251}
252
253pub async fn rebind_entry<K, V, Out, Fut, E>(
263 map: &mut BTreeMap<K, V>,
264 key: &K,
265 op: impl FnOnce(V) -> Fut,
266) -> Result<Out::Rest, E>
267where
268 K: Ord,
269 Out: Threaded<V>,
270 Fut: Future<Output = Result<Out, E>>,
271{
272 let (key, value) = map
273 .remove_entry(key)
274 .expect("cannot rebind a missing entry");
275 let (value, rest) = op(value).await?.split();
276 map.insert(key, value);
277 Ok(rest)
278}
279
280#[cfg(test)]
281mod tests {
282 use super::*;
283 use crate::channel::oneshot;
284 use futures::{
285 executor::block_on,
286 future::{self, Either, select},
287 pin_mut,
288 };
289 use std::{
290 sync::{
291 Arc,
292 atomic::{AtomicBool, Ordering},
293 },
294 thread,
295 time::Duration,
296 };
297
298 fn delay(duration: Duration) -> impl Future<Output = ()> {
300 let (sender, receiver) = oneshot::channel();
301 thread::spawn(move || {
302 thread::sleep(duration);
303 sender.send(()).unwrap();
304 });
305 async move {
306 let _ = receiver.await;
307 }
308 }
309
310 #[test]
311 fn test_initialization() {
312 let pool = Pool::<i32>::default();
313 assert_eq!(pool.len(), 0);
314 assert!(pool.is_empty());
315 }
316
317 #[test]
318 fn test_dummy_future_doesnt_resolve() {
319 block_on(async {
320 let mut pool = Pool::<i32>::default();
321 let stream_future = pool.next_completed();
322 let timeout_future = async {
323 delay(Duration::from_millis(100)).await;
324 };
325 pin_mut!(stream_future);
326 pin_mut!(timeout_future);
327 let result = select(stream_future, timeout_future).await;
328 match result {
329 Either::Left((_, _)) => panic!("Stream resolved unexpectedly"),
330 Either::Right((_, _)) => {
331 }
333 }
334 });
335 }
336
337 #[test]
338 fn test_adding_futures() {
339 let mut pool = Pool::<i32>::default();
340 assert_eq!(pool.len(), 0);
341 assert!(pool.is_empty());
342
343 pool.push(async { 42 });
344 assert_eq!(pool.len(), 1);
345 assert!(!pool.is_empty(),);
346
347 pool.push(async { 43 });
348 assert_eq!(pool.len(), 2,);
349 }
350
351 #[test]
352 fn test_streaming_resolved_futures() {
353 block_on(async move {
354 let mut pool = Pool::<i32>::default();
355 pool.push(future::ready(42));
356 let result = pool.next_completed().await;
357 assert_eq!(result, 42,);
358 assert!(pool.is_empty(),);
359 });
360 }
361
362 #[test]
363 fn test_multiple_futures() {
364 block_on(async move {
365 let mut pool = Pool::<i32>::default();
366
367 let (finisher_1, finished_1) = oneshot::channel();
369 let (finisher_3, finished_3) = oneshot::channel();
370 pool.push(async move {
371 finished_1.await.unwrap();
372 finisher_3.send(()).unwrap();
373 1
374 });
375 pool.push(async move {
376 finisher_1.send(()).unwrap();
377 2
378 });
379 pool.push(async move {
380 finished_3.await.unwrap();
381 3
382 });
383
384 let first = pool.next_completed().await;
385 assert_eq!(first, 2, "First resolved should be 2");
386 let second = pool.next_completed().await;
387 assert_eq!(second, 1, "Second resolved should be 1");
388 let third = pool.next_completed().await;
389 assert_eq!(third, 3, "Third resolved should be 3");
390 assert!(pool.is_empty(),);
391 });
392 }
393
394 #[test]
395 fn test_cancel_all() {
396 block_on(async move {
397 let flag = Arc::new(AtomicBool::new(false));
398 let flag_clone = flag.clone();
399 let mut pool = Pool::<i32>::default();
400
401 let (finisher, finished) = oneshot::channel();
403 pool.push(async move {
404 finished.await.unwrap();
405 flag_clone.store(true, Ordering::SeqCst);
406 42
407 });
408 assert_eq!(pool.len(), 1);
409
410 pool.cancel_all();
412 assert!(pool.is_empty());
413 assert!(!flag.load(Ordering::SeqCst));
414
415 let _ = finisher.send(());
417
418 let stream_future = pool.next_completed();
420 let timeout_future = async {
421 delay(Duration::from_millis(100)).await;
422 };
423 pin_mut!(stream_future);
424 pin_mut!(timeout_future);
425 let result = select(stream_future, timeout_future).await;
426 match result {
427 Either::Left((_, _)) => panic!("Stream resolved after cancellation"),
428 Either::Right((_, _)) => {
429 }
431 }
432 assert!(!flag.load(Ordering::SeqCst));
433
434 pool.push(future::ready(42));
436 assert_eq!(pool.len(), 1);
437 let result = pool.next_completed().await;
438 assert_eq!(result, 42);
439 assert!(pool.is_empty());
440 });
441 }
442
443 #[test]
444 fn test_many_futures() {
445 block_on(async move {
446 let mut pool = Pool::<i32>::default();
447 let num_futures = 1000;
448 for i in 0..num_futures {
449 pool.push(future::ready(i));
450 }
451 assert_eq!(pool.len(), num_futures as usize);
452
453 let mut sum = 0;
454 for _ in 0..num_futures {
455 let value = pool.next_completed().await;
456 sum += value;
457 }
458 let expected_sum = (0..num_futures).sum::<i32>();
459 assert_eq!(
460 sum, expected_sum,
461 "Sum of resolved values should match expected"
462 );
463 assert!(
464 pool.is_empty(),
465 "Pool should be empty after all futures resolve"
466 );
467 });
468 }
469
470 #[test]
471 fn test_borrowing_futures() {
472 block_on(async {
473 let values = vec![1, 2, 3];
474
475 let mut pool = Pool::<&i32>::default();
477 for value in &values {
478 pool.push(async move { value });
479 }
480 assert_eq!(pool.len(), values.len());
481
482 let mut sum = 0;
483 for _ in 0..values.len() {
484 sum += *pool.next_completed().await;
485 }
486 assert_eq!(sum, 6);
487 assert!(pool.is_empty());
488 });
489 }
490
491 #[test]
492 fn test_abortable_pool_initialization() {
493 let pool = AbortablePool::<i32>::default();
494 assert_eq!(pool.len(), 0);
495 assert!(pool.is_empty());
496 }
497
498 #[test]
499 fn test_abortable_pool_adding_futures() {
500 let mut pool = AbortablePool::<i32>::default();
501 assert_eq!(pool.len(), 0);
502 assert!(pool.is_empty());
503
504 let _hook1 = pool.push(async { 42 });
505 assert_eq!(pool.len(), 1);
506 assert!(!pool.is_empty());
507
508 let _hook2 = pool.push(async { 43 });
509 assert_eq!(pool.len(), 2);
510 }
511
512 #[test]
513 fn test_abortable_pool_successful_completion() {
514 block_on(async move {
515 let mut pool = AbortablePool::<i32>::default();
516 let _hook = pool.push(future::ready(42));
517 let result = pool.next_completed().await;
518 assert_eq!(result, Ok(42));
519 assert!(pool.is_empty());
520 });
521 }
522
523 #[test]
524 fn test_abortable_pool_aborts_pre_polled_ready_future() {
525 block_on(async move {
526 let mut pool = AbortablePool::<i32>::default();
527 let hook = pool.push(future::ready(42));
528 drop(hook);
529 let result = pool.next_completed().await;
530 assert!(result.is_err());
531 });
532 }
533
534 #[test]
535 fn test_abortable_pool_drop_abort() {
536 block_on(async move {
537 let mut pool = AbortablePool::<i32>::default();
538
539 let (sender, receiver) = oneshot::channel();
540 let hook = pool.push(async move {
541 receiver.await.unwrap();
542 42
543 });
544
545 drop(hook);
546
547 let result = pool.next_completed().await;
548 assert!(result.is_err());
549 assert!(pool.is_empty());
550
551 let _ = sender.send(());
552 });
553 }
554
555 #[test]
556 fn test_abortable_pool_partial_abort() {
557 block_on(async move {
558 let mut pool = AbortablePool::<i32>::default();
559
560 let _hook1 = pool.push(future::ready(1));
561 let (sender, receiver) = oneshot::channel();
562 let hook2 = pool.push(async move {
563 receiver.await.unwrap();
564 2
565 });
566 let _hook3 = pool.push(future::ready(3));
567
568 assert_eq!(pool.len(), 3);
569
570 drop(hook2);
571
572 let mut results = Vec::new();
573 for _ in 0..3 {
574 let result = pool.next_completed().await;
575 results.push(result);
576 }
577
578 let successful: Vec<_> = results.iter().filter_map(|r| r.as_ref().ok()).collect();
579 let aborted: Vec<_> = results.iter().filter(|r| r.is_err()).collect();
580
581 assert_eq!(successful.len(), 2);
582 assert_eq!(aborted.len(), 1);
583 assert!(successful.contains(&&1));
584 assert!(successful.contains(&&3));
585 assert!(pool.is_empty());
586
587 let _ = sender.send(());
588 });
589 }
590
591 #[test]
592 fn test_abortable_pool_borrowing_futures() {
593 block_on(async {
594 let value = 42;
595 let mut pool = AbortablePool::<&i32>::default();
596
597 let (sender, receiver) = oneshot::channel::<()>();
599 let hook = pool.push(async {
600 receiver.await.unwrap();
601 &value
602 });
603 drop(hook);
604 assert!(pool.next_completed().await.is_err());
605
606 let _hook = pool.push(async { &value });
607 assert_eq!(pool.next_completed().await, Ok(&42));
608 assert!(pool.is_empty());
609
610 let _ = sender.send(());
611 });
612 }
613
614 #[test]
615 fn test_rebind_restores_value_and_yields_rest() {
616 block_on(async {
617 let mut slot = Some(1u32);
618 let rest: Result<(&str, bool), &str> = rebind(&mut slot, |value| {
619 future::ready(Ok((value + 1, "rest", true)))
620 })
621 .await;
622 assert_eq!(rest, Ok(("rest", true)));
623 assert_eq!(slot, Some(2));
624
625 let rest: Result<(), &str> =
626 rebind(&mut slot, |value| future::ready(Ok(value + 1))).await;
627 assert_eq!(rest, Ok(()));
628 assert_eq!(slot, Some(3));
629 });
630 }
631
632 #[test]
633 fn test_rebind_error_destroys_value() {
634 block_on(async {
635 let mut slot = Some(1u32);
636 let rest: Result<(), &str> =
637 rebind(&mut slot, |_| future::ready(Err::<u32, _>("failed"))).await;
638 assert_eq!(rest, Err("failed"));
639 assert_eq!(slot, None);
640 });
641 }
642
643 #[test]
644 #[should_panic(expected = "cannot rebind an empty slot")]
645 fn test_rebind_empty_slot_panics() {
646 block_on(async {
647 let mut slot: Option<u32> = None;
648 let _: Result<(), &str> = rebind(&mut slot, |v| future::ready(Ok(v))).await;
649 });
650 }
651
652 #[test]
653 fn test_rebind_entry_restores_value_and_yields_rest() {
654 block_on(async {
655 let mut map = BTreeMap::from([("a", 1u32), ("b", 10)]);
656 let rest: Result<bool, &str> =
657 rebind_entry(&mut map, &"a", |value| future::ready(Ok((value + 1, true)))).await;
658 assert_eq!(rest, Ok(true));
659 assert_eq!(map, BTreeMap::from([("a", 2), ("b", 10)]));
660 });
661 }
662
663 #[test]
664 fn test_rebind_entry_error_destroys_value() {
665 block_on(async {
666 let mut map = BTreeMap::from([("a", 1u32)]);
667 let rest: Result<(), &str> =
668 rebind_entry(&mut map, &"a", |_| future::ready(Err::<u32, _>("failed"))).await;
669 assert_eq!(rest, Err("failed"));
670 assert!(map.is_empty());
671 });
672 }
673
674 #[test]
675 #[should_panic(expected = "cannot rebind a missing entry")]
676 fn test_rebind_entry_missing_entry_panics() {
677 block_on(async {
678 let mut map: BTreeMap<&str, u32> = BTreeMap::new();
679 let _: Result<(), &str> = rebind_entry(&mut map, &"a", |v| future::ready(Ok(v))).await;
680 });
681 }
682
683 #[test]
684 fn test_option_future() {
685 block_on(async {
686 let option_future = OptionFuture::<oneshot::Receiver<()>>::from(None);
687 pin_mut!(option_future);
688
689 let waker = futures::task::noop_waker();
690 let mut cx = std::task::Context::from_waker(&waker);
691 assert!(option_future.poll(&mut cx).is_pending());
692
693 let (tx, rx) = oneshot::channel();
694 let option_future: OptionFuture<_> = Some(rx).into();
695 pin_mut!(option_future);
696
697 tx.send(1usize).unwrap();
698 assert_eq!(option_future.poll(&mut cx), Poll::Ready(Ok(1)));
699 });
700 }
701}