69
69
//! });
70
70
//! ```
71
71
72
+ // Temporary workaround until the `async_event_loom` flag can be whitelisted
73
+ // without a `build.rs` [1].
74
+ //
75
+ // [1]: (https://github.com/rust-lang/rust/issues/124800).
76
+ #![ allow( unexpected_cfgs) ]
77
+
72
78
mod loom_exports;
73
79
74
80
use std:: future:: Future ;
@@ -81,6 +87,7 @@ use std::task::{Context, Poll, Waker};
81
87
use loom_exports:: cell:: UnsafeCell ;
82
88
use loom_exports:: sync:: atomic:: { self , AtomicBool } ;
83
89
use loom_exports:: sync:: Mutex ;
90
+ use pin_project_lite:: pin_project;
84
91
85
92
/// An object that can receive or send notifications.
86
93
pub struct Event {
@@ -130,9 +137,29 @@ impl Event {
130
137
131
138
/// Returns a future that can be `await`ed until the provided predicate is
132
139
/// satisfied.
133
- pub fn wait_until < F : FnMut ( ) -> Option < T > , T > ( & self , predicate : F ) -> WaitUntil < F , T > {
140
+ pub fn wait_until < F , T > ( & self , predicate : F ) -> WaitUntil < F , T >
141
+ where
142
+ F : FnMut ( ) -> Option < T > ,
143
+ {
134
144
WaitUntil :: new ( & self . wait_set , predicate)
135
145
}
146
+
147
+ /// Returns a future that can be `await`ed until the provided predicate is
148
+ /// satisfied or until the provided future completes.
149
+ ///
150
+ /// The deadline is specified as a `Future` that is expected to resolves to
151
+ /// `()` after some duration, such as a `tokio::time::Sleep` future.
152
+ pub fn wait_until_or_timeout < F , T , D > (
153
+ & self ,
154
+ predicate : F ,
155
+ deadline : D ,
156
+ ) -> WaitUntilOrTimeout < F , T , D >
157
+ where
158
+ F : FnMut ( ) -> Option < T > ,
159
+ D : Future < Output = ( ) > ,
160
+ {
161
+ WaitUntilOrTimeout :: new ( & self . wait_set , predicate, deadline)
162
+ }
136
163
}
137
164
138
165
impl Default for Event {
@@ -378,6 +405,53 @@ enum WaitUntilState {
378
405
Completed ,
379
406
}
380
407
408
+ pin_project ! {
409
+ /// A future that can be `await`ed until a predicate is satisfied or until a
410
+ /// deadline elapses.
411
+ pub struct WaitUntilOrTimeout <' a, F : FnMut ( ) -> Option <T >, T , D : Future <Output = ( ) >> {
412
+ wait_until: WaitUntil <' a, F , T >,
413
+ #[ pin]
414
+ deadline: D ,
415
+ }
416
+ }
417
+
418
+ impl < ' a , F , T , D > WaitUntilOrTimeout < ' a , F , T , D >
419
+ where
420
+ F : FnMut ( ) -> Option < T > ,
421
+ D : Future < Output = ( ) > ,
422
+ {
423
+ /// Creates a future associated with the specified event sink that can be
424
+ /// `await`ed until the specified predicate is satisfied, or until the
425
+ /// specified timeout future completes.
426
+ fn new ( wait_set : & ' a WaitSet , predicate : F , deadline : D ) -> Self {
427
+ Self {
428
+ wait_until : WaitUntil :: new ( wait_set, predicate) ,
429
+ deadline,
430
+ }
431
+ }
432
+ }
433
+
434
+ impl < ' a , F , T , D > Future for WaitUntilOrTimeout < ' a , F , T , D >
435
+ where
436
+ F : FnMut ( ) -> Option < T > ,
437
+ D : Future < Output = ( ) > ,
438
+ {
439
+ type Output = Option < T > ;
440
+
441
+ #[ inline]
442
+ fn poll ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
443
+ let this = self . project ( ) ;
444
+
445
+ if let Poll :: Ready ( value) = Pin :: new ( this. wait_until ) . poll ( cx) {
446
+ Poll :: Ready ( Some ( value) )
447
+ } else if this. deadline . poll ( cx) . is_ready ( ) {
448
+ Poll :: Ready ( None )
449
+ } else {
450
+ Poll :: Pending
451
+ }
452
+ }
453
+ }
454
+
381
455
/// A set of notifiers.
382
456
///
383
457
/// The set wraps a Mutex-protected list of notifiers and manages a flag for
0 commit comments