Skip to content

Commit 5eed7c7

Browse files
committed
Add a test implementation of FutureSpawner to track spawned futs
1 parent e72d6cf commit 5eed7c7

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

lightning/src/util/native_async.rs

Lines changed: 93 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,90 @@ 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+
#[cfg(feature = "std")]
44+
{
45+
FutureQueue(Mutex::new(Vec::new()))
46+
}
47+
#[cfg(not(feature = "std"))]
48+
{
49+
FutureQueue(RefCell::new(Vec::new()))
50+
}
51+
}
52+
53+
pub(crate) fn pending_futures(&self) -> usize {
54+
#[cfg(feature = "std")]
55+
{
56+
self.0.lock().unwrap().len()
57+
}
58+
#[cfg(not(feature = "std"))]
59+
{
60+
self.0.borrow().len()
61+
}
62+
}
63+
64+
pub(crate) fn poll_futures(&self) {
65+
let mut futures;
66+
#[cfg(feature = "std")]
67+
{
68+
futures = self.0.lock().unwrap();
69+
}
70+
#[cfg(not(feature = "std"))]
71+
{
72+
futures = self.0.borrow_mut();
73+
}
74+
futures.retain_mut(|fut| {
75+
use core::task::{Context, Poll};
76+
let waker = crate::util::async_poll::dummy_waker();
77+
match fut.as_mut().poll(&mut Context::from_waker(&waker)) {
78+
Poll::Ready(()) => false,
79+
Poll::Pending => true,
80+
}
81+
});
82+
}
83+
}
84+
85+
#[cfg(test)]
86+
impl FutureSpawner for FutureQueue {
87+
fn spawn<T: Future<Output = ()> + MaybeSend + 'static>(&self, future: T) {
88+
#[cfg(feature = "std")]
89+
{
90+
self.0.lock().unwrap().push(Box::pin(future));
91+
}
92+
#[cfg(not(feature = "std"))]
93+
{
94+
self.0.borrow_mut().push(Box::pin(future));
95+
}
96+
}
97+
}
98+
99+
#[cfg(test)]
100+
impl<D: core::ops::Deref<Target = FutureQueue> + MaybeSend + MaybeSync + 'static> FutureSpawner
101+
for D
102+
{
103+
fn spawn<T: Future<Output = ()> + MaybeSend + 'static>(&self, future: T) {
104+
#[cfg(feature = "std")]
105+
{
106+
self.0.lock().unwrap().push(Box::pin(future));
107+
}
108+
#[cfg(not(feature = "std"))]
109+
{
110+
self.0.borrow_mut().push(Box::pin(future));
111+
}
112+
}
113+
}

0 commit comments

Comments
 (0)