Skip to main content

sark_core/deadline/
exact.rs

1use o3::depot::{
2    capacity,
3    heap::{self, keyed},
4};
5
6use crate::{deadline, manifold};
7
8/// Specialized one-action book with the minimum resident footprint.
9pub struct Exact<K: manifold::raw::Key, P: Copy + Ord> {
10    heap: keyed::Min<K, deadline::Scheduled<P>>,
11}
12
13impl<K: manifold::raw::Key, P: Copy + Ord> Exact<K, P> {
14    pub fn try_new(capacity: capacity::Count) -> Result<Self, heap::Error> {
15        Ok(Self {
16            heap: keyed::Min::try_new(capacity)?,
17        })
18    }
19}
20
21impl<K: manifold::raw::Key, P: Copy + Ord> deadline::Book<K, P> for Exact<K, P> {
22    fn schedule(&mut self, key: K, item: deadline::Scheduled<P>) -> Result<(), deadline::Error<K>> {
23        match self.heap.entry(key) {
24            Err(error) => {
25                return Err(deadline::Error::OutOfRange {
26                    key: error.key(),
27                    capacity: error.capacity(),
28                });
29            }
30            Ok(keyed::Entry::Vacant(entry)) => entry.insert(item),
31            Ok(keyed::Entry::Occupied(entry)) if *entry.priority() == item => {}
32            Ok(keyed::Entry::Occupied(entry)) => entry.set(item),
33            Ok(keyed::Entry::Conflict(error)) => {
34                return Err(deadline::Error::Conflict {
35                    requested: error.requested(),
36                    current: error.current(),
37                });
38            }
39        }
40        Ok(())
41    }
42
43    fn cancel(&mut self, key: K) -> deadline::Mutation {
44        let heap::Probe::Occupied(entry) = self.heap.probe(key) else {
45            return deadline::Mutation::Unchanged;
46        };
47        entry.retire_min().into()
48    }
49
50    fn cancel_one(&mut self, key: K, action: deadline::Action) -> deadline::Mutation {
51        let heap::Probe::Occupied(entry) = self.heap.probe(key) else {
52            return deadline::Mutation::Unchanged;
53        };
54        if entry.priority().action != action {
55            return deadline::Mutation::Unchanged;
56        }
57        entry.retire_min().into()
58    }
59
60    fn peek(&self) -> Option<(K, deadline::Scheduled<P>)> {
61        self.heap.peek().map(|(key, item)| (key, *item))
62    }
63
64    fn poll_due(&mut self, now: P) -> deadline::Poll<deadline::Expired<K, P>> {
65        let Some(entry) = self.heap.first_entry() else {
66            return deadline::Poll::Idle;
67        };
68        if entry.priority().at > now {
69            return deadline::Poll::Idle;
70        }
71        deadline::Poll::Expired(deadline::Expired {
72            key: entry.key(),
73            scheduled: entry.remove(),
74        })
75    }
76
77    fn len(&self) -> usize {
78        self.heap.len()
79    }
80}