adaptive_sleep/
lib.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
const EXPONENTIAL_GROWTH: u32 = 10;
const EXPONENTIAL_MAX: u32 = 100_000;
const LINEAR_GROWTH: u32 = 250_000;
const LINEAR_MAX: u32 = 42_000_000;

#[derive(Debug, Clone, Copy)]
pub struct AdaptiveSleep {
    sleep_time: u32,
    exponential_growth: u32,
    exponential_max: u32,
    linear_growth: u32,
    linear_max: u32,
}

impl AdaptiveSleep {
    pub fn new(
        exponential_growth: u32,
        exponential_max: u32,
        linear_growth: u32,
        linear_max: u32,
    ) -> Self {
        Self {
            sleep_time: 1,
            exponential_growth,
            exponential_max,
            linear_growth,
            linear_max,
        }
    }

    pub fn sleep(&mut self) {
        sleep(
            &mut self.sleep_time,
            self.exponential_growth,
            self.exponential_max,
            self.linear_growth,
            self.linear_max,
        );
    }
    pub fn reset(&mut self) {
        self.sleep_time = 1;
    }
}

impl Default for AdaptiveSleep {
    fn default() -> Self {
        Self::new(
            EXPONENTIAL_GROWTH,
            EXPONENTIAL_MAX,
            LINEAR_GROWTH,
            LINEAR_MAX,
        )
    }
}

fn sleep(
    sleep_time: &mut u32,
    exponential_growth: u32,
    exponential_max: u32,
    linear_growth: u32,
    linear_max: u32,
) {
    match *sleep_time {
        n if (1..exponential_max).contains(&n) => *sleep_time *= exponential_growth,
        n if (exponential_max..linear_max).contains(&n) => *sleep_time += linear_growth,
        n if (linear_max..).contains(&n) => *sleep_time = linear_max,
        _ => *sleep_time = 1,
    }

    if *sleep_time > exponential_growth {
        std::thread::sleep(std::time::Duration::from_nanos(*sleep_time as u64));
    }
}

// starts with an exponentially growing sleep time until it hits a
// threshold and grows linearly
pub fn adaptive_sleep(sleep_time: &mut u32) {
    match *sleep_time {
        n if (1..EXPONENTIAL_MAX).contains(&n) => *sleep_time *= EXPONENTIAL_GROWTH,
        n if (EXPONENTIAL_MAX..LINEAR_MAX).contains(&n) => *sleep_time += LINEAR_GROWTH,
        n if (LINEAR_MAX..).contains(&n) => *sleep_time = LINEAR_MAX,
        _ => *sleep_time = 1,
    }

    if *sleep_time > EXPONENTIAL_GROWTH {
        std::thread::sleep(std::time::Duration::from_nanos(*sleep_time as u64));
    }
}