rustdoc-args = ["--cfg", "docsrs"]
[features]
-futures = [ "futures-util" ]
+futures = [ ]
std = ["lightning/std", "lightning-rapid-gossip-sync/std"]
default = ["std"]
bitcoin = { version = "0.29.0", default-features = false }
lightning = { version = "0.0.114", path = "../lightning", default-features = false }
lightning-rapid-gossip-sync = { version = "0.0.114", path = "../lightning-rapid-gossip-sync", default-features = false }
-futures-util = { version = "0.3", default-features = false, optional = true }
[dev-dependencies]
lightning = { version = "0.0.114", path = "../lightning", features = ["_test_utils"] }
#![deny(private_intra_doc_links)]
#![deny(missing_docs)]
-#![deny(unsafe_code)]
+#![cfg_attr(not(feature = "futures"), deny(unsafe_code))]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#[cfg(feature = "std")]
use std::time::Instant;
-#[cfg(feature = "futures")]
-use futures_util::task;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
}
#[cfg(feature = "futures")]
-use core::future::Future;
-#[cfg(feature = "futures")]
-use core::task::Poll;
-#[cfg(feature = "futures")]
-use core::pin::Pin;
-#[cfg(feature = "futures")]
-use core::marker::Unpin;
-#[cfg(feature = "futures")]
-struct Selector<A: Future<Output=()> + Unpin, B: Future<Output=bool> + Unpin> {
- a: A,
- b: B,
-}
-#[cfg(feature = "futures")]
-enum SelectorOutput {
- A, B(bool),
-}
+pub(crate) mod futures_util {
+ use core::future::Future;
+ use core::task::{Poll, Waker, RawWaker, RawWakerVTable};
+ use core::pin::Pin;
+ use core::marker::Unpin;
+ pub(crate) struct Selector<A: Future<Output=()> + Unpin, B: Future<Output=bool> + Unpin> {
+ pub a: A,
+ pub b: B,
+ }
+ pub(crate) enum SelectorOutput {
+ A, B(bool),
+ }
-#[cfg(feature = "futures")]
-impl<A: Future<Output=()> + Unpin, B: Future<Output=bool> + Unpin> Future for Selector<A, B> {
- type Output = SelectorOutput;
- fn poll(mut self: Pin<&mut Self>, ctx: &mut core::task::Context<'_>) -> Poll<SelectorOutput> {
- match Pin::new(&mut self.a).poll(ctx) {
- Poll::Ready(()) => { return Poll::Ready(SelectorOutput::A); },
- Poll::Pending => {},
- }
- match Pin::new(&mut self.b).poll(ctx) {
- Poll::Ready(res) => { return Poll::Ready(SelectorOutput::B(res)); },
- Poll::Pending => {},
+ impl<A: Future<Output=()> + Unpin, B: Future<Output=bool> + Unpin> Future for Selector<A, B> {
+ type Output = SelectorOutput;
+ fn poll(mut self: Pin<&mut Self>, ctx: &mut core::task::Context<'_>) -> Poll<SelectorOutput> {
+ match Pin::new(&mut self.a).poll(ctx) {
+ Poll::Ready(()) => { return Poll::Ready(SelectorOutput::A); },
+ Poll::Pending => {},
+ }
+ match Pin::new(&mut self.b).poll(ctx) {
+ Poll::Ready(res) => { return Poll::Ready(SelectorOutput::B(res)); },
+ Poll::Pending => {},
+ }
+ Poll::Pending
}
- Poll::Pending
}
+
+ // If we want to poll a future without an async context to figure out if it has completed or
+ // not without awaiting, we need a Waker, which needs a vtable...we fill it with dummy values
+ // but sadly there's a good bit of boilerplate here.
+ fn dummy_waker_clone(_: *const ()) -> RawWaker { RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE) }
+ fn dummy_waker_action(_: *const ()) { }
+
+ const DUMMY_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
+ dummy_waker_clone, dummy_waker_action, dummy_waker_action, dummy_waker_action);
+ pub(crate) fn dummy_waker() -> Waker { unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE)) } }
}
+#[cfg(feature = "futures")]
+use futures_util::{Selector, SelectorOutput, dummy_waker};
+#[cfg(feature = "futures")]
+use core::task;
/// Processes background events in a future.
///
}
}, |t| sleeper(Duration::from_secs(t)),
|fut: &mut SleepFuture, _| {
- let mut waker = task::noop_waker();
+ let mut waker = dummy_waker();
let mut ctx = task::Context::from_waker(&mut waker);
core::pin::Pin::new(fut).poll(&mut ctx).is_ready()
})