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