dope_core/driver/schedule/
sequence.rs1use std::{cell, mem, num};
2
3use o3::base::marker::ThreadBound;
4
5use crate::driver;
6
7const LOCAL: u64 = u32::MAX as u64;
8const BLOCK: u64 = 1_u64 << u32::BITS;
9
10pub(in crate::driver) struct Owner(cell::Cell<Option<num::NonZero<u64>>>);
11
12impl Owner {
13 pub(in crate::driver) const fn new() -> Self {
14 Self(cell::Cell::new(Some(num::NonZero::<u64>::MIN)))
15 }
16
17 fn claim(&self) -> Option<num::NonZero<u64>> {
18 let first = self.0.get()?;
19 let skip = 1_u32.wrapping_sub(first.get() as u32);
20 let first = first.checked_add(u64::from(skip))?;
21 self.0.set(first.checked_add(BLOCK));
22 Some(first)
23 }
24
25 pub(in crate::driver) fn next(&self) -> Option<num::NonZero<u64>> {
26 let next = self.0.get()?;
27 self.0.set(next.checked_add(1));
28 Some(next)
29 }
30}
31
32#[derive(Clone, Copy, Debug, Eq, PartialEq)]
33pub struct Exhausted;
34
35#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
40#[repr(transparent)]
41pub struct Id<'d> {
42 raw: num::NonZero<u64>,
43 driver: driver::Invariant<'d>,
44 thread: ThreadBound,
45}
46
47impl<'d> Id<'d> {
48 pub(in crate::driver) fn new(driver: driver::Reference<'d>, raw: num::NonZero<u64>) -> Self {
49 Self {
50 raw,
51 driver: driver.brand,
52 thread: ThreadBound::NEW,
53 }
54 }
55}
56
57pub struct Block<'d> {
58 driver: driver::Reference<'d>,
59 next: cell::Cell<Option<num::NonZero<u64>>>,
60}
61
62impl<'d> Block<'d> {
63 pub(in crate::driver) fn new(driver: driver::Reference<'d>) -> Self {
64 let next = driver.shared.context().sequence.claim();
65 Self {
66 driver,
67 next: cell::Cell::new(next),
68 }
69 }
70
71 pub fn try_next(&self) -> Result<Id<'d>, Exhausted> {
72 let raw = match self.next.get() {
73 Some(raw) => raw,
74 None => self
75 .driver
76 .shared
77 .context()
78 .sequence
79 .claim()
80 .ok_or(Exhausted)?,
81 };
82 let next = raw.checked_add(1).filter(|next| next.get() & LOCAL != 0);
83 self.next.set(next);
84 Ok(Id::new(self.driver, raw))
85 }
86}
87
88const _: () = {
89 assert!(mem::size_of::<Block<'static>>() == 2 * mem::size_of::<usize>());
90 assert!(mem::size_of::<Id<'static>>() == mem::size_of::<num::NonZero<u64>>());
91 assert!(mem::size_of::<Result<Id<'static>, Exhausted>>() == mem::size_of::<usize>());
92};