timer_deque_rs/deque_timeout/
timer_tickets.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
18use std::{borrow::Borrow, fmt, sync::{Arc, Weak}};
19
20use crate::
21{
22    common::TimerDequeId, 
23    deque_timeout::{OrderedTimerDequeHandle, OrderedTimerDequeInterf, OrderedTimerDequeMode}, 
24    error::{TimerErrorType, TimerResult}, 
25    map_timer_err, 
26    timer_portable::timer::{AbsoluteTime, RelativeTime}
27};
28
29
30
31/// A ticket which is issued to the caller. 
32/// If `TimerDequeTicket` is dropped, the [Weak] reference to [Arc]
33/// will no longer be valid and the timer would ignore the instance and remove
34/// it from the queue independeltly from the deque operation mode.
35#[derive(Debug, Hash, Eq, PartialOrd, Ord)]
36pub struct TimerDequeTicket
37{
38    /// It holds the uniq ID which can be used to remove the instance 
39    /// from the queue manually.
40    status: Arc<TimerDequeId>,
41}
42
43impl AsRef<TimerDequeId> for TimerDequeTicket
44{
45    fn as_ref(&self) -> &TimerDequeId 
46    {
47        return &self.status;
48    }
49}
50
51impl Borrow<TimerDequeId> for TimerDequeTicket
52{
53    fn borrow(&self) -> &TimerDequeId 
54    {
55        return &self.status;
56    }
57}
58
59impl fmt::Display for TimerDequeTicket
60{
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
62    {
63        write!(f, "{}", self.status)
64    }
65}
66
67impl PartialEq for TimerDequeTicket
68{
69    fn eq(&self, other: &Self) -> bool 
70    {
71        return self.status == other.status;
72    }
73}
74
75impl PartialEq<TimerDequeId> for TimerDequeTicket
76{
77    fn eq(&self, other: &TimerDequeId) -> bool 
78    {
79        return self.status.as_ref() == other;
80    }
81}
82
83impl PartialEq<&TimerDequeId> for TimerDequeTicket
84{
85    fn eq(&self, other: &&TimerDequeId) -> bool 
86    {
87        return self.status.as_ref() == *other;
88    }
89}
90
91impl PartialEq<TimerDequeTicket> for TimerDequeId
92{
93    fn eq(&self, other: &TimerDequeTicket) -> bool 
94    {
95        return self == other.status.as_ref();
96    }
97}
98
99impl<MODE: OrderedTimerDequeMode> PartialEq<TimerDequeTicketIssuer<MODE>> for TimerDequeTicket
100{
101    fn eq(&self, other: &TimerDequeTicketIssuer<MODE>) -> bool 
102    {
103        let Some(up) = other.weak_status.upgrade()
104            else { return false };
105
106        return self.status.as_ref() == up.as_ref();
107    }
108}
109
110impl TimerDequeTicket
111{
112    fn new() -> Self
113    {
114        return 
115            Self
116            { 
117                status: 
118                    Arc::new(TimerDequeId::new()),
119            };
120    }
121
122    fn pair(&self) -> Weak<TimerDequeId>
123    {
124        return Arc::downgrade(&self.status);
125    }
126
127    pub 
128    fn get_deque_id(&self) -> &TimerDequeId
129    {
130        return self.status.as_ref();
131    }
132
133    pub 
134    fn is_queued(&self) -> bool
135    {
136        return Arc::weak_count(&self.status) > 1;
137    }
138}
139
140/// A type of deque which issues a `tickets` [TimerDequeTicket] which
141/// contains a [TimerDequeId] - a uniq number of the ticket.
142/// On timeout, the [TimerDequeId] is returned to indentify the timeout
143/// source.
144/// 
145/// # Generics
146/// 
147/// `MODE` - a [OrderedTimerDequeMode] defines the deque behaviour. There are
148///     two types of the operation:
149/// 
150/// * [`DequeOnce`]: crate::deque_timeout#DequeOnce  
151/// After timeout the element is removed from the queue.
152/// 
153/// * [`DequePeriodic`]: crate::deque_timeout#DequePeriodic  
154/// After timeout the element timeout is extended automatically
155/// until the item removed from the queue manually.
156/// 
157/// # Examples
158/// 
159/// ```ignore
160/// let mut time_list = 
161///     OrderedTimerDeque
162///         ::<DequeOnce, TimerDequeTicketIssuer<_>>
163///         ::new("test_label1".into(), 4, false, true)
164///            .unwrap();
165/// ```
166/// or
167/// ```ignore
168/// let mut time_list = 
169///     OrderedTimerDeque
170///         ::<DequePeriodic, TimerDequeTicketIssuer<_>>
171///         ::new("test_label1".into(), 4, false, true)
172///            .unwrap();
173/// ```
174#[derive(Debug)]
175pub struct TimerDequeTicketIssuer<MODE>
176where 
177    MODE: OrderedTimerDequeMode
178{
179    /// A [Weak] reference to [Arc] which holds the queue identification.
180    weak_status: Weak<TimerDequeId>,
181
182    /// An absolute timestamp in seconds (UTC time) sets the timer.
183    timeout_mode: MODE,
184}
185
186impl<MODE: OrderedTimerDequeMode> fmt::Display for TimerDequeTicketIssuer<MODE>
187{  
188    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> 
189    { 
190        write!(f, "{} until: {}", self.weak_status.upgrade().map_or("dropped".into(), |f| f.to_string()), 
191            self.timeout_mode)
192    }
193}
194
195impl<MODE: OrderedTimerDequeMode> Eq for TimerDequeTicketIssuer<MODE> {}
196
197impl<MODE: OrderedTimerDequeMode> PartialEq for TimerDequeTicketIssuer<MODE>
198{
199    fn eq(&self, other: &Self) -> bool 
200    {
201        let s = self.weak_status.upgrade();
202        let o = other.weak_status.upgrade();
203
204        return s == o;
205    }
206}
207
208impl<MODE: OrderedTimerDequeMode> PartialEq<TimerDequeId> for TimerDequeTicketIssuer<MODE>
209{
210    fn eq(&self, other: &TimerDequeId) -> bool 
211    {
212        return 
213            self
214                .weak_status
215                .upgrade()
216                .map_or(false, |f| f.as_ref() == other);
217    }
218}
219
220impl<MODE: OrderedTimerDequeMode> PartialEq<TimerDequeTicket> for TimerDequeTicketIssuer<MODE>
221{
222    fn eq(&self, other: &TimerDequeTicket) -> bool 
223    {
224        let Some(s) = self.weak_status.upgrade()
225            else { return false };
226
227        return s.as_ref() == other.status.as_ref();
228    }
229}
230
231impl<MODE: OrderedTimerDequeMode> Ord for TimerDequeTicketIssuer<MODE>
232{
233    fn cmp(&self, other: &Self) -> std::cmp::Ordering 
234    {
235        return self.timeout_mode.cmp(&other.timeout_mode);
236    }
237}
238
239impl<MODE: OrderedTimerDequeMode> PartialOrd for TimerDequeTicketIssuer<MODE>
240{
241    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> 
242    {
243        return Some(self.cmp(other));
244    }
245}
246
247impl<MODE> TimerDequeTicketIssuer<MODE>
248where   
249    MODE: OrderedTimerDequeMode
250{
251    pub(super)
252    fn new(time: MODE) -> TimerResult<(Self, TimerDequeTicket)>
253    { 
254        time.validate_time(AbsoluteTime::now())?;
255
256        let ext_ticket = TimerDequeTicket::new();
257
258        let int_ticket = 
259            Self
260            {
261                weak_status: 
262                    ext_ticket.pair(),
263                timeout_mode: 
264                   time
265            };
266
267
268        return Ok((int_ticket, ext_ticket));
269    }
270
271    pub(super) 
272    fn get_queue_id(&self) -> TimerResult<Arc<TimerDequeId>>
273    {
274        return 
275            self
276                .weak_status
277                .upgrade()
278                .ok_or(
279                    map_timer_err!(TimerErrorType::TicketInstanceGone, "ticket is no longer valid")
280                );
281    }
282}
283
284impl<MODE> OrderedTimerDequeInterf<MODE> for TimerDequeTicketIssuer<MODE>
285where 
286    MODE: OrderedTimerDequeMode,
287{
288    #[inline]
289    fn get_timeout_absolute(&self) -> AbsoluteTime 
290    {
291        return self.timeout_mode.get_absolut_timeout();
292    }
293}
294
295
296
297impl<MODE> OrderedTimerDequeHandle<MODE> for TimerDequeTicketIssuer<MODE>
298where 
299    MODE: OrderedTimerDequeMode,
300{
301    /// Input item.
302    type TimerId = TimerDequeId;
303
304    type HandleRes = Vec<Self::TimerId>;
305
306    fn handle(mut self, timer_self: &mut super::OrderTimerDeque<MODE, Self>, 
307        timer_ids: &mut Self::HandleRes) -> TimerResult<()>
308    {
309        if let Some(target) = self.into_inner()
310        {
311            timer_ids.push(target);
312
313            self.timeout_mode.advance_timeout();
314
315            if MODE::IS_ONCE == false
316            {
317                return timer_self.queue_item(self);
318            }
319            else
320            {
321                return Ok(());
322            }
323        }
324
325        return Ok(());
326    }
327
328    #[inline]
329    fn is_same(&self, other: &Self::TimerId) -> bool 
330    {
331        return self.into_inner().as_ref() == Some(other);
332    }
333
334    #[inline]
335    fn postpone(&mut self, postp_time: RelativeTime) -> TimerResult<()> 
336    {
337        let _ = self.get_queue_id()?;
338
339        return self.timeout_mode.postpone(postp_time);
340    }
341    
342    #[inline]
343    fn resched(&mut self, time: MODE) -> TimerResult<()> 
344    {
345        let _ = self.get_queue_id()?;
346
347        self.timeout_mode = time;
348
349        return Ok(());
350    }
351
352    #[inline]
353    fn into_timer_id(self) -> Option<Self::TimerId>
354    {
355        return self.into_inner();
356    }
357}
358
359impl<MODE: OrderedTimerDequeMode> TimerDequeTicketIssuer<MODE>
360{
361    /// Checks if the instance is still actual i.e was not dropeed.
362    fn is_valid(&self) -> bool
363    {
364        return self.weak_status.upgrade().is_some();
365    }
366
367    /// Obtains the [TimerDequeueId] only if the [Weak] pointer `weak_status`
368    /// to ID is still actual.
369    fn into_inner(&self) -> Option<TimerDequeId>
370    {
371        return self.weak_status.upgrade().map(|f| *f.as_ref());
372    }
373}
374