dope_core/driver/schedule/ready/
mod.rs1use std::{marker, mem, num};
2
3pub(crate) use arena::Arena;
4use arena::{
5 cells::{Entry, Renewal, Resident, Slots, Table},
6 layout, payload, pool, topology,
7};
8pub use key::retained::Retained;
9use key::{
10 Detached, DispatchKey, FreeIndex, Index, ReservedKey, RootIndex, Staged, TaskIndex, TaskKey,
11 TopologyKey,
12};
13pub(crate) use key::{DynamicIndex, QueueIndex, Stored};
14use kind::Kind;
15use layout::Layout;
16use o3::{
17 base::{marker::ThreadBound, num::Generation},
18 mem::Lease,
19};
20use payload::{Link, Task};
21use pool::{Chain, Pool};
22use record::Record;
23pub use rounds::Rounds;
24use topology::Topology;
25
26use crate::{driver, driver::route, io::fd::identity};
27
28mod arena;
29mod record;
30mod rounds;
31
32pub(super) enum Lane {}
33
34#[derive(Clone, Copy, Debug, PartialEq, Eq)]
36pub struct Stale;
37
38#[derive(Clone, Copy, Eq, PartialEq)]
40#[repr(u8)]
41pub enum Readiness {
42 Idle,
43 Ready,
44}
45
46#[derive(Clone, Copy, Debug, PartialEq, Eq)]
48#[repr(transparent)]
49pub struct Capacity {
50 available: u32,
51}
52
53impl Capacity {
54 const fn new(free: u32) -> Self {
55 Self { available: free }
56 }
57
58 #[must_use]
59 pub const fn available(self) -> usize {
60 self.available as usize
61 }
62}
63
64#[derive(Clone, Copy)]
65pub(in crate::driver) struct Access<'a, 'd> {
66 borrow: marker::PhantomData<fn(&'a ()) -> &'a ()>,
67 driver: driver::Invariant<'d>,
68}
69
70impl<'d> Access<'_, 'd> {
71 pub(in crate::driver) fn new<'a>(driver: &'a driver::Reference<'d>) -> Access<'a, 'd>
72 where
73 'd: 'a,
74 {
75 Access {
76 borrow: marker::PhantomData,
77 driver: driver.brand,
78 }
79 }
80
81 fn bind(self, stored: Stored) -> Key<'d> {
82 Key {
83 stored,
84 arena: self.driver,
85 thread: ThreadBound::NEW,
86 }
87 }
88}
89
90enum TaskParent<'d> {
91 Root,
92 Task(Key<'d>),
93 Stale,
94}
95
96#[doc(hidden)]
97pub mod task;
98pub mod wake;
99
100#[derive(Clone, Copy)]
102#[repr(transparent)]
103pub struct Key<'d> {
104 stored: Stored,
105 arena: driver::Invariant<'d>,
106 thread: ThreadBound,
107}
108
109impl PartialEq for Key<'_> {
110 fn eq(&self, other: &Self) -> bool {
111 self.stored == other.stored
112 }
113}
114
115impl Eq for Key<'_> {}
116
117impl<'d> Key<'d> {
118 fn from_index(index: num::NonZero<u16>, epoch: Generation) -> Self {
119 Self {
120 stored: Stored::from_parts(index, epoch),
121 arena: driver::Invariant(marker::PhantomData),
122 thread: ThreadBound::NEW,
123 }
124 }
125
126 pub(in crate::driver) const fn raw(self) -> Stored {
127 self.stored
128 }
129}
130
131#[derive(Clone, Copy)]
132struct Address<'d> {
133 driver: driver::Reference<'d>,
134 key: Retained<'d>,
135}
136
137impl PartialEq for Address<'_> {
138 fn eq(&self, other: &Self) -> bool {
139 self.key == other.key
140 }
141}
142
143impl Eq for Address<'_> {}
144
145impl<'d> Address<'d> {
146 fn new(driver: driver::Reference<'d>, key: Key<'d>) -> Self {
147 Self {
148 driver,
149 key: Retained(key),
150 }
151 }
152
153 fn wake(self) {
154 self.driver.ready().activate(self.key.0);
155 }
156
157 fn belongs_to(self, driver: driver::Reference<'_>) -> bool {
158 self.driver.is_same(driver)
159 }
160
161 fn key(self) -> Key<'d> {
162 self.key.0
163 }
164
165 fn retarget(self, key: Key<'d>) -> Self {
166 Self::new(self.driver, key)
167 }
168}
169
170#[derive(Clone, Copy)]
172#[repr(transparent)]
173pub struct Target<'d> {
174 address: Address<'d>,
175}
176
177impl PartialEq for Target<'_> {
178 fn eq(&self, other: &Self) -> bool {
179 self.address == other.address
180 }
181}
182
183impl Eq for Target<'_> {}
184
185impl<'d> Target<'d> {
186 pub(crate) fn new(driver: driver::Reference<'d>, key: Key<'d>) -> Self {
187 Self {
188 address: Address::new(driver, key),
189 }
190 }
191
192 pub fn wake(self) {
193 self.address.wake();
194 }
195
196 #[doc(hidden)]
197 pub fn key(&self) -> Retained<'d> {
198 self.address.key
199 }
200
201 pub(in crate::driver) fn receive(self) -> (driver::Reference<'d>, Stored) {
202 (self.address.driver, self.address.key.raw())
203 }
204
205 fn address(self) -> Address<'d> {
206 self.address
207 }
208}
209
210#[derive(Clone, Copy)]
211pub struct Handle<'d> {
212 driver: driver::Reference<'d>,
213 id: identity::Identity<'d>,
214}
215
216impl<'d> Handle<'d> {
217 pub(in crate::driver) const fn new(
218 driver: driver::Reference<'d>,
219 id: identity::Identity<'d>,
220 ) -> Self {
221 Self { driver, id }
222 }
223
224 pub fn set_target<Tag: route::Tag>(self, target: route::Operation<'d, Tag>) {
225 self.driver
226 .descriptors()
227 .set_target(self.id, target.into_token());
228 }
229
230 pub fn activate(self) {
231 if self.driver.descriptors().target(self.id).is_some() {
232 self.driver.ready().arena().activate_fd(self.id);
233 }
234 }
235
236 pub fn key(self) -> Key<'d> {
237 let index = self.id.queue_index();
238 Key::from_index(index.0, self.id.generation())
239 }
240
241 pub fn target(self) -> Target<'d> {
242 Target::new(self.driver, self.key())
243 }
244}
245
246pub struct Slot<'d, Tag: route::Tag> {
249 owner: Lease<DispatchKey<'d>>,
250 target: marker::PhantomData<*mut Tag>,
251}
252
253impl<'d, Tag: route::Tag> Slot<'d, Tag> {
254 fn new(driver: driver::Reference<'d>, key: DispatchKey<'d>) -> Self {
255 Self {
256 owner: Lease::new(key, driver),
257 target: marker::PhantomData,
258 }
259 }
260
261 pub fn activate(&self) {
262 self.owner
263 .item()
264 .ready()
265 .arena()
266 .activate_slot(self.dispatch_key());
267 }
268
269 #[must_use]
271 pub fn take(&self) -> Readiness {
272 self.owner.item().ready().arena().take(self.dispatch_key())
273 }
274
275 pub fn target(&self) -> Target<'d> {
277 Target::new(*self.owner.item(), self.dispatch_key().key())
278 }
279
280 fn dispatch_key(&self) -> &DispatchKey<'d> {
281 self.owner.sink()
282 }
283}
284
285const _: () = {
286 assert!(mem::size_of::<Readiness>() == mem::size_of::<u8>());
287 assert!(mem::size_of::<usize>() >= mem::size_of::<u32>());
288 assert!(mem::size_of::<Access<'static, 'static>>() == 0);
289};
290const _: () = {
291 assert!(mem::size_of::<Key<'static>>() == mem::size_of::<u64>());
292 assert!(mem::size_of::<Option<Key<'static>>>() == mem::size_of::<Key<'static>>());
293 assert!(mem::size_of::<Option<Retained<'static>>>() == mem::size_of::<Retained<'static>>());
294 assert!(mem::size_of::<DispatchKey<'static>>() == mem::size_of::<Key<'static>>());
295 assert!(mem::align_of::<DispatchKey<'static>>() == mem::align_of::<Key<'static>>());
296 assert!(mem::size_of::<Slot<'static, route::KeyTag<0>>>() == 2 * mem::size_of::<usize>());
297};
298const _: () = assert!(mem::size_of::<Target<'static>>() == 2 * mem::size_of::<usize>());
299const _: () = {
300 assert!(mem::size_of::<Handle<'static>>() == 2 * mem::size_of::<usize>());
301};
302
303mod key;
304mod kind;
305mod state;
306
307#[derive(Clone, Copy)]
308#[repr(transparent)]
309pub struct Context<'d>(driver::Reference<'d>);
310
311impl<'d> Context<'d> {
312 pub(in crate::driver) const fn new(driver: driver::Reference<'d>) -> Self {
313 Self(driver)
314 }
315
316 pub(crate) fn arena(self) -> &'d Arena {
317 self.0.shared.context().schedule.owner.context()
318 }
319
320 pub(crate) fn handle(self, id: identity::Identity<'d>) -> Handle<'d> {
321 Handle::new(self.0, id)
322 }
323
324 pub fn make_slot<Tag: route::Tag>(
325 self,
326 target: route::Operation<'d, Tag>,
327 ) -> Result<Slot<'d, Tag>, Capacity> {
328 self.arena().make_slot(self.0, target)
329 }
330
331 pub fn activate(self, key: Key<'d>) {
334 self.arena().activate(Access::new(&self.0), key);
335 }
336
337 pub fn try_activate(self, key: Retained<'d>) -> Result<(), Stale> {
339 self.arena().try_retained(key)
340 }
341
342 pub fn has_ready(self) -> bool {
343 self.arena().has_ready()
344 }
345}
346
347const _: () = assert!(
348 std::mem::size_of::<Context<'static>>() == std::mem::size_of::<driver::Reference<'static>>()
349);