1use std::future::Future;
13use std::sync::atomic::AtomicBool;
14use std::sync::atomic::Ordering;
15use std::sync::Arc;
16use tokio::sync::Mutex as TokioMutex;
17use tokio::task::JoinHandle;
18use tokio::time::Sleep;
19
20#[derive(Debug, Clone)]
26pub enum TimerError {
27 InvalidFormat,
28}
29
30impl std::fmt::Display for TimerError {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
32 match self {
33 Self::InvalidFormat => {
34 f.write_str("错误的格式.")?;
35 }
36 }
37 return Ok(());
38 }
39}
40
41impl std::error::Error for TimerError {}
42
43#[derive(Clone, Debug)]
50pub struct Timer {
51 thread_handles: Arc<TokioMutex<Vec<JoinHandle<()>>>>,
52 is_stop: Arc<AtomicBool>,
53}
54
55impl Timer {
56 pub fn new() -> Self {
57 return Self {
58 thread_handles: Arc::new(TokioMutex::new(Vec::new())),
59 is_stop: Arc::new(AtomicBool::new(false)),
60 };
61 }
62
63 pub fn sleep(t: u64) -> Sleep {
65 use std::time::Duration;
66
67 return tokio::time::sleep(Duration::from_millis(t));
68 }
69
70 #[deprecated(
71 since = "2.0.0",
72 note = "停止时钟放到了Drop中, 只需要在主程序等待一段时间, 即可正确地释放资源."
73 )]
74 pub async fn stop(&mut self) {
76 self.is_stop.store(true, Ordering::SeqCst);
77 loop {
78 match {
79 let handle = self.thread_handles.lock().await.pop();
80 handle
81 } {
82 Some(handle) => handle.await.unwrap(),
83 None => break,
84 }
85 }
86 return;
87 }
88
89 pub fn schedule_pattern<F1, F2>(&mut self, pattern: &str, mut f: F1) -> Result<(), TimerError>
95 where
96 F1: FnMut() -> F2 + Send + 'static,
97 F2: Future<Output = ()> + Send + 'static,
98 {
99 enum Status {
101 MIN,
102 MAX,
103 SEPARATION,
104 SLASH,
105 }
106 let expand = |mut min: usize, max: usize, separation: usize| {
107 let mut result: Vec<usize> = Vec::new();
108 while min <= max {
109 result.push(min);
110 min += separation;
111 }
112 return result;
113 };
114 let mut table: [([bool; 60], usize, usize); 6] = [
115 ([false; 60], 0, 59),
116 ([false; 60], 0, 59),
117 ([false; 60], 0, 59),
118 ([false; 60], 1, 31),
119 ([false; 60], 1, 12),
120 ([false; 60], 1, 7),
121 ];
122 let mut pattern: String = pattern.to_string();
123 while pattern.contains(" ") {
124 pattern = pattern.replace(" ", " ");
125 }
126 if pattern.split(' ').count() != table.len() {
127 return Err(TimerError::InvalidFormat);
128 }
129 let mut index: usize = 0;
130 for x in pattern.split(' ') {
131 if x.len() == 0 {
132 return Err(TimerError::InvalidFormat);
133 }
134 for y in x.split([',', ',']) {
135 if y.len() == 0 {
136 return Err(TimerError::InvalidFormat);
137 }
138 let mut status: Status = Status::MIN;
139 let mut min: Vec<u8> = Vec::new();
140 let mut max: Vec<u8> = Vec::new();
141 let mut separation: Vec<u8> = Vec::new();
142 for z in y.as_bytes() {
143 match status {
144 Status::MIN => {
145 if (*z as char).is_ascii_digit() {
146 min.push(*z);
147 } else if *z == b'-' {
148 status = Status::MAX;
149 } else if *z == b'*' {
150 if 0 < min.len() {
151 return Err(TimerError::InvalidFormat);
152 }
153 min.extend_from_slice(table[index].1.to_string().as_bytes());
154 max.extend_from_slice(table[index].2.to_string().as_bytes());
155 status = Status::SLASH;
156 } else {
157 return Err(TimerError::InvalidFormat);
158 }
159 }
160 Status::MAX => {
161 if (*z as char).is_ascii_digit() {
162 max.push(*z);
163 } else if *z == b'/' {
164 status = Status::SEPARATION;
165 } else {
166 return Err(TimerError::InvalidFormat);
167 }
168 }
169 Status::SEPARATION => {
170 if (*z as char).is_ascii_digit() {
171 separation.push(*z);
172 } else {
173 return Err(TimerError::InvalidFormat);
174 }
175 }
176 Status::SLASH => {
177 if *z == b'/' {
178 status = Status::SEPARATION;
179 }
180 }
181 }
182 }
183 match status {
184 Status::MIN => {
185 if min.len() == 0 {
186 return Err(TimerError::InvalidFormat);
187 } else {
188 max = min.clone();
189 }
190 }
191 Status::MAX => {
192 if max.len() == 0 {
193 return Err(TimerError::InvalidFormat);
194 }
195 }
196 Status::SEPARATION => {
197 if separation.len() == 0 {
198 return Err(TimerError::InvalidFormat);
199 }
200 }
201 Status::SLASH => {}
202 }
203 let min: usize = if min.len() == 0 {
204 table[index].1
205 } else {
206 String::from_utf8(min)
207 .map_err(|_| TimerError::InvalidFormat)?
208 .parse::<usize>()
209 .map_err(|_| TimerError::InvalidFormat)?
210 };
211 let max: usize = if max.len() == 0 {
212 table[index].2
213 } else {
214 String::from_utf8(max)
215 .map_err(|_| TimerError::InvalidFormat)?
216 .parse::<usize>()
217 .map_err(|_| TimerError::InvalidFormat)?
218 };
219 let separation: usize = if separation.len() == 0 {
220 1
221 } else {
222 String::from_utf8(separation)
223 .map_err(|_| TimerError::InvalidFormat)?
224 .parse::<usize>()
225 .map_err(|_| TimerError::InvalidFormat)?
226 };
227 if min < table[index].1
228 || table[index].2 < min
229 || max < table[index].1
230 || table[index].2 < max
231 || max < min
232 {
233 return Err(TimerError::InvalidFormat);
234 }
235 for z in expand(min, max, separation) {
236 table[index].0[z] = true;
237 }
238 } index += 1;
240 } let is_stop: Arc<AtomicBool> = self.is_stop.clone();
242 let handle = tokio::task::spawn(async move {
243 use iceyee_datetime::DateTime;
244 let second = &table[0];
245 let minute = &table[1];
246 let hour = &table[2];
247 let day = &table[3];
248 let month = &table[4];
249 let weekday = &table[5];
250 while !is_stop.load(Ordering::SeqCst) {
251 let t: u64 = (1000 - DateTime::now() as u64 % 1000) + 200;
252 let sl = tokio::task::spawn(Self::sleep(t));
253 let dt: DateTime = DateTime::new();
254 if second.0[dt.second]
255 && minute.0[dt.minute]
256 && hour.0[dt.hour]
257 && day.0[dt.day]
258 && month.0[dt.month]
259 && weekday.0[dt.weekday]
260 {
261 f().await;
262 }
263 while !is_stop.load(Ordering::SeqCst) && !sl.is_finished() {
264 Self::sleep(50).await;
265 }
266 }
267 });
268 let thread_handles = self.thread_handles.clone();
269 tokio::task::spawn(async move {
270 thread_handles.lock().await.push(handle);
271 });
272 return Ok(());
273 }
274
275 pub fn schedule_execute_before<F1, F2>(&mut self, delay: u64, period: u64, mut f: F1)
277 where
278 F1: FnMut() -> F2 + Send + 'static,
279 F2: Future<Output = ()> + Send + 'static,
280 {
281 let is_stop: Arc<AtomicBool> = self.is_stop.clone();
282 let handle = tokio::task::spawn(async move {
283 let sl = tokio::task::spawn(Timer::sleep(delay));
284 while !is_stop.load(Ordering::SeqCst) && !sl.is_finished() {
285 Self::sleep(200).await;
286 }
287 while !is_stop.load(Ordering::SeqCst) {
288 let sl = tokio::task::spawn(Timer::sleep(period));
289 f().await;
290 while !is_stop.load(Ordering::SeqCst) && !sl.is_finished() {
291 Self::sleep(200).await;
292 }
293 }
294 });
295 let thread_handles = self.thread_handles.clone();
296 tokio::task::spawn(async move {
297 thread_handles.lock().await.push(handle);
298 });
299 return;
300 }
301
302 pub fn schedule_execute_after<F1, F2>(&mut self, delay: u64, period: u64, mut f: F1)
304 where
305 F1: FnMut() -> F2 + Send + 'static,
306 F2: Future<Output = ()> + Send + 'static,
307 {
308 let is_stop: Arc<AtomicBool> = self.is_stop.clone();
309 let handle = tokio::task::spawn(async move {
310 let sl = tokio::task::spawn(Self::sleep(delay));
311 while !is_stop.load(Ordering::SeqCst) && !sl.is_finished() {
312 Self::sleep(200).await;
313 }
314 while !is_stop.load(Ordering::SeqCst) {
315 f().await;
316 let sl = tokio::task::spawn(Self::sleep(period));
317 while !is_stop.load(Ordering::SeqCst) && !sl.is_finished() {
318 Self::sleep(200).await;
319 }
320 }
321 });
322 let thread_handles = self.thread_handles.clone();
323 tokio::task::spawn(async move {
324 thread_handles.lock().await.push(handle);
325 });
326 return;
327 }
328}
329
330impl Drop for Timer {
331 fn drop(&mut self) {
332 self.is_stop.store(true, Ordering::SeqCst);
333 let thread_handles = self.thread_handles.clone();
334 tokio::task::spawn(async move {
335 let mut thread_handles = thread_handles.lock().await;
336 loop {
337 match thread_handles.pop() {
338 Some(handle) => handle.await.unwrap(),
339 None => break,
340 }
341 }
342 });
343 return;
344 }
345}
346
347