dope_core/driver/retained/accept/
mod.rs1use std::{cell, mem, net, 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::{
17 event::{batch::Flow, net::accept::Failure},
18 fd::domain::retire,
19 socket,
20 },
21};
22
23pub mod raw;
24
25#[derive(Debug)]
27pub enum Readiness {
28 Ready,
29 Pending,
30 Inflight,
31}
32
33impl From<driver::Reference<'_>> for Readiness {
34 fn from(driver: driver::Reference<'_>) -> Self {
36 let retired = driver.descriptors().retirement();
37 if retired.has_pending() {
38 Self::Pending
39 } else if retired.has_inflight() {
40 Self::Inflight
41 } else {
42 Self::Ready
43 }
44 }
45}
46
47impl Readiness {
48 pub fn progress<'a>(
49 self,
50 region: ®ion::Token<region::Identity<'a>>,
51 ) -> schedule::Progress<'a> {
52 match self {
53 Self::Ready | Self::Pending => schedule::Progress::Runnable,
54 Self::Inflight => schedule::Progress::waiting(region),
55 }
56 }
57}
58
59#[pin_project::pin_project(!Unpin)]
60pub struct Lane<'d, Tag>
61where
62 Tag: route::Tag<Class = kind::Accept>,
63{
64 state: arm::State<'d, Tag>,
65 addr: cell::UnsafeCell<Storage<Length>>,
66 closed: retire::Completed,
67}
68
69impl<'d, Tag> Lane<'d, Tag>
70where
71 Tag: route::Tag<Class = kind::Accept>,
72{
73 pub fn new(target: route::Target<'d, Tag>) -> Self {
74 Self {
75 state: arm::State::new(target),
76 addr: cell::UnsafeCell::new(Storage::<Length>::empty()),
77 closed: retire::Completed::EMPTY,
78 }
79 }
80}
81
82pub struct Slots<'d, Tag>
85where
86 Tag: route::Tag<Class = kind::Accept>,
87{
88 lanes: pin::Pin<Box<[Lane<'d, Tag>]>>,
89 active: usize,
90}
91
92impl<'d, Tag> Slots<'d, Tag>
93where
94 Tag: route::Tag<Class = kind::Accept>,
95{
96 pub fn new(lanes: Box<[Lane<'d, Tag>]>) -> Self {
97 Self {
98 lanes: Box::into_pin(lanes),
99 active: 0,
100 }
101 }
102
103 pub fn get_mut(&mut self, index: usize) -> Option<Entry<'_, 'd, Tag>> {
104 let lane = unsafe { self.lanes.as_mut().get_unchecked_mut() }.get_mut(index)?;
106 Some(Entry {
107 lane: unsafe { pin::Pin::new_unchecked(lane) },
108 active: &mut self.active,
109 })
110 }
111
112 fn iter_mut(
113 &mut self,
114 ) -> impl DoubleEndedIterator<Item = pin::Pin<&mut Lane<'d, Tag>>> + ExactSizeIterator + '_
115 {
116 unsafe { self.lanes.as_mut().get_unchecked_mut() }
119 .iter_mut()
120 .map(|lane| unsafe { pin::Pin::new_unchecked(lane) })
121 }
122
123 pub fn is_empty(&self) -> bool {
124 self.lanes.is_empty()
125 }
126
127 pub fn len(&self) -> usize {
128 self.lanes.len()
129 }
130
131 pub const fn active(&self) -> usize {
133 self.active
134 }
135
136 pub fn stop(&mut self, driver: &mut driver::Context<'_, 'd>) {
137 let mut active = 0;
138 for lane in self.iter_mut() {
139 let state = lane.project().state;
140 state.stop(driver);
141 active += usize::from(state.is_live());
142 }
143 self.active = active;
144 }
145
146 pub fn progress<'a>(
147 &self,
148 region: ®ion::Token<region::Identity<'a>>,
149 ) -> schedule::Progress<'a> {
150 self.lanes
151 .iter()
152 .fold(schedule::Progress::Quiescent, |progress, lane| {
153 progress.reduce(lane.state.progress(region))
154 })
155 }
156
157 pub fn finish(&mut self, proof: &mut finish::Finish<'_, 'd>) {
158 for lane in self.iter_mut() {
159 lane.project().state.finish(proof);
160 }
161 self.active = 0;
162 }
163}
164
165pub struct Entry<'a, 'd, Tag>
169where
170 Tag: route::Tag<Class = kind::Accept>,
171{
172 lane: pin::Pin<&'a mut Lane<'d, Tag>>,
173 active: &'a mut usize,
174}
175
176impl<'a, 'd, Tag> Entry<'a, 'd, Tag>
177where
178 Tag: route::Tag<Class = kind::Accept>,
179{
180 pub fn begin(mut self) -> Option<accept::raw::Arming<'a, 'd, Tag>> {
181 if !self.lane.as_mut().project().state.start() {
182 return None;
183 }
184 Some(accept::raw::Arming::new(self))
185 }
186
187 pub fn retire(mut self, token: route::Erased<'d, kind::Accept>) -> Retire<'a, 'd, Tag> {
191 let lane = self.lane.as_mut().project();
192 let retired = match lane.state.complete(token, Flow::Last) {
193 arm::Disposition::Discard => return Retire::Stale,
194 arm::Disposition::Deliver | arm::Disposition::Probe => {
195 Retired::Terminal(Terminal { lane: self.lane })
196 }
197 arm::Disposition::Retiring => Retired::Cancelled,
198 };
199 *self.active -= 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 let result = lane.state.apply(result);
213 if let arm::Submission::Armed = result {
214 *lane.closed = closed;
215 *self.active += 1;
217 }
218 result
219 }
220}
221
222#[must_use]
223pub enum Retire<'a, 'd, Tag>
224where
225 Tag: route::Tag<Class = kind::Accept>,
226{
227 Stale,
228 Done(Retired<'a, 'd, Tag>),
229}
230
231#[must_use]
232pub enum Retired<'a, 'd, Tag>
233where
234 Tag: route::Tag<Class = kind::Accept>,
235{
236 Terminal(Terminal<'a, 'd, Tag>),
237 Cancelled,
238}
239
240#[must_use]
241pub struct Terminal<'a, 'd, Tag>
242where
243 Tag: route::Tag<Class = kind::Accept>,
244{
245 lane: pin::Pin<&'a mut Lane<'d, Tag>>,
246}
247
248impl<'d, Tag> Terminal<'_, 'd, Tag>
249where
250 Tag: route::Tag<Class = kind::Accept>,
251{
252 pub fn can_defer(&self, failure: &Failure, driver: &mut driver::Context<'_, 'd>) -> bool {
254 failure.can_defer(driver)
255 || (matches!(failure, Failure::Syscall(_))
256 && failure.is_resource()
257 && self.lane.closed != driver.driver_ref().descriptors().retirement().completed())
258 }
259
260 pub fn into_addr(self) -> Result<net::SocketAddr, socket::Error> {
261 let storage = *self.lane.project().addr.get_mut();
262 storage.to_std().map_err(socket::Error::from)
263 }
264
265 pub fn discard(self) {
266 *self.lane.project().addr.get_mut() = Storage::<Length>::empty();
267 }
268}
269
270const _: () = {
271 type Tag = route::KeyTag<1, kind::Accept>;
272 const fn layout<'a, 'd: 'a>() {
273 assert!(
274 mem::size_of::<Lane<'d, Tag>>()
275 == mem::size_of::<(arm::State<'d, Tag>, Storage<Length>, retire::Completed)>()
276 );
277 assert!(
278 mem::align_of::<Lane<'d, Tag>>()
279 == mem::align_of::<(arm::State<'d, Tag>, Storage<Length>, retire::Completed)>()
280 );
281 assert!(
282 mem::size_of::<Slots<'d, Tag>>()
283 == mem::size_of::<(pin::Pin<Box<[Lane<'d, Tag>]>>, usize)>()
284 );
285 assert!(
286 mem::align_of::<Slots<'d, Tag>>() == mem::align_of::<pin::Pin<Box<[Lane<'d, Tag>]>>>()
287 );
288 assert!(mem::size_of::<Terminal<'a, 'd, Tag>>() == mem::size_of::<usize>());
289 assert!(mem::size_of::<Entry<'a, 'd, Tag>>() == 2 * mem::size_of::<usize>());
290 assert!(mem::size_of::<Option<Entry<'a, 'd, Tag>>>() == 2 * mem::size_of::<usize>());
291 assert!(mem::size_of::<accept::raw::Arming<'a, 'd, Tag>>() == 2 * mem::size_of::<usize>());
292 }
293 layout();
294};