read_write_store/
timeout.rs

1//! Timeout specifiers and error types.
2//!
3//! See [Timeout](Timeout).
4
5use std::time::{Duration, Instant};
6
7/// A timeout (or lack thereof) describing how blocking operations should behave.
8#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
9pub enum Timeout {
10    /// Disallows blocking for a contended resource.
11    DontBlock,
12    /// Allows blocking for a contended resource until the given time has passed.
13    BlockUntil(Instant),
14    /// Allows blocking for a contended resource indefinitely.
15    BlockIndefinitely,
16}
17
18impl Timeout {
19    /// Creates a new timeout that lasts for the provided duration, starting now.
20    ///
21    /// # Example
22    ///
23    /// ```
24    /// # use read_write_store::timeout::Timeout;
25    /// # use std::time::{Instant, Duration};
26    /// let first_timeout = Timeout::BlockUntil(Instant::now());
27    /// let second_timeout = Timeout::block_for(Duration::from_secs(1));
28    /// assert!(first_timeout < second_timeout);
29    /// ```
30    pub fn block_for(duration: Duration) -> Self {
31        Self::BlockUntil(Instant::now() + duration)
32    }
33
34    /// Creates a new timeout that lasts for the provided number of milliseconds, starting now.
35    ///
36    /// # Example
37    ///
38    /// ```
39    /// # use read_write_store::timeout::Timeout;
40    /// # use std::time::Instant;
41    /// let first_timeout = Timeout::BlockUntil(Instant::now());
42    /// let second_timeout = Timeout::block_for_millis(1000);
43    /// assert!(first_timeout < second_timeout);
44    /// ```
45    pub fn block_for_millis(millis: u64) -> Self {
46        Self::block_for(Duration::from_millis(millis))
47    }
48}
49
50/// A result which either succeeded, or failed due to a timeout.
51pub type BlockResult<T> = Result<T, TimedOut>;
52
53/// The value of the error alternative of [BlockResult](crate::BlockResult) that indicates a
54/// timeout.
55#[derive(Debug, Clone, Copy, Ord, PartialOrd, Hash, Eq, PartialEq)]
56pub struct TimedOut;
57
58#[cfg(test)]
59mod test {
60    use std::time::{Duration, Instant};
61
62    use crate::Timeout;
63
64    #[test]
65    fn ordering_is_correct() {
66        let now = Instant::now();
67
68        let in_the_future = Timeout::BlockUntil(now + Duration::from_secs(1));
69        let in_the_past = Timeout::BlockUntil(now - Duration::from_secs(1));
70
71        let mut timeouts = vec![
72            Timeout::BlockIndefinitely,
73            in_the_future,
74            in_the_past,
75            Timeout::DontBlock,
76        ];
77
78        timeouts.sort();
79
80        assert_eq!(
81            timeouts,
82            vec![
83                Timeout::DontBlock,
84                in_the_past,
85                in_the_future,
86                Timeout::BlockIndefinitely,
87            ]
88        );
89    }
90}