Skip to main content

dope_core/driver/settings/demands/
mod.rs

1use o3::depot::capacity;
2
3use crate::{
4    driver::{route::table::conn, settings, settings::errors},
5    io::transfer,
6};
7
8pub mod slots;
9
10#[derive(Clone, Copy, Default, Eq, PartialEq)]
11#[repr(C)]
12pub struct Files {
13    accepted: Accept,
14    outbound: Outbound,
15}
16
17#[derive(Clone, Copy, Default, Eq, PartialEq)]
18#[repr(transparent)]
19pub struct Accept(u32);
20
21#[derive(Clone, Copy, Default, Eq, PartialEq)]
22#[repr(transparent)]
23pub struct Outbound(u32);
24
25impl Files {
26    pub const ZERO: Self = Self::new(Accept::ZERO, Outbound::ZERO);
27
28    pub const fn new(accepted: Accept, outbound: Outbound) -> Self {
29        Self { accepted, outbound }
30    }
31
32    pub const fn accept(accepted: Accept) -> Self {
33        Self::new(accepted, Outbound::ZERO)
34    }
35
36    pub const fn only_out(outbound: Outbound) -> Self {
37        Self::new(Accept::ZERO, outbound)
38    }
39
40    pub const fn accepted(self) -> Accept {
41        self.accepted
42    }
43
44    pub const fn outbound(self) -> Outbound {
45        self.outbound
46    }
47
48    pub(in crate::driver::settings) fn merge(self, next: Self) -> Result<Self, errors::Claim> {
49        let current = self.accepted.get();
50        let added = next.accepted.get();
51        let accepted = Accept(
52            current
53                .checked_add(added)
54                .ok_or(errors::Claim::AcceptedDescriptorsOverflow { current, added })?,
55        );
56        let current = self.outbound.get();
57        let added = next.outbound.get();
58        let outbound = Outbound(
59            current
60                .checked_add(added)
61                .ok_or(errors::Claim::OutboundDescriptorsOverflow { current, added })?,
62        );
63        Ok(Self::new(accepted, outbound))
64    }
65}
66
67impl Accept {
68    pub const ZERO: Self = Self(0);
69    pub(in crate::driver::settings) const fn get(self) -> u32 {
70        self.0
71    }
72}
73
74impl From<slots::Slots> for Accept {
75    fn from(slots: slots::Slots) -> Self {
76        Self(slots.raw())
77    }
78}
79
80impl From<conn::Capacity> for Accept {
81    fn from(capacity: conn::Capacity) -> Self {
82        Self(capacity.raw())
83    }
84}
85
86impl Outbound {
87    pub const ZERO: Self = Self(0);
88
89    pub const fn new(count: capacity::Count) -> Self {
90        Self(count.raw())
91    }
92
93    pub const fn fixed<const VALUE: u32>() -> Self {
94        Self(VALUE)
95    }
96    pub(in crate::driver::settings) const fn get(self) -> u32 {
97        self.0
98    }
99
100    pub const fn scale<const FACTOR: u32>(capacity: conn::Capacity) -> Self {
101        Self(capacity.scale::<FACTOR>().raw())
102    }
103}
104
105impl TryFrom<usize> for Accept {
106    type Error = Overflow;
107    fn try_from(value: usize) -> Result<Self, Self::Error> {
108        Ok(Self(capacity::Count::try_from(value)?.raw()))
109    }
110}
111
112impl TryFrom<usize> for Outbound {
113    type Error = Overflow;
114    fn try_from(value: usize) -> Result<Self, Self::Error> {
115        Ok(Self::new(capacity::Count::try_from(value)?))
116    }
117}
118
119/// Additive receive-pool demand. Entries compose by addition while buffer
120/// length composes by maximum because every slot uses the largest framing.
121#[derive(Clone, Copy, Eq, PartialEq)]
122#[repr(C)]
123pub struct Receive {
124    entries: Entries,
125    buffer_len: transfer::Len,
126}
127
128/// Additive receive-slot demand representable by the claim accumulator.
129#[derive(Clone, Copy, Default, Eq, PartialEq)]
130#[repr(transparent)]
131pub struct Entries(u32);
132
133#[derive(Clone, Copy, Debug, Eq, PartialEq)]
134#[repr(transparent)]
135pub struct Overflow {
136    actual: usize,
137}
138
139#[derive(Clone, Copy, Default, Eq, PartialEq)]
140#[repr(transparent)]
141pub struct Submit(u32);
142
143/// Ready and timer slot counts, added for claims and resolved against a baseline.
144#[derive(Clone, Copy, Default, Eq, PartialEq)]
145#[repr(C)]
146pub struct Schedule {
147    ready: slots::Slots,
148    timers: slots::Slots,
149}
150
151impl Receive {
152    pub const ZERO: Self = Self {
153        entries: Entries::ZERO,
154        buffer_len: transfer::Len::ZERO,
155    };
156
157    pub const fn new(entries: Entries, len: transfer::Len) -> Self {
158        Self {
159            entries,
160            buffer_len: len,
161        }
162    }
163
164    pub const fn entries(self) -> Entries {
165        self.entries
166    }
167
168    pub const fn buffer_len(self) -> transfer::Len {
169        self.buffer_len
170    }
171
172    pub(in crate::driver::settings) fn merge(self, next: Self) -> Result<Self, errors::Claim> {
173        let entries = self.entries.0.checked_add(next.entries.0).ok_or(
174            errors::Claim::ReceiveEntriesOverflow {
175                current: self.entries.0,
176                added: next.entries.0,
177            },
178        )?;
179        Ok(Self::new(
180            Entries(entries),
181            self.buffer_len.max(next.buffer_len),
182        ))
183    }
184}
185
186impl From<settings::Receive> for Receive {
187    fn from(layout: settings::Receive) -> Self {
188        Self::new(
189            Entries(u32::from(layout.entries())),
190            transfer::Len::from_nonzero(layout.buffer_len()),
191        )
192    }
193}
194
195impl From<settings::Datagram> for Receive {
196    fn from(layout: settings::Datagram) -> Self {
197        Self::from(layout.receive())
198    }
199}
200
201impl Entries {
202    pub const ZERO: Self = Self(0);
203
204    pub(in crate::driver::settings) const fn get(self) -> u32 {
205        self.0
206    }
207}
208
209impl From<capacity::Count> for Entries {
210    fn from(count: capacity::Count) -> Self {
211        Self(count.raw())
212    }
213}
214
215impl TryFrom<usize> for Entries {
216    type Error = Overflow;
217
218    fn try_from(value: usize) -> Result<Self, Self::Error> {
219        Ok(Self(capacity::Count::try_from(value)?.raw()))
220    }
221}
222
223impl From<capacity::Error> for Overflow {
224    fn from(error: capacity::Error) -> Self {
225        Self::new(error.requested())
226    }
227}
228
229impl Overflow {
230    pub(in crate::driver::settings) const fn new(actual: usize) -> Self {
231        Self { actual }
232    }
233}
234
235impl Default for Receive {
236    fn default() -> Self {
237        Self::ZERO
238    }
239}
240
241impl Submit {
242    pub(in crate::driver::settings) const fn get(self) -> u32 {
243        self.0
244    }
245}
246
247impl From<u32> for Submit {
248    fn from(value: u32) -> Self {
249        Self(value)
250    }
251}
252
253impl Schedule {
254    pub const ZERO: Self = Self::new(slots::Slots::ZERO, slots::Slots::ZERO);
255    pub const DEFAULT: Self = Self::fixed::<1024, 1024>();
256
257    pub const fn new(ready: slots::Slots, timers: slots::Slots) -> Self {
258        Self { ready, timers }
259    }
260
261    pub const fn fixed<const READY: u32, const TIMERS: u32>() -> Self {
262        Self::new(
263            slots::Slots::fixed::<READY>(),
264            slots::Slots::fixed::<TIMERS>(),
265        )
266    }
267
268    #[must_use]
269    pub const fn resolve(self, need: Self) -> Self {
270        Self {
271            ready: self.ready.max(need.ready),
272            timers: self.timers.max(need.timers),
273        }
274    }
275
276    #[must_use]
277    pub const fn ready(self) -> slots::Slots {
278        self.ready
279    }
280
281    #[must_use]
282    pub const fn timers(self) -> slots::Slots {
283        self.timers
284    }
285
286    pub(in crate::driver::settings) fn merge(self, next: Self) -> Result<Self, errors::Claim> {
287        let ready = self
288            .ready
289            .checked_add(next.ready)
290            .map_err(errors::Claim::SchedulerReadyOverflow)?;
291        let timers = self
292            .timers
293            .checked_add(next.timers)
294            .map_err(errors::Claim::SchedulerTimersOverflow)?;
295        Ok(Self::new(ready, timers))
296    }
297}
298
299const _: () = {
300    assert!(core::mem::size_of::<Files>() == 2 * core::mem::size_of::<u32>());
301    assert!(core::mem::size_of::<Accept>() == core::mem::size_of::<u32>());
302    assert!(core::mem::size_of::<Outbound>() == core::mem::size_of::<u32>());
303    assert!(core::mem::size_of::<Receive>() == 2 * core::mem::size_of::<u32>());
304    assert!(core::mem::size_of::<Entries>() == core::mem::size_of::<u32>());
305    assert!(core::mem::size_of::<Submit>() == core::mem::size_of::<u32>());
306    assert!(core::mem::size_of::<Schedule>() == 2 * core::mem::size_of::<u32>());
307};