timer_deque_rs/lib.rs
1/*-
2 * timer-deque-rs - a Rust crate which provides timer and timer queues based on target OS
3 * functionality.
4 *
5 * Copyright (C) 2025 Aleksandr Morozov alex@nixd.org
6 * 4neko.org alex@4neko.org
7 *
8 * The timer-rs crate can be redistributed and/or modified
9 * under the terms of either of the following licenses:
10 *
11 * 1. the Mozilla Public License Version 2.0 (the “MPL”) OR
12 *
13 * 2. The MIT License (MIT)
14 *
15 * 3. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
16 */
17
18//! # timer-deque-rs
19//!
20//! ## A crate which combines a timer with the different deque types.
21//!
22//! <img src="https://cdn.4neko.org/timer_deque_rs.webp" width="280"/> <img src="https://cdn.4neko.org/source_avail.webp" width="280"/> <img src="https://cdn.4neko.org/mit_mpl_eupl_2.webp" width="280"/>
23//!
24//! ## Timer dequeue
25//!
26//! A deque which uses timer to deque objects.
27//!
28//! ### Two deque opeartion modes:
29//!
30//! * [DequeOnce] - after a timeout an item is removed from the queue.
31//!
32//! * [DequePeriodic] - after the timeout an item's timeout is extended
33//! and item is returned back to queue. It should be manually removed.
34//!
35//! ## Features
36//!
37//! ### MIO
38//! - `enable_mio_compat` - enables the crate [MIO](https://crates.io/crates/mio) and adds support for [OrderTimerDeque] and [TimerFd]
39//!
40//! ### Below is related to BSD systems
41//! - `bsd_use_timerfd` - use `timerfd` instead of `kqueue`
42//! - `bsd_use_poll` - use `poll` instread of `kqueue`
43//!
44//! ### Two deque types:
45//!
46//! #### [TimerDequeConsumer] consumes the item and places it on the queue.
47//! ```ignore
48//! let time_list =
49//! OrderTimerDeque
50//! ::<DequeOnce, TimerDequeConsumer<Arc<TestItem>, _>>
51//! ::new("test_label".into(), 4, false, true).unwrap();
52//! ```
53//! or
54//! ```ignore
55//! let time_list =
56//! OrderTimerDeque
57//! ::<DequePeriodic, TimerDequeConsumer<Arc<TestItem>, _>>
58//! ::new("test_label".into(), 4, false, true).unwrap();
59//! ```
60//!
61//! #### [TimerDequeTicketIssuer] issues a ticket for each iem in the queue.
62//!
63//! ```ignore
64//! let time_list =
65//! OrderTimerDeque
66//! ::<DequeOnce, TimerDequeTicketIssuer<_>>
67//! ::new("test_label".into(), 4, false, true).unwrap();
68//! ```
69//! or
70//! ```ignore
71//! let time_list =
72//! OrderTimerDeque
73//! ::<DequePeriodic, TimerDequeTicketIssuer<_>>
74//! ::new("test_label".into(), 4, false, true).unwrap();
75//! ```
76//!
77//! ## Timers polling
78//!
79//! ### Async poll using Tokio
80//!
81//! ```ignore
82//! let time_list =
83//! OrderTimerDeque
84//! ::<DequeOnce, TimerDequeConsumer<Arc<TestItem>, _>>
85//! ::new("test_label_async".into(), 4, false, true)
86//! .unwrap();
87//!
88//! let mut time_list =
89//! AsyncFd::try_with_interest(time_list, Interest::READABLE).unwrap();
90//!
91//! // poll for event
92//! let mut guard = time_list.readable_mut().await.unwrap();
93//!
94//! // process
95//! let timeout_items = guard.get_inner_mut().async_poll_for_event_and_process().await.unwrap();
96//! drop(guard);
97//! ```
98//!
99//! ### Async poll using SMOLL
100//!
101//! For SMOLL the same method can be used as for Tokio.
102//!
103//! ### Async poll
104//!
105//! Not very efficient but timer provides the [Future], so by calling
106//!
107//! ```ignore
108//! let timeout_items = guard.get_inner_mut().async_poll_for_event_and_process().await;
109//! ```
110//!
111//! depending on the timer FD mode, this funcion will either block until result or return imidiatly
112//! with some result i.e WouldBlock.
113//!
114//! ### Sync poll
115//!
116//! For the `sync` a `Epoll` for Linux and `Kqueue` for BSD are used. Both are
117//! wrapped into [TimerPoll].
118//!
119//! ```ignore
120//! let ev_watch = TimerPoll::new().unwrap();
121//!
122//! let time_list =
123//! OrderTimerDeque
124//! ::<DequeOnce, TimerDequeConsumer<Arc<TestItem>, _>>
125//! ::new("test_label".into(), 4, false, true).unwrap();
126//!
127//! // adds timer to event
128//! let mut time_list_poll = ev_watch.add(time_list).unwrap();
129//!
130//! // adds timeout
131//! let tss_set1 = DequeOnce::new(abs_time.clone().add_sec(3));
132//! let ent1 = Arc::new(TestItem(1));
133//!
134//! time_list_poll.get_inner_mut().add(ent1.clone(), tss_set1).unwrap();
135//!
136//! // polling
137//! let res = ev_watch.poll(Option::None).unwrap();
138//!
139//! // processing
140//! let timeout_items = time_list_poll.get_inner_mut().handle_timer_event(res.unwrap().pop().unwrap()).unwrap();
141//! ```
142//!
143//! ## Timer
144//!
145//! A timer can be used directly.
146//!
147//! ```ignore
148//! // timer init as blocking
149//! let timer =
150//! TimerFd::new(Cow::Borrowed("test"), TimerType::CLOCK_REALTIME, TimerFlags::empty()).unwrap();
151//!
152//! // setting the timout and timer mode
153//! let abs_time = AbsoluteTime::now().add_sec(3);
154//!
155//! // the flags will be set automatically
156//! let exp_time =
157//! TimerExpMode::<AbsoluteTime>::new_oneshot(abs_time);
158//!
159//! // setting timer
160//! let res =
161//! timer.set_time(exp_time);
162//!
163//! // read timer
164//! let ovf = timer.read().unwrap().unwrap();
165//! ```
166//!
167//! The above is not too efficient because in case of `nonblocking`, it will return none immidiatly and
168//! in case of `blocking` it would block thread.
169//!
170//! A `Epoll`, `Select`, `KQueue` can be used to poll timer more efficient. Or, for example, `AsyncFd` from
171//! `tokio` can be used too.
172//!
173//! ## Task spawn and executer
174//!
175//! A parallel task execution based on the task timeout.
176//!
177//! ```ignore
178//!
179//! #[derive(Debug)]
180//! struct TaskStruct1
181//! {
182//! a1: u64,
183//! s: Sender<u64>,
184//! }
185//!
186//! impl TaskStruct1
187//! {
188//! fn new(a1: u64, s: Sender<u64>) -> Self
189//! {
190//! return Self{ a1: a1, s };
191//! }
192//! }
193//!
194//! impl PeriodicTask for TaskStruct1
195//! {
196//! fn exec(&mut self) -> PeriodicTaskResult
197//! {
198//! println!("taskstruct1 val: {}", self.a1);
199//!
200//! let _ = self.s.send(self.a1);
201//!
202//! return PeriodicTaskResult::Ok;
203//! }
204//! }
205//!
206//! // ...
207//!
208//! let s = SyncPeriodicTasks::new(2.try_into().unwrap()).unwrap();
209//!
210//! // ...
211//!
212//! let task1 = TaskStruct1::new(0, send.clone());
213//! let task1_ptt =
214//! PeriodicTaskTime::interval(RelativeTime::new_time(1, 0));
215//!
216//! let task5 = TaskStruct1::new(4, send.clone());
217//! let task5_ptt =
218//! PeriodicTaskTime::exact_time(AbsoluteTime::now() + RelativeTime::new_time(5, 0));
219//!
220//! let task1_guard = s.add("task1", task1, task1_ptt).unwrap();
221//! let task5_guard = s.add("task5", task5, task5_ptt).unwrap();
222//!
223//! // ...
224//! ```
225//!
226
227pub extern crate nix;
228pub extern crate bitflags;
229pub extern crate chrono;
230pub extern crate rand;
231pub extern crate crossbeam_deque;
232
233#[cfg(target_os = "windows")]
234extern crate windows;
235
236#[cfg(any(
237 target_os = "freebsd",
238 target_os = "dragonfly",
239 target_os = "netbsd",
240 target_os = "openbsd",
241 target_os = "macos",
242))]
243extern crate crossbeam_utils;
244
245#[cfg(any(
246 target_os = "freebsd",
247 target_os = "dragonfly",
248 target_os = "netbsd",
249 target_os = "openbsd",
250 target_os = "macos",
251))]
252extern crate instance_copy_on_write;
253
254#[cfg(feature = "enable_mio_compat")]
255extern crate mio;
256
257/// All code which should be ported to the specific OS. Contains a system timer
258/// implementation and poll.
259pub mod timer_portable;
260
261/// Crates error handling.
262pub mod error;
263
264/// Common things.
265pub mod common;
266
267pub mod periodic_task;
268
269/// A base implementation of the sorted timer timeout queue.
270pub mod deque_timeout;
271
272
273#[cfg(feature = "enable_mio_compat")]
274pub use timer_portable::TimerFdMioCompat;
275
276pub use deque_timeout::
277{
278 DequeOnce,
279 DequePeriodic,
280 OrderTimerDeque,
281 OrderedTimerDequeMode,
282 timer_tickets::{TimerDequeTicketIssuer, TimerDequeTicket},
283 timer_consumer::TimerDequeConsumer
284};
285
286pub use timer_portable::{TimerFd, TimerPoll, TimerReadRes, FdTimerCom, AbsoluteTime, RelativeTime};
287
288pub use common::TimerDequeId;
289
290pub use periodic_task::{PeriodicTask, PeriodicTaskResult, SyncPeriodicTasks, PeriodicTaskTime};
291