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().stored().try_receive(Self::new(key)) {
80 Ok(()) => continue,
81 Err(stale) => stale.key(),
82 };
83 match store.take(permit, index, stale) {
84 permit::State::Granted(returned) => {
85 if returned != stale {
86 return;
87 }
88 }
89 permit::State::Gone | permit::State::Waiting | permit::State::Stale => return,
90 }
91 }
92 }
93}
94
95#[repr(transparent)]
98pub struct Exhausted<'d> {
99 driver: marker::PhantomData<driver::Reference<'d>>,
100}
101
102#[must_use = "a receive registration must be polled, cancelled, or retired"]
104#[repr(transparent)]
105pub struct Registration<'d> {
106 target: ready::Target<'d>,
107 permit: <crate::Permits as Queue>::Capability,
108}
109
110#[derive(Clone, Copy, Debug, PartialEq, Eq)]
112pub struct Stale;
113
114#[derive(Clone, Copy, Debug, PartialEq, Eq)]
116pub struct Absent;
117
118impl<'d> Exhausted<'d> {
119 pub(crate) const fn from_driver(_driver: driver::Reference<'d>) -> Self {
120 Self {
121 driver: marker::PhantomData,
122 }
123 }
124
125 pub(in crate::driver) fn retire(self) -> dope_sys::Errno {
127 dope_sys::Errno::NO_BUFFER_SPACE
128 }
129}
130
131impl<'d, P> Registration<'d>
132where
133 crate::Permits: Queue<Capability = P>,
134{
135 pub fn try_acquire(target: ready::Target<'d>) -> Result<Self, Absent> {
137 let permit = crate::Permits::try_acquire().map_err(|permit::Absent| Absent)?;
138 Ok(Self { target, permit })
139 }
140
141 pub fn clear(target: ready::Target<'d>) {
143 let reg = match Self::try_acquire(target) {
144 Ok(reg) => reg,
145 Err(Absent) => return,
146 };
147 reg.retire();
148 }
149
150 pub fn exhausted(
152 self,
153 proof: Exhausted<'d>,
154 ) -> Result<Poll<Attempt<'d>>, (Exhausted<'d>, Stale)> {
155 let Self { target, permit } = self;
156 let (driver, key) = target.receive();
157 if !Self::is_live(driver, key) {
158 return Err((proof, Stale));
159 }
160 let store = driver.receive().exhausted();
161 match store.try_arm(&permit, Index::from_key(key), key) {
162 Ok(()) => Ok(Poll::Ready(Attempt::new(permit, driver))),
163 Err(key) => Self::take(permit, store, driver, key).map_err(|stale| (proof, stale)),
164 }
165 }
166
167 pub fn resume(self) -> Result<Poll<Attempt<'d>>, Stale> {
170 let Self { target, permit } = self;
171 let (driver, key) = target.receive();
172 let store = driver.receive().exhausted();
173 if !Self::is_live(driver, key) {
174 return match Self::cancel_inner(&permit, store, key) {
175 Ok(()) | Err(Stale) => Err(Stale),
176 };
177 }
178 Self::take(permit, store, driver, key)
179 }
180
181 pub fn cancel(self) -> Result<(), Stale> {
183 let Self { target, permit } = self;
184 let (driver, key) = target.receive();
185 Self::cancel_inner(&permit, driver.receive().exhausted(), key)
186 }
187
188 pub fn retire(self) {
191 match self.cancel() {
192 Ok(()) | Err(Stale) => {}
193 }
194 }
195
196 fn is_live(driver: driver::Reference<'_>, key: ready::Stored) -> bool {
197 driver.ready().arena().stored().is_dispatch(Proof::new(key))
198 }
199
200 fn take(
201 permit: P,
202 store: &'d crate::Permits,
203 driver: driver::Reference<'d>,
204 key: ready::Stored,
205 ) -> Result<Poll<Attempt<'d>>, Stale> {
206 match store.take(&permit, Index::from_key(key), key) {
207 permit::State::Waiting => Ok(Poll::Pending),
208 permit::State::Granted(_) => Ok(Poll::Ready(Attempt::new(permit, driver))),
209 permit::State::Gone | permit::State::Stale => Err(Stale),
210 }
211 }
212
213 fn cancel_inner(permit: &P, store: &crate::Permits, key: ready::Stored) -> Result<(), Stale> {
214 match store.cancel(permit, Index::from_key(key), key) {
215 permit::State::Gone | permit::State::Waiting | permit::State::Granted(_) => Ok(()),
216 permit::State::Stale => Err(Stale),
217 }
218 }
219}
220
221const _: () = {
222 assert!(
223 std::mem::size_of::<Selection>()
224 == std::mem::size_of::<<Engine as engine::Buffer>::Selection>()
225 );
226 assert!(
227 std::mem::align_of::<Selection>()
228 == std::mem::align_of::<<Engine as engine::Buffer>::Selection>()
229 );
230 assert!(std::mem::size_of::<Proof>() == std::mem::size_of::<ready::Stored>());
231 assert!(std::mem::align_of::<Proof>() == std::mem::align_of::<ready::Stored>());
232 assert!(std::mem::size_of::<Exhausted<'static>>() == 0);
233 assert!(std::mem::align_of::<Exhausted<'static>>() == 1);
234 assert!(std::mem::size_of::<<crate::Permits as Queue>::Capability>() == 0);
235 assert!(std::mem::size_of::<permit::Absent>() == 0);
236 assert!(std::mem::size_of::<Absent>() == 0);
237 assert!(std::mem::size_of::<Registration<'static>>() == 2 * std::mem::size_of::<usize>());
238 assert!(
239 std::mem::size_of::<Registration<'static>>()
240 == std::mem::size_of::<ready::Target<'static>>()
241 );
242 assert!(
243 std::mem::align_of::<Registration<'static>>()
244 == std::mem::align_of::<ready::Target<'static>>()
245 );
246};
247
248#[derive(Clone, Copy)]
250#[repr(transparent)]
251pub struct Index(ready::DynamicIndex);
252
253impl Index {
254 const fn from_key(key: ready::Stored) -> Self {
255 Self(key.dense())
256 }
257}