Skip to content

Commit 67d83e1

Browse files
committed
Add a test implementation of FutureSpawner to track spawned futs
1 parent 822ad88 commit 67d83e1

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

lightning/src/util/native_async.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,15 @@
77
//! This module contains a few public utility which are used to run LDK in a native Rust async
88
//! environment.
99
10+
#[cfg(all(test, feature = "std"))]
11+
use crate::sync::Mutex;
1012
use crate::util::async_poll::{MaybeSend, MaybeSync};
1113

14+
#[cfg(all(test, not(feature = "std")))]
15+
use core::cell::RefCell;
1216
use core::future::Future;
17+
#[cfg(test)]
18+
use core::pin::Pin;
1319

1420
/// A generic trait which is able to spawn futures in the background.
1521
pub trait FutureSpawner: MaybeSend + MaybeSync + 'static {
@@ -18,3 +24,81 @@ pub trait FutureSpawner: MaybeSend + MaybeSync + 'static {
1824
/// This method MUST NOT block on the given future immediately.
1925
fn spawn<T: Future<Output = ()> + MaybeSend + 'static>(&self, future: T);
2026
}
27+
28+
#[cfg(test)]
29+
trait MaybeSendableFuture: Future<Output = ()> + MaybeSend + 'static {}
30+
#[cfg(test)]
31+
impl<F: Future<Output = ()> + MaybeSend + 'static> MaybeSendableFuture for F {}
32+
33+
/// A simple [`FutureSpawner`] which holds [`Future`]s until they are manually polled via
34+
/// [`Self::poll_futures`].
35+
#[cfg(all(test, feature = "std"))]
36+
pub(crate) struct FutureQueue(Mutex<Vec<Pin<Box<dyn MaybeSendableFuture>>>>);
37+
#[cfg(all(test, not(feature = "std")))]
38+
pub(crate) struct FutureQueue(RefCell<Vec<Pin<Box<dyn MaybeSendableFuture>>>>);
39+
40+
#[cfg(test)]
41+
impl FutureQueue {
42+
pub(crate) fn new() -> Self {
43+
FutureQueue(Mutex::new(Vec::new()))
44+
}
45+
46+
pub(crate) fn pending_futures(&self) -> usize {
47+
#[cfg(feature = "std")]
48+
{
49+
self.0.lock().unwrap().len()
50+
}
51+
#[cfg(not(feature = "std"))]
52+
{
53+
self.0.borrow().len()
54+
}
55+
}
56+
57+
pub(crate) fn poll_futures(&self) {
58+
let mut futures;
59+
#[cfg(feature = "std")]
60+
{
61+
futures = self.0.lock().unwrap();
62+
}
63+
#[cfg(not(feature = "std"))]
64+
{
65+
futures = self.0.borrow_mut();
66+
}
67+
futures.retain_mut(|fut| {
68+
use core::task::{Context, Poll};
69+
let waker = crate::util::async_poll::dummy_waker();
70+
match fut.as_mut().poll(&mut Context::from_waker(&waker)) {
71+
Poll::Ready(()) => false,
72+
Poll::Pending => true,
73+
}
74+
});
75+
}
76+
}
77+
78+
#[cfg(test)]
79+
impl FutureSpawner for FutureQueue {
80+
fn spawn<T: Future<Output = ()> + MaybeSend + 'static>(&self, future: T) {
81+
#[cfg(feature = "std")]
82+
{
83+
self.0.lock().unwrap().push(Box::pin(future));
84+
}
85+
#[cfg(not(feature = "std"))]
86+
{
87+
self.0.borrow_mut().push(Box::pin(future));
88+
}
89+
}
90+
}
91+
92+
#[cfg(test)]
93+
impl<D: core::ops::Deref<Target = FutureQueue> + Send + Sync + 'static> FutureSpawner for D {
94+
fn spawn<T: Future<Output = ()> + MaybeSend + 'static>(&self, future: T) {
95+
#[cfg(feature = "std")]
96+
{
97+
self.0.lock().unwrap().push(Box::pin(future));
98+
}
99+
#[cfg(not(feature = "std"))]
100+
{
101+
self.0.borrow_mut().push(Box::pin(future));
102+
}
103+
}
104+
}

0 commit comments

Comments
 (0)