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
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.

use super::time::{Duration, Instant};
use fail::fail_point;

#[derive(Debug, Copy, Clone)]
pub struct DeadlineError;

impl std::error::Error for DeadlineError {
    fn description(&self) -> &str {
        "deadline has elapsed"
    }
}

impl std::fmt::Display for DeadlineError {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(fmt, "deadline has elapsed")
    }
}

/// A handy structure for checking deadline.
#[derive(Debug, Copy, Clone)]
pub struct Deadline {
    deadline: Instant,
}

impl Deadline {
    /// Creates a new `Deadline` by the given `deadline`.
    pub fn new(deadline: Instant) -> Self {
        Self { deadline }
    }

    /// Creates a new `Deadline` that will reach after specified amount of time in future.
    pub fn from_now(after_duration: Duration) -> Self {
        let deadline = Instant::now_coarse() + after_duration;
        Self { deadline }
    }

    /// Returns error if the deadline is exceeded.
    pub fn check(&self) -> std::result::Result<(), DeadlineError> {
        fail_point!("deadline_check_fail", |_| Err(DeadlineError));

        let now = Instant::now_coarse();
        if self.deadline <= now {
            return Err(DeadlineError);
        }
        Ok(())
    }
}