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,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