1use core::{mem,time};
2
3extern crate alloc;
4use alloc::boxed::Box;
5
6#[derive(PartialEq, Clone, Copy)]
7#[repr(C)]
8struct FatPtr {
9 ptr: usize,
10 vtable: usize,
11}
12
13impl FatPtr {
14 #[inline(always)]
15 const fn null() -> Self {
16 Self {
17 ptr: 0,
18 vtable: 0
19 }
20 }
21
22 #[inline(always)]
23 const fn is_null(&self) -> bool {
24 self.ptr == 0 && self.vtable == 0
25 }
26}
27
28#[cfg(windows)]
29mod win32;
30#[cfg(windows)]
31pub use win32::*;
32
33#[cfg(any(target_os = "macos", target_os = "ios"))]
34mod apple;
35#[cfg(any(target_os = "macos", target_os = "ios"))]
36pub use apple::*;
37
38#[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]
39mod posix;
40#[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]
41pub use posix::*;
42
43unsafe impl Send for Timer {}
44unsafe impl Sync for Timer {}
45
46impl Timer {
47 #[inline(always)]
48 pub const fn schedule(&self) -> Schedule<'_> {
50 Schedule {
51 timer: self,
52 timeout: time::Duration::from_millis(0),
53 interval: time::Duration::from_secs(0),
54 }
55 }
56
57 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
58 #[inline(always)]
59 pub fn schedule_once(&self, timeout: time::Duration) -> bool {
66 assert!(!(timeout.as_secs() == 0 && timeout.as_nanos() == 0), "Cannot set zero initial timeout");
68 self.schedule_interval(timeout, time::Duration::from_secs(0))
69 }
70}
71
72pub struct Schedule<'a> {
76 timer: &'a Timer,
77 timeout: time::Duration,
78 interval: time::Duration,
79}
80
81impl<'a> Schedule<'a> {
82 #[inline(always)]
83 pub const fn initial(mut self, timeout: time::Duration) -> Self {
85 assert!(!(timeout.as_secs() == 0 && timeout.as_nanos() == 0), "Cannot set zero initial timeout");
87 self.timeout = timeout;
88 self
89 }
90
91 #[inline(always)]
92 pub const fn interval(mut self, timeout: time::Duration) -> Self {
97 self.interval = timeout;
98 self
99 }
100
101 #[inline(always)]
102 pub fn schedule(&self) -> bool {
106 if self.timeout == time::Duration::ZERO {
107 self.timer.schedule_interval(self.interval, self.interval)
108 } else {
109 self.timer.schedule_interval(self.timeout, self.interval)
110 }
111 }
112}
113
114struct BoxFnPtr(pub FatPtr);
115
116impl BoxFnPtr {
117 #[inline(always)]
118 const fn null() -> Self {
119 Self(FatPtr::null())
120 }
121
122 #[inline(always)]
123 const fn is_null(&self) -> bool {
124 self.0.is_null()
125 }
126}
127
128impl Drop for BoxFnPtr {
129 #[inline(always)]
130 fn drop(&mut self) {
131 if !self.is_null() {
132 unsafe {
133 let _ = Box::from_raw(mem::transmute::<_, *mut dyn FnMut()>(self.0));
134 }
135 }
136 }
137}