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. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
14 */
15
16//! # timer-deque-rs
17//!
18//! ## A crate which combines a timer with the different deque types.
19//!
20//! <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/mpl_or_eupl_500.webp" width="280"/>
21//!
22//! ## Timer dequeue
23//!
24//! A deque which uses timer to deque objects.
25//!
26//! ### Two deque opeartion modes:
27//!
28//! * [OrderdTimerDequeOnce] - after a timeout an item is removed from the queue.
29//!
30//! * [OrderdTimerDequePeriodic] - after the timeout an item's timeout is extended
31//! and item is returned back to queue. It should be manually removed.
32//!
33//! ### Three deque types:
34//!
35//! [TimerDequeueConsumer] consumes the item and places it on the queue.
36//! ```ignore
37//! let mut time_list =
38//! OrderedTimerDeque
39//! ::<TimerDequeueConsumer<TestItem, OrderdTimerDequeOnce>>
40//! ::new("test_label".into(), 4, false).unwrap();
41//! ```
42//! or
43//! ```ignore
44//! let mut time_list =
45//! OrderedTimerDeque
46//! ::<TimerDequeueConsumer<TestItem, OrderdTimerDequePeriodic>>
47//! ::new("test_label".into(), 4, false).unwrap();
48//! ```
49//!
50//! [TimerDequeueSignalTicket] sends signal as specified in the callback(non-blocking) for every added item.
51//! ```ignore
52//! let mut time_list =
53//! OrderedTimerDeque
54//! ::<TimerDequeueSignalTicket<TestSigStruct, OrderdTimerDequeOnce>>
55//! ::new("test_label".into(), 4, false).unwrap();
56//! ```
57//! or
58//! ```ignore
59//! let mut time_list =
60//! OrderedTimerDeque
61//! ::<TimerDequeueSignalTicket<TestSigStruct, OrderdTimerDequePeriodic>>
62//! ::new("test_label".into(), 4, false).unwrap();
63//! ```
64//!
65//!
66//! [TimerDequeueTicketIssuer] issues a ticket which can be dropped (deallocated), so timer would ignore item.
67//! ```ignore
68//! let mut time_list =
69//! OrderedTimerDeque
70//! ::<TimerDequeueTicketIssuer<OrderdTimerDequeOnce>>
71//! ::new("test_label".into(), 4, false).unwrap();
72//! ```
73//! or
74//! ```ignore
75//! let mut time_list =
76//! OrderedTimerDeque
77//! ::<TimerDequeueTicketIssuer<OrderdTimerDequePeriodic>>
78//! ::new("test_label".into(), 4, false).unwrap();
79//! ```
80//!
81//!
82//! ## Timers polling
83//!
84//! For the `sync` a `Epoll` for Linux and `Kqueue` for BSD are used. Both are
85//! wrapped into [TimerPoll].
86//!
87//! ```ignore
88//! let ev_watch = TimerPoll::new().unwrap();
89//!
90//! let mut time_list =
91//! OrderedTimerDeque
92//! ::<TimerDequeueConsumer<Arc<TestItem>, OrderdTimerDequeOnce>>
93//! ::new("test_label".into(), 4, false).unwrap();
94//!
95//! // add timer to event
96//! ev_watch.add(&time_list).unwrap();
97//! ```
98//! In case if monitored timer, for example, `time_list` from above exmaple would be dropped intentionally or
99//! by acident, it will be automatically removed from the poll queue. If, for any reason the `ev_watch` becomes
100//! invalid i.e dropped, all added instances will be unbinded from this [TimerPoll] instance and can be reused.
101//!
102//! Alternativly, [OrderedTimerDeque] provides blocking/nonblocking function
103//! `wait_for_event` which is less efficient.
104//!
105//! For the `async` a [Future] is implemented. Polling `future` is not too
106//! efficient (the same situation with `wait_for_event`).
107//!
108//! ```ignore
109//! let mut time_list =
110//! OrderedTimerDeque
111//! ::<TimerDequeueConsumer<Arc<TestItem>, OrderdTimerDequeOnce>>
112//! ::new("test_label_async".into(), 4, false)
113//! .unwrap();
114//!
115//! let res = time_list.poll().await.unwrap();
116//!
117//! // ...
118//! // read timeout items
119//! time_list.timeout_event_handler(res, &mut timeout_items).unwrap();
120//! ```
121//!
122//! For more efficient `polling` of Timer for event, use async crates like
123//! `smol`, `tokio` or other. In case of `tokio` an `AsyncFd can be used.`
124//!
125//! ```ignore
126//! let time_list =
127//! OrderedTimerDeque
128//! ::<TimerDequeueSignalTicket<TestStruct>, OrderdTimerDequeOnce>
129//! ::new("test_label".into(), 4, false)
130//! .unwrap();
131//!
132//! let mut async_time_list = AsyncFd::new(time_list).unwrap();
133//!
134//!
135//! // poll the timer until it becomes ready
136//! let mut read_guard =
137//! async_time_list.ready_mut(Interest::READABLE).await.unwrap();
138//!
139//! // clear ready otherwise it will return WOULDBLOCK
140//! read_guard.clear_ready();
141//!
142//! // read events
143//! let res = read_guard.get_inner().wait_for_event().unwrap();
144//! ```
145//!
146//! ## Timer
147//!
148//! A timer can be used directly.
149//!
150//! ```ignore
151//! // timer init as blocking
152//! let timer =
153//! TimerFd::new(Cow::Borrowed("test"), TimerType::CLOCK_REALTIME, TimerFlags::empty()).unwrap();
154//!
155//! // setting the timout and timer mode
156//! let abs_time = AbsoluteTime::now().add_sec(3);
157//!
158//! // the flags will be set automatically
159//! let exp_time =
160//! TimerExpMode::<AbsoluteTime>::new_oneshot(abs_time);
161//!
162//! // setting timer
163//! let res =
164//! timer.set_time(exp_time);
165//!
166//! // read timer
167//! let ovf = timer.read().unwrap().unwrap();
168//! ```
169//!
170//! The above is not too efficient because in case of `nonblocking`, it will return none immidiatly and
171//! in case of `blocking` it would block thread.
172//!
173//! A `Epoll`, `Select`, `KQueue` can be used to poll timer more efficient. Or, for example, `AsyncFd` from
174//! `tokio` can be used too.
175//!
176//! ## Task spawn and executer
177//!
178//! A parallel task execution based on the task timeout.
179//!
180//! ```ignore
181//!
182//! #[derive(Debug)]
183//! struct TaskStruct1
184//! {
185//! a1: u64,
186//! s: Sender<u64>,
187//! }
188//!
189//! impl TaskStruct1
190//! {
191//! fn new(a1: u64, s: Sender<u64>) -> Self
192//! {
193//! return Self{ a1: a1, s };
194//! }
195//! }
196//!
197//! impl PeriodicTask for TaskStruct1
198//! {
199//! fn exec(&mut self) -> PeriodicTaskResult
200//! {
201//! println!("taskstruct1 val: {}", self.a1);
202//!
203//! let _ = self.s.send(self.a1);
204//!
205//! return PeriodicTaskResult::Ok;
206//! }
207//! }
208//!
209//! // ...
210//!
211//! let s = SyncPeriodicTasks::new(2.try_into().unwrap()).unwrap();
212//!
213//! // ...
214//!
215//! let task1 = TaskStruct1::new(0, send.clone());
216//! let task1_ptt =
217//! PeriodicTaskTime::interval(RelativeTime::new_time(1, 0));
218//!
219//! let task5 = TaskStruct1::new(4, send.clone());
220//! let task5_ptt =
221//! PeriodicTaskTime::exact_time(AbsoluteTime::now() + RelativeTime::new_time(5, 0));
222//!
223//! let task1_guard = s.add("task1", task1, task1_ptt).unwrap();
224//! let task5_guard = s.add("task5", task5, task5_ptt).unwrap();
225//!
226//! // ...
227//! ```
228//!
229
230pub extern crate nix;
231pub extern crate bitflags;
232pub extern crate chrono;
233pub extern crate rand;
234pub extern crate crossbeam_deque;
235
236/// All code which should be ported to the specific OS. Contains a system timer
237/// implementation and poll.
238pub mod timer_portable;
239
240/// Crates error handling.
241pub mod error;
242
243/// Common things.
244pub mod common;
245
246pub mod periodic_task;
247
248/// A base implementation of the sorted timer timeout queue.
249pub mod deque_timeout;
250
251//pub mod shared_state;
252
253//pub mod periodic_timeout;
254
255#[cfg(test)]
256mod tests;
257
258// deque
259pub use deque_timeout::{OrderedTimerDeque, OrderdTimerDequeOnce, OrderdTimerDequePeriodic};
260
261pub use deque_timeout::timer_consumer::TimerDequeueConsumer;
262pub use deque_timeout::timer_signal::{TimerDequeueSignal, TimerDequeueSignalTicket};
263pub use deque_timeout::timer_tickets::{TimerDequeueTicketIssuer, TimerDequeueTicket};
264
265pub use timer_portable::{TimerPoll, TimerReadRes, FdTimerCom, AbsoluteTime, RelativeTime};
266
267pub use common::TimerDequeueId;
268
269pub use periodic_task::{PeriodicTask, PeriodicTaskResult, SyncPeriodicTasks, PeriodicTaskTime};
270