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