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    pub const fn fixed<const VALUE: u32>() -> Self {
89        Self(VALUE)
90    }
91    pub(in crate::driver::settings) const fn get(self) -> u32 {
92        self.0
93    }
94
95    pub const fn scale<const FACTOR: u32>(capacity: conn::Capacity) -> Self {
96        Self(capacity.scale::<FACTOR>().raw())
97    }
98}
99
100impl TryFrom<usize> for Accept {
101    type Error = Overflow;
102    fn try_from(value: usize) -> Result<Self, Self::Error> {
103        Ok(Self(capacity::Count::try_from(value)?.raw()))
104    }
105}
106
107impl TryFrom<usize> for Outbound {
108    type Error = Overflow;
109    fn try_from(value: usize) -> Result<Self, Self::Error> {
110        Ok(Self(capacity::Count::try_from(value)?.raw()))
111    }
112}
113
114/// Additive receive-pool demand. Entries compose by addition while buffer
115/// length composes by maximum because every slot uses the largest framing.
116#[derive(Clone, Copy, Eq, PartialEq)]
117#[repr(C)]
118pub struct Receive {
119    entries: Entries,
120    buffer_len: transfer::Len,
121}
122
123/// Additive receive-slot demand representable by the claim accumulator.
124#[derive(Clone, Copy, Default, Eq, PartialEq)]
125#[repr(transparent)]
126pub struct Entries(u32);
127
128#[derive(Clone, Copy, Debug, Eq, PartialEq)]
129#[repr(transparent)]
130pub struct Overflow {
131    actual: usize,
132}
133
134#[derive(Clone, Copy, Default, Eq, PartialEq)]
135#[repr(transparent)]
136pub struct Submit(u32);
137
138/// Additive scheduler demand for ready and timer slots.
139#[derive(Clone, Copy, Default, Eq, PartialEq)]
140#[repr(C)]
141pub struct Schedule {
142    ready: slots::Slots,
143    timers: slots::Slots,
144}
145
146impl Receive {
147    pub const ZERO: Self = Self {
148        entries: Entries::ZERO,
149        buffer_len: transfer::Len::ZERO,
150    };
151
152    pub const fn new(entries: Entries, len: transfer::Len) -> Self {
153        Self {
154            entries,
155            buffer_len: len,
156        }
157    }
158
159    pub const fn entries(self) -> Entries {
160        self.entries
161    }
162
163    pub const fn buffer_len(self) -> transfer::Len {
164        self.buffer_len
165    }
166
167    pub(in crate::driver::settings) fn merge(self, next: Self) -> Result<Self, errors::Claim> {
168        let entries = self.entries.0.checked_add(next.entries.0).ok_or(
169            errors::Claim::ReceiveEntriesOverflow {
170                current: self.entries.0,
171                added: next.entries.0,
172            },
173        )?;
174        Ok(Self::new(
175            Entries(entries),
176            self.buffer_len.max(next.buffer_len),
177        ))
178    }
179}
180
181impl From<settings::Receive> for Receive {
182    fn from(layout: settings::Receive) -> Self {
183        Self::new(
184            Entries(u32::from(layout.entries())),
185            transfer::Len::from_nonzero(layout.buffer_len()),
186        )
187    }
188}
189
190impl From<settings::Datagram> for Receive {
191    fn from(layout: settings::Datagram) -> Self {
192        Self::from(layout.receive())
193    }
194}
195
196impl Entries {
197    pub const ZERO: Self = Self(0);
198
199    pub(in crate::driver::settings) const fn get(self) -> u32 {
200        self.0
201    }
202}
203
204impl From<capacity::Count> for Entries {
205    fn from(count: capacity::Count) -> Self {
206        Self(count.raw())
207    }
208}
209
210impl TryFrom<usize> for Entries {
211    type Error = Overflow;
212
213    fn try_from(value: usize) -> Result<Self, Self::Error> {
214        Ok(Self(capacity::Count::try_from(value)?.raw()))
215    }
216}
217
218impl From<capacity::Error> for Overflow {
219    fn from(error: capacity::Error) -> Self {
220        Self::new(error.requested())
221    }
222}
223
224impl Overflow {
225    pub(in crate::driver::settings) const fn new(actual: usize) -> Self {
226        Self { actual }
227    }
228}
229
230impl Default for Receive {
231    fn default() -> Self {
232        Self::ZERO
233    }
234}
235
236impl Submit {
237    pub(in crate::driver::settings) const fn get(self) -> u32 {
238        self.0
239    }
240}
241
242impl From<u32> for Submit {
243    fn from(value: u32) -> Self {
244        Self(value)
245    }
246}
247
248impl Schedule {
249    pub const ZERO: Self = Self::new(slots::Slots::ZERO, slots::Slots::ZERO);
250
251    pub const fn new(ready: slots::Slots, timers: slots::Slots) -> Self {
252        Self { ready, timers }
253    }
254
255    pub const fn fixed<const READY: u32, const TIMERS: u32>() -> Self {
256        Self::new(
257            slots::Slots::fixed::<READY>(),
258            slots::Slots::fixed::<TIMERS>(),
259        )
260    }
261
262    pub const fn ready(self) -> slots::Slots {
263        self.ready
264    }
265
266    pub const fn timers(self) -> slots::Slots {
267        self.timers
268    }
269
270    pub(in crate::driver::settings) fn merge(self, next: Self) -> Result<Self, errors::Claim> {
271        let ready = self
272            .ready
273            .checked_add(next.ready)
274            .map_err(errors::Claim::SchedulerReadyOverflow)?;
275        let timers = self
276            .timers
277            .checked_add(next.timers)
278            .map_err(errors::Claim::SchedulerTimersOverflow)?;
279        Ok(Self::new(ready, timers))
280    }
281}
282
283const _: () = {
284    assert!(core::mem::size_of::<Files>() == 2 * core::mem::size_of::<u32>());
285    assert!(core::mem::size_of::<Accept>() == core::mem::size_of::<u32>());
286    assert!(core::mem::size_of::<Outbound>() == core::mem::size_of::<u32>());
287    assert!(core::mem::size_of::<Receive>() == 2 * core::mem::size_of::<u32>());
288    assert!(core::mem::size_of::<Entries>() == core::mem::size_of::<u32>());
289    assert!(core::mem::size_of::<Submit>() == core::mem::size_of::<u32>());
290    assert!(core::mem::size_of::<Schedule>() == 2 * core::mem::size_of::<u32>());
291};