timer_deque_rs/timer_portable/unix/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::timer_portable::unix::{TimerFlags, TimerType, UnixFd};
35use crate::{map_portable_err, portable_err, AbsoluteTime};
36use crate::timer_portable::
37{
38 AsTimerId, FdTimerCom, TimerExpMode, TimerId
39};
40
41
42#[derive(Debug)]
50pub struct TimerFdInternal
51{
52 label: Cow<'static, str>,
54
55 timer_fd: OwnedFd,
57}
58
59impl fmt::Display for TimerFdInternal
60{
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
62 {
63 write!(f, "{}", self.timer_fd.as_raw_fd())
64 }
65}
66
67impl AsFd for TimerFdInternal
68{
69 fn as_fd(&self) -> BorrowedFd<'_>
70 {
71 return self.timer_fd.as_fd();
72 }
73}
74
75impl AsRawFd for TimerFdInternal
76{
77 fn as_raw_fd(&self) -> RawFd
78 {
79 return self.timer_fd.as_raw_fd();
80 }
81}
82
83impl Eq for TimerFdInternal {}
84
85impl PartialEq for TimerFdInternal
86{
87 fn eq(&self, other: &Self) -> bool
88 {
89 return self.timer_fd.as_raw_fd() == other.timer_fd.as_raw_fd();
90 }
91}
92
93impl PartialEq<RawFd> for TimerFdInternal
94{
95 fn eq(&self, other: &RawFd) -> bool
96 {
97 return self.timer_fd.as_raw_fd() == *other;
98 }
99}
100
101impl PartialEq<str> for TimerFdInternal
102{
103 fn eq(&self, other: &str) -> bool
104 {
105 return self.label == other;
106 }
107}
108
109impl AsRef<str> for TimerFdInternal
110{
111 fn as_ref(&self) -> &str
112 {
113 return &self.label;
114 }
115}
116
117impl UnixFd for TimerFdInternal
118{
119
120}
121
122impl AsTimerId for TimerFdInternal
123{
124 fn as_timer_id(&self) -> TimerId
125 {
126 return TimerId::from(self.timer_fd.as_raw_fd());
127 }
128}
129
130
131impl Ord for TimerFdInternal
132{
133 fn cmp(&self, other: &Self) -> std::cmp::Ordering
134 {
135 return self.timer_fd.as_raw_fd().cmp(&other.timer_fd.as_raw_fd());
136 }
137}
138
139impl PartialOrd for TimerFdInternal
140{
141 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering>
142 {
143 return Some(self.cmp(other));
144 }
145}
146
147impl FdTimerRead for TimerFdInternal
148{
149 #[inline]
150 fn read(&self) -> TimerPortResult<TimerReadRes<u64>>
151 {
152 let mut timer_overfl = [0u8; size_of::<u64>()];
153
154 loop
155 {
156 let ret =
157 nix::unistd::read(&self.timer_fd, &mut timer_overfl);
158
159 if let Ok(_) = ret
160 {
161 let overl: u64 = u64::from_ne_bytes(timer_overfl);
162
163 return Ok(TimerReadRes::Ok(overl));
164 }
165 else if let Err(Errno::EINTR) = ret
166 {
167 continue;
168 }
169 else if let Err(Errno::EAGAIN) = ret
170 {
171 return Ok(TimerReadRes::WouldBlock);
173 }
174 else if let Err(Errno::ECANCELED) = ret
175 {
176 return Ok(TimerReadRes::Cancelled);
177 }
178 else if let Err(e) = ret
179 {
180 portable_err!(e, "read timer overflow error for timer: '{}'", self.label)
181 }
182 }
183 }
184}
185
186impl FdTimerCom for TimerFdInternal
187{
188 fn new(label: Cow<'static, str>, timer_type: TimerType, timer_flags: TimerFlags) -> TimerPortResult<Self>
189 where
190 Self: Sized
191 {
192 let timer_fd =
193 unsafe { libc::timerfd_create(timer_type.into(), timer_flags.bits()) };
194
195 if timer_fd == -1
196 {
197 portable_err!(Errno::last(), "timer: '{}', timerfd_create failed with error", label);
198 }
199
200 return Ok(
201 Self
202 {
203 label:
204 label,
205 timer_fd:
206 unsafe { OwnedFd::from_raw_fd(timer_fd) },
207 }
210 );
211 }
212
213 fn set_time<TIMERTYPE: ModeTimeType>(&self, timer_exp: TimerExpMode<TIMERTYPE>) -> TimerPortResult<()>
214 {
215 let flags = TIMERTYPE::get_flags().bits();
219 let timer_value: itimerspec = timer_exp.into();
220
221 let res =
222 unsafe
223 {
224 libc::timerfd_settime(self.timer_fd.as_raw_fd(), flags,
225 &timer_value, core::ptr::null_mut())
226 };
227
228 if res == -1
229 {
230 portable_err!(Errno::last(), "can not init timer: '{}'", self.label);
231 }
232
233 return Ok(());
234 }
235
236 fn unset_time(&self) -> TimerPortResult<()>
237 {
238 let mut timer_value: itimerspec = unsafe { std::mem::zeroed() };
240
241 let res =
242 unsafe
243 {
244 libc::timerfd_gettime(self.timer_fd.as_raw_fd(),
245 &mut timer_value as *mut _ as *mut itimerspec)
246 };
247
248 if res == -1
249 {
250 portable_err!(Errno::last(), "can not timerfd_gettime for timer: '{}'", self.label);
251 }
252
253 let timer_mode = TimerExpMode::<AbsoluteTime>::from(timer_value);
254
255 if TimerExpMode::<AbsoluteTime>::reset() == timer_mode
256 {
257 return Ok(());
259 }
260
261 let timer_value: itimerspec = TimerExpMode::<AbsoluteTime>::reset().into();
264
265 let res =
266 unsafe
267 {
268 libc::timerfd_settime(self.timer_fd.as_raw_fd(), 0,
269 &timer_value, core::ptr::null_mut())
270 };
271
272 if res == -1
273 {
274 portable_err!(Errno::last(), "can not unset timer: '{}'", self.label);
275 }
276
277 return Ok(());
278 }
279
280 fn set_nonblocking(&self, flag: bool) -> TimerPortResult<()>
281 {
282 let mut fl =
283 OFlag::from_bits_retain(
284 fcntl::fcntl(&self.timer_fd, FcntlArg::F_GETFL)
285 .map_err(|e|
286 map_portable_err!(e, "timer: '{}', fcntl F_GETFL failed", self.label)
287 )?
288 );
289
290 fl.set(OFlag::O_NONBLOCK, flag);
291
292 fcntl::fcntl(&self.timer_fd, FcntlArg::F_SETFL(fl))
293 .map_err(|e|
294 map_portable_err!(e, "timer: '{}', fcntl F_SETFL failed", self.label)
295 )?;
296
297 return Ok(());
298 }
299
300 fn is_nonblocking(&self) -> TimerPortResult<bool>
301 {
302 let fl =
303 OFlag::from_bits_retain(
304 fcntl::fcntl(&self.timer_fd, FcntlArg::F_GETFL)
305 .map_err(|e|
306 map_portable_err!(e, "timer: '{}', fcntl F_GETFL failed", self.label)
307 )?
308 );
309
310 return Ok(fl.intersects(OFlag::O_NONBLOCK));
311 }
312}
313
314
315impl TimerFdInternal
316{
317
318}
319
320impl Future for &TimerFdInternal
321{
322 type Output = TimerPortResult<TimerReadRes<u64>>;
323
324 fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output>
325 {
326 let res = self.read();
327
328 if let Ok(TimerReadRes::WouldBlock) = res
329 {
330 cx.waker().wake_by_ref();
331
332 return Poll::Pending;
333 }
334 else
335 {
336 return Poll::Ready(res);
337 }
338 }
339}
340
341impl Future for TimerFdInternal
342{
343 type Output = TimerPortResult<TimerReadRes<u64>>;
344
345 fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output>
346 {
347 let res = self.read();
348
349 if let Ok(TimerReadRes::WouldBlock) = res
350 {
351 cx.waker().wake_by_ref();
352
353 return Poll::Pending;
354 }
355 else
356 {
357 return Poll::Ready(res);
358 }
359 }
360}
361
362