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 ;
1012use crate :: util:: async_poll:: { MaybeSend , MaybeSync } ;
1113
14+ #[ cfg( all( test, not( feature = "std" ) ) ) ]
15+ use core:: cell:: RefCell ;
1216use 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.
1521pub 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