1use core::{convert, mem, num};
2
3use o3::{
4 base::marker::ThreadBound,
5 depot,
6 depot::{
7 arena::slab::{
8 self, entries, external,
9 external::{errors, shared},
10 lookup,
11 },
12 capacity,
13 index::Initialized,
14 },
15};
16
17use crate::driver::{
18 route,
19 route::{indices, table},
20};
21
22#[derive(Clone, Copy)]
24#[repr(transparent)]
25pub struct Identity<'d, Tag: route::Tag>(Option<route::Target<'d, Tag>>);
26
27unsafe impl depot::raw::Compact for indices::SlotIndex {
30 const MAX: u32 = route::SLOT_MASK as u32;
31
32 fn into_raw(self) -> u32 {
33 self.raw()
34 }
35
36 unsafe fn from_raw(raw: u32) -> Self {
37 indices::SlotIndex::from_field(u64::from(raw))
38 }
39}
40
41unsafe impl depot::raw::Count<indices::SlotIndex> for table::Capacity {
43 fn count(self) -> capacity::Count {
44 self.count()
45 }
46}
47
48#[repr(transparent)]
50pub struct Cell<'a, T, Tag: route::Tag> {
51 inner: &'a shared::Storage<T, route::Epoch, Tag>,
52}
53
54impl<'a, T, Tag: route::Tag> Cell<'a, T, Tag> {
55 pub(in crate::driver::route) const fn new(
56 inner: &'a shared::Storage<T, route::Epoch, Tag>,
57 ) -> Self {
58 Self { inner }
59 }
60}
61
62type Allocation<'a, T, Tag> = depot::raw::Proof<
63 (&'a shared::Storage<T, route::Epoch, Tag>, u32),
64 Initialized<entries::Allocated>,
65>;
66
67type Vacancy<'a, T, Tag> = external::Vacant<
68 entries::Pending<
69 'a,
70 external::Stamped<T, route::Epoch>,
71 { u32::MAX },
72 entries::Interior<true>,
73 1,
74 >,
75 Tag,
76 true,
77 route::Epoch,
78>;
79
80pub struct Slot<'a, T, Tag: route::Tag>(Allocation<'a, T, Tag>);
82
83impl<'a, T, Tag: route::Tag> Slot<'a, T, Tag> {
84 pub fn vacancy(self) -> Result<Vacancy<'a, T, Tag>, slab::Vacancy> {
85 self.0.vacancy()
86 }
87
88 pub fn try_entry(
89 self,
90 ) -> Result<table::Current<'a, T, Tag>, lookup::Error<(), convert::Infallible>> {
91 Ok(table::Current::new(self.0.try_entry()?))
92 }
93
94 pub fn try_key(
95 self,
96 epoch: route::Epoch,
97 ) -> Result<table::Current<'a, T, Tag>, errors::Lookup<route::Epoch, Tag, ()>> {
98 Ok(table::Current::new(self.0.try_key(epoch)?))
99 }
100}
101
102unsafe impl<'a, T, Tag: route::Tag> depot::raw::Project<indices::SlotIndex, entries::Allocated>
104 for Cell<'a, T, Tag>
105{
106 type Output = Slot<'a, T, Tag>;
107
108 unsafe fn project(self, index: indices::SlotIndex) -> Self::Output {
109 let live = unsafe { depot::raw::Proof::new((self.inner, index.raw())) };
111 Slot(live.into())
112 }
113}
114
115impl<'d, Tag: route::Tag> Identity<'d, Tag> {
116 pub const VACANT: Self = Self(None);
117
118 pub const fn from_target(target: route::Target<'d, Tag>) -> Self {
119 Self(Some(target))
120 }
121
122 pub fn into_target(self) -> Option<route::Target<'d, Tag>> {
123 self.0
124 }
125
126 pub unsafe fn target(self) -> route::Target<'d, Tag> {
130 unsafe { mem::transmute(self.0) }
132 }
133}
134
135impl<Tag: route::Tag> PartialEq for Identity<'_, Tag> {
136 fn eq(&self, other: &Self) -> bool {
137 self.0 == other.0
138 }
139}
140
141impl<Tag: route::Tag> Eq for Identity<'_, Tag> {}
142
143#[derive(Clone, Copy)]
144#[repr(transparent)]
145pub(crate) struct Auxiliary(u32);
146
147impl Auxiliary {
148 pub(crate) const fn from_meta(meta: u64) -> Self {
149 Self(((meta & route::AUX_MASK) >> route::AUX_SHIFT) as u32)
150 }
151
152 pub(crate) const fn with_bits(self, mask: u8, value: u8) -> Self {
153 let mask = mask as u32;
154 Self((self.0 & !mask) | (value as u32 & mask))
155 }
156
157 pub(crate) const fn raw(self) -> u32 {
158 self.0
159 }
160}
161
162impl From<u8> for Auxiliary {
163 fn from(raw: u8) -> Self {
164 Self(u32::from(raw))
165 }
166}
167
168#[derive(Clone, Copy)]
169#[repr(C)]
170pub(crate) struct Packed {
171 identity: num::NonZero<u64>,
172 thread: ThreadBound,
173 meta: u64,
174}
175
176impl Packed {
177 pub(crate) const fn new(token: route::Token, aux: Auxiliary) -> Self {
178 let route::Token {
179 epoch,
180 thread,
181 meta,
182 } = token;
183 Self {
184 identity: epoch,
185 thread,
186 meta: (meta & !route::AUX_MASK) | ((aux.raw() as u64) << route::AUX_SHIFT),
187 }
188 }
189
190 pub(crate) const fn words(self) -> [u64; 2] {
191 [self.identity.get(), self.meta]
192 }
193
194 pub(crate) const fn from_words(
195 identity: num::NonZero<u64>,
196 meta: u64,
197 thread: ThreadBound,
198 ) -> Self {
199 Self {
200 identity,
201 thread,
202 meta,
203 }
204 }
205
206 pub(crate) const unsafe fn restore(words: [u64; 2], thread: ThreadBound) -> Self {
209 Self::from_words(
210 unsafe { num::NonZero::<u64>::new_unchecked(words[0]) },
211 words[1],
212 thread,
213 )
214 }
215
216 pub(crate) const fn target(self) -> route::Token {
217 route::Token {
218 epoch: self.identity,
219 thread: self.thread,
220 meta: self.meta & !route::AUX_MASK,
221 }
222 }
223}
224
225const _: () = {
226 assert!(
227 mem::size_of::<Identity<'static, route::KeyTag<1>>>()
228 == mem::size_of::<route::Target<'static, route::KeyTag<1>>>()
229 );
230 assert!(
231 mem::align_of::<Identity<'static, route::KeyTag<1>>>()
232 == mem::align_of::<route::Target<'static, route::KeyTag<1>>>()
233 );
234 assert!(
235 mem::size_of::<Identity<'static, route::KeyTag<1>>>() == mem::size_of::<route::Token>()
236 );
237 assert!(
238 mem::align_of::<Identity<'static, route::KeyTag<1>>>() == mem::align_of::<route::Token>()
239 );
240 assert!(mem::size_of::<Auxiliary>() == mem::size_of::<u32>());
241 assert!(mem::size_of::<Packed>() == 2 * mem::size_of::<u64>());
242 assert!(mem::align_of::<Packed>() == mem::align_of::<u64>());
243};