-
Notifications
You must be signed in to change notification settings - Fork 31
/
time.rs
115 lines (101 loc) · 3.82 KB
/
time.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//! Contains helper structures to deal with time-related functionality.
use std::time::Duration;
use crate::ap::messages::{RequestMessage, ShutdownMessage};
use crate::ap::{AbstractProcess, DeferredRequestHandler, ProcessRef, RequestHandler};
use crate::host;
use crate::serializer::CanSerialize;
/// A reference to a timer created from send_after.
#[derive(Clone, Copy)]
pub struct TimerRef(u64);
impl TimerRef {
pub(crate) fn new(timer_id: u64) -> Self {
TimerRef(timer_id)
}
/// Cancel the timer, blocking until the timer is canceled.
pub fn cancel(self) -> bool {
unsafe { host::api::timer::cancel_timer(self.0) == 1 }
}
}
/// Modifies `T` so that all functions on it will return a timeout.
///
/// It's used to time out calls such as [`ProcessRef::shutdown`],
/// [`ProcessRef::request`], etc.
pub struct WithTimeout<T> {
timeout: Duration,
item: T,
}
impl<T: AbstractProcess> WithTimeout<ProcessRef<T>> {
pub fn from(timeout: Duration, item: ProcessRef<T>) -> Self {
Self { timeout, item }
}
/// Shuts the [`AbstractProcess`] down.
///
/// The function will only wait for the duration of the specified timeout on
/// the process to shut down, before returning `Err(Timeout)`.
#[track_caller]
pub fn shutdown(&self) -> Result<(), Timeout>
where
// The serializer needs to be able to serialize values of `ShutdownMessage` & `()` for the
// return value.
T::Serializer: CanSerialize<ShutdownMessage<T::Serializer>>,
T::Serializer: CanSerialize<()>,
{
self.item.shutdown_timeout(Some(self.timeout))
}
/// Make a request to the process.
///
/// The function will only wait for the duration of the specified timeout on
/// the response, before returning `Err(Timeout)`.
#[track_caller]
pub fn request<R: 'static>(&self, request: R) -> Result<T::Response, Timeout>
where
T: RequestHandler<R>,
T::Serializer: CanSerialize<R>,
T::Serializer: CanSerialize<T::Response>,
T::Serializer: CanSerialize<RequestMessage<R, T::Response, T::Serializer>>,
{
self.item.request_timeout(request, Some(self.timeout))
}
/// Make a deferred request to the process.
///
/// The function will only wait for the duration of the specified timeout on
/// the response, before returning `Err(Timeout)`.
#[track_caller]
pub fn deferred_request<R: 'static>(&self, request: R) -> Result<T::Response, Timeout>
where
T: DeferredRequestHandler<R>,
T::Serializer: CanSerialize<R>,
T::Serializer: CanSerialize<T::Response>,
T::Serializer: CanSerialize<RequestMessage<R, T::Response, T::Serializer>>,
{
self.item
.deferred_request_timeout(request, Some(self.timeout))
}
}
/// Error result for [`ProcessRef::shutdown`] & [`ProcessRef::request`].
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct Timeout;
/// Modifies `T` so that all functions on it will be performed with a delay.
///
/// It's used to delay calls such as [`ProcessRef::send`].
pub struct WithDelay<T> {
duration: Duration,
item: T,
}
impl<T: AbstractProcess> WithDelay<ProcessRef<T>> {
pub fn from(duration: Duration, item: ProcessRef<T>) -> Self {
Self { duration, item }
}
/// Send message to the process after the specified duration has passed.
///
/// This is a non-blocking function, meaning that `send` is going to be
/// performed in the background while the execution continues. The call will
/// return a reference to the timer allowing you to cancel the operation.
#[track_caller]
pub fn send<M: 'static>(&self, message: M) -> TimerRef
where
T::Serializer: CanSerialize<M>,
{
self.item.delayed_send(message, self.duration)
}
}