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