round_based/
runtime.rs

1//! Async runtime abstraction
2//!
3//! Runtime abstraction allows the MPC protocol to stay runtime-agnostic while being
4//! able to use features that are common to any runtime
5
6/// Async runtime abstraction
7///
8/// Abstracts async runtime like [tokio]. Currently only exposes a [yield_now](Self::yield_now)
9/// function.
10pub trait AsyncRuntime {
11    /// Future type returned by [yield_now](Self::yield_now)
12    type YieldNowFuture: core::future::Future<Output = ()>;
13
14    /// Yields the execution back to the runtime
15    ///
16    /// If the protocol performs a long computation, it might be better for performance
17    /// to split it with yield points, so the signle computation does not starve other
18    /// tasks.
19    fn yield_now(&self) -> Self::YieldNowFuture;
20}
21
22/// [Tokio](tokio)-specific async runtime
23#[cfg(feature = "runtime-tokio")]
24#[derive(Debug, Default)]
25pub struct TokioRuntime;
26
27#[cfg(feature = "runtime-tokio")]
28impl AsyncRuntime for TokioRuntime {
29    type YieldNowFuture =
30        core::pin::Pin<alloc::boxed::Box<dyn core::future::Future<Output = ()> + Send>>;
31
32    fn yield_now(&self) -> Self::YieldNowFuture {
33        alloc::boxed::Box::pin(tokio::task::yield_now())
34    }
35}
36
37#[doc(inline)]
38pub use unknown_runtime::UnknownRuntime;
39
40/// Default runtime
41#[cfg(feature = "runtime-tokio")]
42#[cfg_attr(docsrs, doc(cfg(all())))]
43pub type DefaultRuntime = TokioRuntime;
44/// Default runtime
45#[cfg(not(feature = "runtime-tokio"))]
46#[cfg_attr(docsrs, doc(cfg(all())))]
47pub type DefaultRuntime = UnknownRuntime;
48
49/// Unknown async runtime
50pub mod unknown_runtime {
51    /// Unknown async runtime
52    ///
53    /// Tries to implement runtime features using generic futures code. It's better to use
54    /// runtime-specific implementation.
55    #[derive(Debug, Default)]
56    pub struct UnknownRuntime;
57
58    impl super::AsyncRuntime for UnknownRuntime {
59        type YieldNowFuture = YieldNow;
60
61        fn yield_now(&self) -> Self::YieldNowFuture {
62            YieldNow(false)
63        }
64    }
65
66    /// Future for the `yield_now` function.
67    pub struct YieldNow(bool);
68
69    impl core::future::Future for YieldNow {
70        type Output = ();
71
72        fn poll(
73            mut self: core::pin::Pin<&mut Self>,
74            cx: &mut core::task::Context<'_>,
75        ) -> core::task::Poll<Self::Output> {
76            if !self.0 {
77                self.0 = true;
78                cx.waker().wake_by_ref();
79                core::task::Poll::Pending
80            } else {
81                core::task::Poll::Ready(())
82            }
83        }
84    }
85}