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