timer_deque_rs/timer_portable/linux/
timer_fd_linux.rs1use std::borrow::Cow;
21use std::{fmt};
22use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd};
23use std::os::unix::prelude::RawFd;
24use std::task::Poll;
25
26use nix::fcntl::{FcntlArg, OFlag};
27use nix::{fcntl, libc};
28use nix::libc::itimerspec;
29
30
31use crate::nix::errno::Errno;
32use crate::timer_portable::portable_error::TimerPortResult;
33use crate::timer_portable::timer::{FdTimerRead, ModeTimeType, TimerReadRes};
34use crate::{map_portable_err, portable_err, AbsoluteTime};
35use crate::timer_portable::
36{
37 FdTimerCom, TimerExpMode, TimerFlags, TimerType
38};
39
40
41#[derive(Debug)]
49pub struct TimerFdInternal
50{
51 label: Cow<'static, str>,
53
54 timer_fd: OwnedFd,
56}
57
58impl fmt::Display for TimerFdInternal
59{
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
61 {
62 write!(f, "{}", self.timer_fd.as_raw_fd())
63 }
64}
65
66impl AsFd for TimerFdInternal
67{
68 fn as_fd(&self) -> BorrowedFd<'_>
69 {
70 return self.timer_fd.as_fd();
71 }
72}
73
74impl AsRawFd for TimerFdInternal
75{
76 fn as_raw_fd(&self) -> RawFd
77 {
78 return self.timer_fd.as_raw_fd();
79 }
80}
81
82impl Eq for TimerFdInternal {}
83
84impl PartialEq for TimerFdInternal
85{
86 fn eq(&self, other: &Self) -> bool
87 {
88 return self.timer_fd.as_raw_fd() == other.timer_fd.as_raw_fd();
89 }
90}
91
92impl PartialEq<RawFd> for TimerFdInternal
93{
94 fn eq(&self, other: &RawFd) -> bool
95 {
96 return self.timer_fd.as_raw_fd() == *other;
97 }
98}
99
100impl PartialEq<str> for TimerFdInternal
101{
102 fn eq(&self, other: &str) -> bool
103 {
104 return self.label == other;
105 }
106}
107
108impl AsRef<str> for TimerFdInternal
109{
110 fn as_ref(&self) -> &str
111 {
112 return &self.label;
113 }
114}
115
116impl Ord for TimerFdInternal
117{
118 fn cmp(&self, other: &Self) -> std::cmp::Ordering
119 {
120 return self.timer_fd.as_raw_fd().cmp(&other.timer_fd.as_raw_fd());
121 }
122}
123
124impl PartialOrd for TimerFdInternal
125{
126 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering>
127 {
128 return Some(self.cmp(other));
129 }
130}
131
132impl FdTimerRead for TimerFdInternal
133{
134 #[inline]
135 fn read(&self) -> TimerPortResult<TimerReadRes<u64>>
136 {
137 let mut timer_overfl = [0u8; size_of::<u64>()];
138
139 loop
140 {
141 let ret =
142 nix::unistd::read(&self.timer_fd, &mut timer_overfl);
143
144 if let Ok(_) = ret
145 {
146 let overl: u64 = u64::from_ne_bytes(timer_overfl);
147
148 return Ok(TimerReadRes::Ok(overl));
149 }
150 else if let Err(Errno::EINTR) = ret
151 {
152 continue;
153 }
154 else if let Err(Errno::EAGAIN) = ret
155 {
156 return Ok(TimerReadRes::WouldBlock);
158 }
159 else if let Err(Errno::ECANCELED) = ret
160 {
161 return Ok(TimerReadRes::Cancelled);
162 }
163 else if let Err(e) = ret
164 {
165 portable_err!(e, "read timer overflow error for timer: '{}'", self.label)
166 }
167 }
168 }
169}
170
171impl FdTimerCom for TimerFdInternal
172{
173 fn new(label: Cow<'static, str>, timer_type: TimerType, timer_flags: TimerFlags) -> TimerPortResult<Self>
174 {
175 let timer_fd =
176 unsafe { libc::timerfd_create(timer_type.into(), timer_flags.bits()) };
177
178 if timer_fd == -1
179 {
180 portable_err!(Errno::last(), "timer: '{}', timerfd_create failed with error", label);
181 }
182
183 return Ok(
184 Self
185 {
186 label:
187 label,
188 timer_fd:
189 unsafe { OwnedFd::from_raw_fd(timer_fd) },
190 }
193 );
194 }
195
196 fn set_time<TIMERTYPE: ModeTimeType>(&self, timer_exp: TimerExpMode<TIMERTYPE>) -> TimerPortResult<()>
197 {
198 let flags = TIMERTYPE::get_flags().bits();
202 let timer_value: itimerspec = timer_exp.into();
203
204 let res =
205 unsafe
206 {
207 libc::timerfd_settime(self.timer_fd.as_raw_fd(), flags,
208 &timer_value, core::ptr::null_mut())
209 };
210
211 if res == -1
212 {
213 portable_err!(Errno::last(), "can not init timer: '{}'", self.label);
214 }
215
216 return Ok(());
217 }
218
219 fn unset_time(&self) -> TimerPortResult<()>
220 {
221 let mut timer_value: itimerspec = unsafe { std::mem::zeroed() };
223
224 let res =
225 unsafe
226 {
227 libc::timerfd_gettime(self.timer_fd.as_raw_fd(),
228 &mut timer_value as *mut _ as *mut itimerspec)
229 };
230
231 if res == -1
232 {
233 portable_err!(Errno::last(), "can not timerfd_gettime for timer: '{}'", self.label);
234 }
235
236 let timer_mode = TimerExpMode::<AbsoluteTime>::from(timer_value);
237
238 if TimerExpMode::<AbsoluteTime>::reset() == timer_mode
239 {
240 return Ok(());
242 }
243
244 let timer_value: itimerspec = TimerExpMode::<AbsoluteTime>::reset().into();
247
248 let res =
249 unsafe
250 {
251 libc::timerfd_settime(self.timer_fd.as_raw_fd(), 0,
252 &timer_value, core::ptr::null_mut())
253 };
254
255 if res == -1
256 {
257 portable_err!(Errno::last(), "can not unset timer: '{}'", self.label);
258 }
259
260 return Ok(());
261 }
262
263 fn set_nonblocking(&self, flag: bool) -> TimerPortResult<()>
264 {
265 let mut fl =
266 OFlag::from_bits_retain(
267 fcntl::fcntl(&self.timer_fd, FcntlArg::F_GETFL)
268 .map_err(|e|
269 map_portable_err!(e, "timer: '{}', fcntl F_GETFL failed", self.label)
270 )?
271 );
272
273 fl.set(OFlag::O_NONBLOCK, flag);
274
275 fcntl::fcntl(&self.timer_fd, FcntlArg::F_SETFL(fl))
276 .map_err(|e|
277 map_portable_err!(e, "timer: '{}', fcntl F_SETFL failed", self.label)
278 )?;
279
280 return Ok(());
281 }
282
283 fn is_nonblocking(&self) -> TimerPortResult<bool>
284 {
285 let fl =
286 OFlag::from_bits_retain(
287 fcntl::fcntl(&self.timer_fd, FcntlArg::F_GETFL)
288 .map_err(|e|
289 map_portable_err!(e, "timer: '{}', fcntl F_GETFL failed", self.label)
290 )?
291 );
292
293 return Ok(fl.intersects(OFlag::O_NONBLOCK));
294 }
295}
296
297
298impl TimerFdInternal
299{
300
301}
302
303impl Future for &TimerFdInternal
304{
305 type Output = TimerPortResult<TimerReadRes<u64>>;
306
307 fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output>
308 {
309 let res = self.read();
310
311 if let Ok(TimerReadRes::WouldBlock) = res
312 {
313 cx.waker().wake_by_ref();
314
315 return Poll::Pending;
316 }
317 else
318 {
319 return Poll::Ready(res);
320 }
321 }
322}
323
324impl Future for TimerFdInternal
325{
326 type Output = TimerPortResult<TimerReadRes<u64>>;
327
328 fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output>
329 {
330 let res = self.read();
331
332 if let Ok(TimerReadRes::WouldBlock) = res
333 {
334 cx.waker().wake_by_ref();
335
336 return Poll::Pending;
337 }
338 else
339 {
340 return Poll::Ready(res);
341 }
342 }
343}
344
345
346#[cfg(test)]
347mod tests
348{
349 use std::time::Instant;
350
351 use tokio::io::{unix::AsyncFd, Interest};
352
353 use crate::timer_portable::timer::AbsoluteTime;
354
355 use super::*;
356
357 #[test]
358 fn test1()
359 {
360 let timer =
361 TimerFdInternal::new(Cow::Borrowed("test"), TimerType::CLOCK_REALTIME,
362 TimerFlags::empty()).unwrap();
363
364 let now = chrono::offset::Local::now().timestamp();
365 let snow = now + 3;
366 let s = Instant::now();
367
368 let timer_mode1 =
369 TimerExpMode::<AbsoluteTime>::new_oneshot(
370 AbsoluteTime::new_time(snow, 0).unwrap()
371 );
372
373 let res =
374 timer
375 .set_time(timer_mode1);
376 println!("timer was set: '{}' '{}'", now, snow);
377
378 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
379
380
381
382 let ovf = timer.read().unwrap().unwrap();
383
384 let ts = chrono::offset::Local::now().timestamp();
385 let e = s.elapsed();
386
387 assert_eq!(ovf, 1);
388 assert_eq!(ts, snow);
389
390 println!("elapsed: {:?}, ts: {}", e, ts);
391
392 assert_eq!((e.as_millis() <= 3100), true);
393
394 println!("Success");
395 return;
396 }
397
398
399 #[tokio::test]
400 async fn test2_fut()
401 {
402 let timer =
403 TimerFdInternal::new(Cow::Borrowed("test"), TimerType::CLOCK_REALTIME,
404 TimerFlags::empty()).unwrap();
405
406 let now = chrono::offset::Local::now().timestamp();
407 let snow = now + 3;
408 let s = Instant::now();
409
410 let timer_mode1 =
411 TimerExpMode::<AbsoluteTime>::new_oneshot(
412 AbsoluteTime::new_time(snow, 0).unwrap()
413 );
414
415
416 let res =
417 timer
418 .set_time(timer_mode1);
419
420 println!("timer was set: '{}' '{}'", now, snow);
421
422 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
423
424 tokio::select! {
428 ovf = timer => {
429 let ts = chrono::offset::Local::now().timestamp();
430 let e = s.elapsed();
431
432 assert_eq!(ovf, Ok(TimerReadRes::Ok(1)));
433 assert_eq!(ts, snow);
434
435 println!("timeout e: {:?}, ts:{} snow:{}", e, ts, snow);
436 }
437 }
438 }
439
440 #[tokio::test]
441 async fn test3_tokio()
442 {
443 let mut timer: AsyncFd<TimerFdInternal> =
444 AsyncFd::with_interest(
445 TimerFdInternal::new(Cow::Borrowed("test"), TimerType::CLOCK_REALTIME,
446 TimerFlags::empty()).unwrap(),
447 Interest::READABLE
448 ).unwrap();
449
450
451 let now = chrono::offset::Local::now().timestamp();
452 let snow = now + 3;
453 let s = Instant::now();
454
455 let timer_mode1 =
456 TimerExpMode::<AbsoluteTime>::new_oneshot(
457 AbsoluteTime::new_time(snow, 0).unwrap()
458 );
459
460 let res =
461 timer
462 .get_mut()
463 .set_time(timer_mode1);
464
465 println!("timer was set: '{}' '{}'", now, snow);
466
467 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
468
469 tokio::select! {
470 read_guard_res = timer.ready(Interest::READABLE) =>
471 {
472 let read_guard = read_guard_res.unwrap();
473
474 let res = read_guard.get_inner().read();
475
476 let ts = chrono::offset::Local::now().timestamp();
477 let e = s.elapsed();
478
479 assert_eq!(res, Ok(TimerReadRes::Ok(1)));
480 assert_eq!(ts, snow);
481
482 println!("timeout e: {:?}, ts:{} snow:{}", e, ts, snow);
483 }
484 }
485 }
486
487 #[test]
488 fn test4_cancel()
489 {
490 let timer =
491 TimerFdInternal::new(Cow::Borrowed("test"), TimerType::CLOCK_REALTIME,
492 TimerFlags::TFD_NONBLOCK).unwrap();
493
494 let now = chrono::offset::Local::now().timestamp();
495 let snow = now + 3;
496 let s = Instant::now();
497
498 let timer_mode1 =
499 TimerExpMode::<AbsoluteTime>::new_oneshot(
500 AbsoluteTime::new_time(snow, 0).unwrap()
501 );
502
503 let res =
504 timer
505 .set_time(timer_mode1);
506 println!("timer was set: '{}' '{}'", now, snow);
507
508 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
509
510
511
512 let ovf = timer.read().unwrap();
513
514 println!("{}", ovf);
515
516 timer.unset_time().unwrap();
517
518 let ovf = timer.read().unwrap();
519
520 println!("{}", ovf);
521 }
534
535}