dope_core/driver/receive/
mod.rs1use std::{marker, task::Poll};
4
5pub use attempt::Attempt;
6use dope_sys::{
7 engine,
8 memory::buffer,
9 table::{permit, permit::Queue},
10};
11use o3::base::num::bounded;
12
13use crate::{
14 Backend, Engine, driver,
15 driver::{schedule::ready, settings},
16};
17
18pub(crate) mod access;
19mod attempt;
20pub mod credit;
21mod raw;
22pub(crate) mod tokens;
23
24#[derive(Clone, Copy, PartialEq, Eq, Debug)]
26#[repr(transparent)]
27pub struct Capacity(bounded::U64<0, { u64::MAX }>);
28
29#[derive(Clone, Copy, PartialEq, Eq, Debug)]
31#[repr(transparent)]
32pub struct Length(bounded::U64<0, { u64::MAX }>);
33
34impl From<bounded::U64<0, { u64::MAX }>> for Capacity {
35 fn from(value: bounded::U64<0, { u64::MAX }>) -> Self {
36 Self(value)
37 }
38}
39
40impl From<bounded::U64<0, { u64::MAX }>> for Length {
41 fn from(value: bounded::U64<0, { u64::MAX }>) -> Self {
42 Self(value)
43 }
44}
45
46#[derive(Clone, Copy, PartialEq, Eq, Debug)]
48#[repr(transparent)]
49pub struct Selection(<Backend as buffer::Selection<settings::Buffers>>::Error);
50
51impl Selection {
52 pub(crate) fn from_native<E>(value: E) -> Self
53 where
54 Backend: buffer::Selection<settings::Buffers, Error = E>,
55 {
56 Self(value)
57 }
58}
59
60#[repr(transparent)]
62pub(crate) struct Proof(ready::Stored);
63
64impl Proof {
65 pub(in crate::driver) const fn new(key: ready::Stored) -> Self {
66 Self(key)
67 }
68
69 pub(in crate::driver) const fn key(&self) -> ready::Stored {
70 self.0
71 }
72
73 pub(crate) fn release(
74 permit: &<crate::Permits as Queue>::Capability,
75 store: &crate::Permits,
76 driver: driver::Reference<'_>,
77 ) {
78 while let Some((index, key)) = store.grant_one(permit) {
79 let stale = match driver.ready().arena().try_receive(Self::new(key)) {
80 Ok(()) => continue,
81 Err(stale) => stale.key(),
82 };
83 let _ = store.take(permit, index, stale);
86 }
87 }
88}
89
90#[repr(transparent)]
93pub struct Exhausted<'d> {
94 driver: marker::PhantomData<driver::Reference<'d>>,
95}
96
97#[must_use = "a receive registration must be polled, cancelled, or retired"]
99#[repr(transparent)]
100pub struct Registration<'d> {
101 target: ready::Target<'d>,
102 permit: <crate::Permits as Queue>::Capability,
103}
104
105#[derive(Clone, Copy, Debug, PartialEq, Eq)]
107pub struct Stale;
108
109#[derive(Clone, Copy, Debug, PartialEq, Eq)]
111pub struct Absent;
112
113impl<'d> Exhausted<'d> {
114 pub(crate) const fn from_driver(_driver: driver::Reference<'d>) -> Self {
115 Self {
116 driver: marker::PhantomData,
117 }
118 }
119
120 pub(in crate::driver) fn retire(self) -> dope_sys::Errno {
122 dope_sys::Errno::NO_BUFFER_SPACE
123 }
124}
125
126impl<'d, P> Registration<'d>
127where
128 crate::Permits: Queue<Capability = P>,
129{
130 pub fn try_acquire(target: ready::Target<'d>) -> Result<Self, Absent> {
132 let permit = crate::Permits::try_acquire().map_err(|permit::Absent| Absent)?;
133 Ok(Self { target, permit })
134 }
135
136 pub fn clear(target: ready::Target<'d>) {
138 let reg = match Self::try_acquire(target) {
139 Ok(reg) => reg,
140 Err(Absent) => return,
141 };
142 reg.retire();
143 }
144
145 pub fn exhausted(
147 self,
148 proof: Exhausted<'d>,
149 ) -> Result<Poll<Attempt<'d>>, (Exhausted<'d>, Stale)> {
150 let Self { target, permit } = self;
151 let (driver, key) = target.receive();
152 if !Self::is_live(driver, key) {
153 return Err((proof, Stale));
154 }
155 let store = driver.receive().exhausted();
156 match store.try_arm(&permit, Index::from_key(key), key) {
157 Ok(()) => Ok(Poll::Ready(Attempt::new(permit, driver))),
158 Err(key) => Self::take(permit, store, driver, key).map_err(|stale| (proof, stale)),
159 }
160 }
161
162 pub fn resume(self) -> Result<Poll<Attempt<'d>>, Stale> {
165 let Self { target, permit } = self;
166 let (driver, key) = target.receive();
167 let store = driver.receive().exhausted();
168 if !Self::is_live(driver, key) {
169 return match Self::cancel_inner(&permit, store, key) {
170 Ok(()) | Err(Stale) => Err(Stale),
171 };
172 }
173 Self::take(permit, store, driver, key)
174 }
175
176 pub fn cancel(self) -> Result<(), Stale> {
178 let Self { target, permit } = self;
179 let (driver, key) = target.receive();
180 Self::cancel_inner(&permit, driver.receive().exhausted(), key)
181 }
182
183 pub fn retire(self) {
186 match self.cancel() {
187 Ok(()) | Err(Stale) => {}
188 }
189 }
190
191 fn is_live(driver: driver::Reference<'_>, key: ready::Stored) -> bool {
192 driver.ready().arena().is_dispatch(Proof::new(key))
193 }
194
195 fn take(
196 permit: P,
197 store: &'d crate::Permits,
198 driver: driver::Reference<'d>,
199 key: ready::Stored,
200 ) -> Result<Poll<Attempt<'d>>, Stale> {
201 match store.take(&permit, Index::from_key(key), key) {
202 permit::State::Waiting => Ok(Poll::Pending),
203 permit::State::Granted(_) => Ok(Poll::Ready(Attempt::new(permit, driver))),
204 permit::State::Gone | permit::State::Stale => Err(Stale),
205 }
206 }
207
208 fn cancel_inner(permit: &P, store: &crate::Permits, key: ready::Stored) -> Result<(), Stale> {
209 match store.cancel(permit, Index::from_key(key), key) {
210 permit::State::Gone | permit::State::Waiting | permit::State::Granted(_) => Ok(()),
211 permit::State::Stale => Err(Stale),
212 }
213 }
214}
215
216const _: () = {
217 assert!(
218 std::mem::size_of::<Selection>()
219 == std::mem::size_of::<<Engine as engine::Buffer>::Selection>()
220 );
221 assert!(
222 std::mem::align_of::<Selection>()
223 == std::mem::align_of::<<Engine as engine::Buffer>::Selection>()
224 );
225 assert!(std::mem::size_of::<Proof>() == std::mem::size_of::<ready::Stored>());
226 assert!(std::mem::align_of::<Proof>() == std::mem::align_of::<ready::Stored>());
227 assert!(std::mem::size_of::<Exhausted<'static>>() == 0);
228 assert!(std::mem::align_of::<Exhausted<'static>>() == 1);
229 assert!(std::mem::size_of::<<crate::Permits as Queue>::Capability>() == 0);
230 assert!(std::mem::size_of::<permit::Absent>() == 0);
231 assert!(std::mem::size_of::<Absent>() == 0);
232 assert!(std::mem::size_of::<Registration<'static>>() == 2 * std::mem::size_of::<usize>());
233 assert!(
234 std::mem::size_of::<Registration<'static>>()
235 == std::mem::size_of::<ready::Target<'static>>()
236 );
237 assert!(
238 std::mem::align_of::<Registration<'static>>()
239 == std::mem::align_of::<ready::Target<'static>>()
240 );
241};
242
243#[derive(Clone, Copy)]
245#[repr(transparent)]
246pub struct Index(ready::DynamicIndex);
247
248impl Index {
249 const fn from_key(key: ready::Stored) -> Self {
250 Self(key.dense())
251 }
252}