zbus/abstractions/mod.rs
1//! This mod contains a bunch of abstractions.
2//!
3//! These abstractions allow us to make use of the appropriate API depending on which features are
4//! enabled.
5
6/// Evaluates the `tokio` or `async-io` expression for the active backend.
7///
8/// With a single backend it resolves to that backend's expression at compile time; with both it
9/// picks at runtime via [`use_tokio`]. The inactive arm is `cfg`-stripped, so each arm only needs
10/// to be valid in the configurations where its backend is compiled in.
11///
12/// The choice is re-evaluated on every call, so this is only safe where it doesn't need to match a
13/// particular connection's backend. A connection latches its backend once at build time (see
14/// [`Executor::new`]); use that instead of this macro for anything tied to the socket's reactor.
15/// The current call sites (timers, the blocking pool) are independent of the socket, so a per-call
16/// decision is fine.
17macro_rules! select_runtime {
18 (tokio: $tokio:expr, async_io: $async_io:expr $(,)?) => {{
19 #[cfg(all(feature = "tokio", feature = "async-io"))]
20 {
21 if $crate::abstractions::use_tokio() {
22 $tokio
23 } else {
24 $async_io
25 }
26 }
27 #[cfg(all(feature = "tokio", not(feature = "async-io")))]
28 {
29 $tokio
30 }
31 #[cfg(all(feature = "async-io", not(feature = "tokio")))]
32 {
33 $async_io
34 }
35 }};
36}
37pub(crate) use select_runtime;
38
39/// Whether zbus should use tokio (rather than `async-io`) for its I/O.
40///
41/// Only consulted when `async-io` is compiled in, since that's the only time there's a choice. With
42/// both backends we use tokio when a tokio runtime is active on the current thread; with only
43/// `async-io` the answer is always `false`. This keeps the features additive: enabling `tokio`
44/// elsewhere in the dependency graph doesn't force every zbus user into a tokio runtime.
45#[cfg(feature = "async-io")]
46pub(crate) fn use_tokio() -> bool {
47 #[cfg(feature = "tokio")]
48 {
49 tokio::runtime::Handle::try_current().is_ok()
50 }
51 #[cfg(not(feature = "tokio"))]
52 {
53 false
54 }
55}
56
57mod executor;
58pub use executor::*;
59mod async_drop;
60pub(crate) mod async_lock;
61pub use async_drop::*;
62pub(crate) mod timeout;
63
64// Not unix-specific itself but only used on unix.
65#[cfg(target_family = "unix")]
66pub(crate) mod process;
67
68#[cfg(all(test, feature = "tokio", feature = "async-io"))]
69mod tests {
70 #[test]
71 fn use_tokio_reflects_active_runtime() {
72 assert!(!super::use_tokio(), "no runtime is active here");
73 let runtime = tokio::runtime::Runtime::new().unwrap();
74 assert!(
75 runtime.block_on(async { super::use_tokio() }),
76 "a tokio runtime is active",
77 );
78 }
79}