Skip to main content

dope_core/driver/retained/accept/
mod.rs

1use std::{cell, mem, net, num::NonZero, pin};
2
3use dope_sys::io::socket::addr::{Length, Storage};
4use o3::base::cell::region;
5
6use crate::{
7    driver,
8    driver::{
9        life::finish,
10        result,
11        retained::{accept, arm, flight},
12        route,
13        route::kind,
14        schedule,
15    },
16    io::{event::net::accept::Failure, fd::domain::retire, socket},
17};
18
19pub mod raw;
20
21/// Current descriptor-retirement barrier for admitting a new accept.
22#[derive(Debug)]
23pub enum Readiness {
24    Ready,
25    Pending,
26    Inflight,
27}
28
29impl From<driver::Reference<'_>> for Readiness {
30    /// Query again after driver mutations; this snapshot is not an admission permit.
31    fn from(driver: driver::Reference<'_>) -> Self {
32        let retired = driver.descriptors().retirement();
33        if retired.has_pending() {
34            Self::Pending
35        } else if retired.has_inflight() {
36            Self::Inflight
37        } else {
38            Self::Ready
39        }
40    }
41}
42
43impl Readiness {
44    pub fn progress<'a>(
45        self,
46        region: &region::Token<region::Identity<'a>>,
47    ) -> schedule::Progress<'a> {
48        match self {
49            Self::Ready | Self::Pending => schedule::Progress::Runnable,
50            Self::Inflight => schedule::Progress::waiting(region),
51        }
52    }
53}
54
55#[pin_project::pin_project(!Unpin)]
56pub struct Lane<'d, Tag>
57where
58    Tag: route::Tag<Class = kind::Accept>,
59{
60    state: arm::Base<'d, Tag>,
61    addr: cell::UnsafeCell<Storage<Length>>,
62    closed: retire::Completed,
63}
64
65impl<'d, Tag> Lane<'d, Tag>
66where
67    Tag: route::Tag<Class = kind::Accept>,
68{
69    pub fn new(target: route::Target<'d, Tag>) -> Self {
70        Self {
71            state: arm::Base::new(target),
72            addr: cell::UnsafeCell::new(Storage::<Length>::empty()),
73            closed: retire::Completed::EMPTY,
74        }
75    }
76}
77
78/// Pinned accept lanes and their exact in-flight count share one owner.
79///
80pub struct Slots<'d, Tag>
81where
82    Tag: route::Tag<Class = kind::Accept>,
83{
84    lanes: pin::Pin<Box<[Lane<'d, Tag>]>>,
85    active: Option<NonZero<usize>>,
86}
87
88impl<'d, Tag> Slots<'d, Tag>
89where
90    Tag: route::Tag<Class = kind::Accept>,
91{
92    pub fn new(lanes: Box<[Lane<'d, Tag>]>) -> Self {
93        Self {
94            lanes: Box::into_pin(lanes),
95            active: None,
96        }
97    }
98
99    pub fn get_mut(&mut self, index: usize) -> Option<Entry<'_, 'd, Tag>> {
100        // SAFETY: the selected lane remains pinned in this owned allocation.
101        let lane = unsafe { self.lanes.as_mut().get_unchecked_mut() }.get_mut(index)?;
102        Some(Entry {
103            lane: unsafe { pin::Pin::new_unchecked(lane) },
104            active: &mut self.active,
105        })
106    }
107
108    fn iter_mut(
109        &mut self,
110    ) -> impl DoubleEndedIterator<Item = pin::Pin<&mut Lane<'d, Tag>>> + ExactSizeIterator + '_
111    {
112        // SAFETY: the boxed slice keeps every lane at a stable address, and
113        // the iterator exposes each exclusive borrow only as pinned.
114        unsafe { self.lanes.as_mut().get_unchecked_mut() }
115            .iter_mut()
116            .map(|lane| unsafe { pin::Pin::new_unchecked(lane) })
117    }
118
119    pub fn is_empty(&self) -> bool {
120        self.lanes.is_empty()
121    }
122
123    pub fn len(&self) -> usize {
124        self.lanes.len()
125    }
126
127    /// Returns the number of submitted accepts awaiting terminal retirement.
128    pub const fn active(&self) -> usize {
129        match self.active {
130            Some(active) => active.get(),
131            None => 0,
132        }
133    }
134
135    pub fn stop(&mut self, driver: &mut driver::Context<'_, 'd>) {
136        let mut active = 0;
137        for lane in self.iter_mut() {
138            let state = lane.project().state;
139            state.stop(driver);
140            active += usize::from(state.is_live());
141        }
142        self.active = NonZero::new(active);
143    }
144
145    pub fn progress<'a>(
146        &self,
147        region: &region::Token<region::Identity<'a>>,
148    ) -> schedule::Progress<'a> {
149        self.lanes
150            .iter()
151            .fold(schedule::Progress::Quiescent, |progress, lane| {
152                progress.reduce(lane.state.progress(region))
153            })
154    }
155
156    pub fn finish(&mut self, proof: &mut finish::Finish<'_, 'd>) {
157        for lane in self.iter_mut() {
158            lane.project().state.finish(proof);
159        }
160        self.active = None;
161    }
162}
163
164/// An exclusive lane selection retains its owning count through the transition.
165///
166///
167pub struct Entry<'a, 'd, Tag>
168where
169    Tag: route::Tag<Class = kind::Accept>,
170{
171    lane: pin::Pin<&'a mut Lane<'d, Tag>>,
172    active: &'a mut Option<NonZero<usize>>,
173}
174
175impl<'a, 'd, Tag> Entry<'a, 'd, Tag>
176where
177    Tag: route::Tag<Class = kind::Accept>,
178{
179    pub fn begin(mut self) -> Option<accept::raw::Arming<'a, 'd, Tag>> {
180        let lane = self.lane.as_mut().project();
181        match lane.state.begin() {
182            arm::Start::Ready => Some(accept::raw::Arming::new(self)),
183            arm::Start::Blocked => None,
184        }
185    }
186
187    /// Retires an operation while borrowing its active owner's nonzero count.
188    /// The matching lane must have reached native terminal completion.
189    /// Empty owners and pending flights cannot grant terminal access.
190    pub fn retire(mut self, token: route::Erased<'d, kind::Accept>) -> Retire<'a, 'd, Tag> {
191        let Some(active) = *self.active else {
192            return Retire::Stale;
193        };
194        let lane = self.lane.as_mut().project();
195        let retired = match lane.state.retire(token) {
196            arm::End::Stale => return Retire::Stale,
197            arm::End::Terminal => Retired::Terminal(Terminal { lane: self.lane }),
198            arm::End::Cancelled => Retired::Cancelled,
199        };
200        *self.active = NonZero::new(active.get() - 1);
201        Retire::Done(retired)
202    }
203
204    /// Commits a previously idle lane and its owning count together.
205    /// The count cannot exceed the allocated lane slice's length.
206    fn apply(
207        &mut self,
208        result: Result<flight::Flight<'d, kind::Accept>, result::SubmitError>,
209        closed: retire::Completed,
210    ) -> arm::Submission {
211        let lane = self.lane.as_mut().project();
212        match lane.state.apply(result) {
213            arm::Submission::Armed => {
214                *lane.closed = closed;
215                let prior = self.active.map_or(0, NonZero::get);
216                // SAFETY: `active` counts distinct lanes of this one owned slice,
217                // whose length the driver admits against its accept capacity in the
218                // `u16`-bounded ready arena. So `prior + 1 <= u16::MAX + 1` is a
219                // nonzero `usize` that cannot overflow off the lane domain.
220                *self.active = Some(unsafe { NonZero::new_unchecked(prior + 1) });
221                arm::Submission::Armed
222            }
223            arm::Submission::Deferred => arm::Submission::Deferred,
224            arm::Submission::Failed(error) => arm::Submission::Failed(error),
225        }
226    }
227}
228
229#[must_use]
230pub enum Retire<'a, 'd, Tag>
231where
232    Tag: route::Tag<Class = kind::Accept>,
233{
234    Stale,
235    Done(Retired<'a, 'd, Tag>),
236}
237
238#[must_use]
239pub enum Retired<'a, 'd, Tag>
240where
241    Tag: route::Tag<Class = kind::Accept>,
242{
243    Terminal(Terminal<'a, 'd, Tag>),
244    Cancelled,
245}
246
247#[must_use]
248pub struct Terminal<'a, 'd, Tag>
249where
250    Tag: route::Tag<Class = kind::Accept>,
251{
252    lane: pin::Pin<&'a mut Lane<'d, Tag>>,
253}
254
255impl<'d, Tag> Terminal<'_, 'd, Tag>
256where
257    Tag: route::Tag<Class = kind::Accept>,
258{
259    /// Preserves completed native capacity returns even when their CQE precedes this error.
260    pub fn can_defer(&self, failure: &Failure, driver: &mut driver::Context<'_, 'd>) -> bool {
261        failure.can_defer(driver)
262            || (matches!(failure, Failure::Syscall(_))
263                && failure.is_resource()
264                && self.lane.closed != driver.driver_ref().descriptors().retirement().completed())
265    }
266
267    pub fn into_addr(self) -> Result<net::SocketAddr, socket::Error> {
268        let storage = *self.lane.project().addr.get_mut();
269        storage.to_std().map_err(socket::Error::from)
270    }
271
272    pub fn discard(self) {
273        *self.lane.project().addr.get_mut() = Storage::<Length>::empty();
274    }
275}
276
277const _: () = {
278    type Tag = route::KeyTag<1, kind::Accept>;
279    const fn layout<'a, 'd: 'a>() {
280        assert!(
281            mem::size_of::<Lane<'d, Tag>>()
282                == mem::size_of::<(arm::Base<'d, Tag>, Storage<Length>, retire::Completed)>()
283        );
284        assert!(
285            mem::align_of::<Lane<'d, Tag>>()
286                == mem::align_of::<(arm::Base<'d, Tag>, Storage<Length>, retire::Completed)>()
287        );
288        assert!(
289            mem::size_of::<Slots<'d, Tag>>()
290                == mem::size_of::<(pin::Pin<Box<[Lane<'d, Tag>]>>, usize)>()
291        );
292        assert!(
293            mem::align_of::<Slots<'d, Tag>>() == mem::align_of::<pin::Pin<Box<[Lane<'d, Tag>]>>>()
294        );
295        assert!(mem::size_of::<Terminal<'a, 'd, Tag>>() == mem::size_of::<usize>());
296        assert!(mem::size_of::<Entry<'a, 'd, Tag>>() == 2 * mem::size_of::<usize>());
297        assert!(mem::size_of::<Option<Entry<'a, 'd, Tag>>>() == 2 * mem::size_of::<usize>());
298        assert!(mem::size_of::<accept::raw::Arming<'a, 'd, Tag>>() == 2 * mem::size_of::<usize>());
299    }
300    layout();
301};