dope_core/driver/retained/accept/
mod.rs1use 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#[derive(Debug)]
23pub enum Readiness {
24 Ready,
25 Pending,
26 Inflight,
27}
28
29impl From<driver::Reference<'_>> for Readiness {
30 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: ®ion::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
78pub 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 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 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 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: ®ion::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
164pub 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 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 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 *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 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};