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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/// Implementation of rate limi semaphore
use ;
/// Use it to control execution frequency
///
/// # Examples:
/// ```rust
/// use std::{thread, sync, time};
/// use raliguard::Semaphore;
///
///
/// // Create a semaphore with restriction `5 tasks per 1 second`
/// let originl_sem = Semaphore::new(5, time::Duration::from_secs(1));
///
/// // Make it sharable between treads (or you can share between tasks)
/// let shared_sem = sync::Arc::new(
/// sync::Mutex::new(originl_sem)
/// );
///
/// // This is a counter that increments when a thread completed
/// let shared_done_count = sync::Arc::new(sync::Mutex::new(0));
///
/// // Spawn 15 threads
/// for _ in 0..15 {
/// let cloned_sem = shared_sem.clone();
/// let cloned_done_state = shared_done_count.clone();
/// let thread = thread::spawn(move || {
/// let mut local_sem = cloned_sem.lock().unwrap();
///
/// // Get required delay
/// let calculated_delay = local_sem.calc_delay();
/// drop(local_sem);
///
/// // If delay exists, sleep it
/// if let Some(delay) = calculated_delay {
/// dbg!(&delay);
/// thread::sleep(delay);
/// }
///
/// // Mark the thread is done
/// let mut local_done_count = cloned_done_state.lock().unwrap();
/// *local_done_count += 1;
///
/// });
/// }
///
/// // So sleep 1 second (add some millis to let threads complete incrementing)
/// thread::sleep(time::Duration::from_secs(1) + time::Duration::from_millis(50));
/// let cloned_done_count = shared_done_count.clone();
/// let current_done = cloned_done_count.lock().unwrap();
///
/// // And then maximum 10 threads should be completed
/// // after 1 second sleeping
/// // (the first 5 with no delay and the another 5 after 1 second)
/// assert_eq!(*current_done, 10);
/// ```