|
7 | 7 | #![deny(private_intra_doc_links)]
|
8 | 8 |
|
9 | 9 | #![deny(missing_docs)]
|
10 |
| -#![deny(unsafe_code)] |
| 10 | +#![cfg_attr(not(feature = "futures"), deny(unsafe_code))] |
11 | 11 |
|
12 | 12 | #![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
13 | 13 |
|
@@ -52,8 +52,6 @@ use std::thread::{self, JoinHandle};
|
52 | 52 | #[cfg(feature = "std")]
|
53 | 53 | use std::time::Instant;
|
54 | 54 |
|
55 |
| -#[cfg(feature = "futures")] |
56 |
| -use futures_util::{select_biased, future::FutureExt, task}; |
57 | 55 | #[cfg(not(feature = "std"))]
|
58 | 56 | use alloc::vec::Vec;
|
59 | 57 |
|
@@ -384,6 +382,50 @@ macro_rules! define_run_body {
|
384 | 382 | } }
|
385 | 383 | }
|
386 | 384 |
|
| 385 | +#[cfg(feature = "futures")] |
| 386 | +pub(crate) mod futures_util { |
| 387 | + use core::future::Future; |
| 388 | + use core::task::{Poll, Waker, RawWaker, RawWakerVTable}; |
| 389 | + use core::pin::Pin; |
| 390 | + use core::marker::Unpin; |
| 391 | + pub(crate) struct Selector<A: Future<Output=()> + Unpin, B: Future<Output=bool> + Unpin> { |
| 392 | + pub a: A, |
| 393 | + pub b: B, |
| 394 | + } |
| 395 | + pub(crate) enum SelectorOutput { |
| 396 | + A, B(bool), |
| 397 | + } |
| 398 | + |
| 399 | + impl<A: Future<Output=()> + Unpin, B: Future<Output=bool> + Unpin> Future for Selector<A, B> { |
| 400 | + type Output = SelectorOutput; |
| 401 | + fn poll(mut self: Pin<&mut Self>, ctx: &mut core::task::Context<'_>) -> Poll<SelectorOutput> { |
| 402 | + match Pin::new(&mut self.a).poll(ctx) { |
| 403 | + Poll::Ready(()) => { return Poll::Ready(SelectorOutput::A); }, |
| 404 | + Poll::Pending => {}, |
| 405 | + } |
| 406 | + match Pin::new(&mut self.b).poll(ctx) { |
| 407 | + Poll::Ready(res) => { return Poll::Ready(SelectorOutput::B(res)); }, |
| 408 | + Poll::Pending => {}, |
| 409 | + } |
| 410 | + Poll::Pending |
| 411 | + } |
| 412 | + } |
| 413 | + |
| 414 | + // If we want to poll a future without an async context to figure out if it has completed or |
| 415 | + // not without awaiting, we need a Waker, which needs a vtable...we fill it with dummy values |
| 416 | + // but sadly there's a good bit of boilerplate here. |
| 417 | + fn dummy_waker_clone(_: *const ()) -> RawWaker { RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE) } |
| 418 | + fn dummy_waker_action(_: *const ()) { } |
| 419 | + |
| 420 | + const DUMMY_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new( |
| 421 | + dummy_waker_clone, dummy_waker_action, dummy_waker_action, dummy_waker_action); |
| 422 | + pub(crate) fn dummy_waker() -> Waker { unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE)) } } |
| 423 | +} |
| 424 | +#[cfg(feature = "futures")] |
| 425 | +use futures_util::{Selector, SelectorOutput, dummy_waker}; |
| 426 | +#[cfg(feature = "futures")] |
| 427 | +use core::task; |
| 428 | + |
387 | 429 | /// Processes background events in a future.
|
388 | 430 | ///
|
389 | 431 | /// `sleeper` should return a future which completes in the given amount of time and returns a
|
@@ -470,16 +512,20 @@ where
|
470 | 512 | chain_monitor, chain_monitor.process_pending_events_async(async_event_handler).await,
|
471 | 513 | channel_manager, channel_manager.process_pending_events_async(async_event_handler).await,
|
472 | 514 | gossip_sync, peer_manager, logger, scorer, should_break, {
|
473 |
| - select_biased! { |
474 |
| - _ = channel_manager.get_persistable_update_future().fuse() => true, |
475 |
| - exit = sleeper(Duration::from_millis(100)).fuse() => { |
| 515 | + let fut = Selector { |
| 516 | + a: channel_manager.get_persistable_update_future(), |
| 517 | + b: sleeper(Duration::from_millis(100)), |
| 518 | + }; |
| 519 | + match fut.await { |
| 520 | + SelectorOutput::A => true, |
| 521 | + SelectorOutput::B(exit) => { |
476 | 522 | should_break = exit;
|
477 | 523 | false
|
478 | 524 | }
|
479 | 525 | }
|
480 | 526 | }, |t| sleeper(Duration::from_secs(t)),
|
481 | 527 | |fut: &mut SleepFuture, _| {
|
482 |
| - let mut waker = task::noop_waker(); |
| 528 | + let mut waker = dummy_waker(); |
483 | 529 | let mut ctx = task::Context::from_waker(&mut waker);
|
484 | 530 | core::pin::Pin::new(fut).poll(&mut ctx).is_ready()
|
485 | 531 | })
|
|
0 commit comments