1use crate::{
2 entry::{MemoryLocationBorrowInfo, RcStorageEntry, StorageEntry},
3 error,
4 references::{GenerationalRef, GenerationalRefMut},
5 AnyStorage, BorrowError, BorrowMutError, BorrowMutResult, BorrowResult, GenerationalLocation,
6 GenerationalPointer, Storage, ValueDroppedError,
7};
8use std::{
9 any::Any,
10 cell::{Ref, RefCell, RefMut},
11 fmt::Debug,
12 num::NonZeroU64,
13};
14
15type RefCellStorageEntryRef = Ref<'static, StorageEntry<RefCellStorageEntryData>>;
16type RefCellStorageEntryMut = RefMut<'static, StorageEntry<RefCellStorageEntryData>>;
17type AnyRef = Ref<'static, Box<dyn Any>>;
18type AnyRefMut = RefMut<'static, Box<dyn Any>>;
19
20thread_local! {
21 static UNSYNC_RUNTIME: RefCell<Vec<&'static UnsyncStorage>> = const { RefCell::new(Vec::new()) };
22}
23
24#[derive(Default)]
25pub(crate) enum RefCellStorageEntryData {
26 Reference(GenerationalPointer<UnsyncStorage>),
27 Rc(RcStorageEntry<Box<dyn Any>>),
28 Data(Box<dyn Any>),
29 #[default]
30 Empty,
31}
32
33impl Debug for RefCellStorageEntryData {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 match self {
36 Self::Reference(pointer) => write!(f, "Reference({:?})", pointer.location),
37 Self::Rc(_) => write!(f, "Rc"),
38 Self::Data(_) => write!(f, "Data"),
39 Self::Empty => write!(f, "Empty"),
40 }
41 }
42}
43
44#[derive(Default)]
46pub struct UnsyncStorage {
47 borrow_info: MemoryLocationBorrowInfo,
48 data: RefCell<StorageEntry<RefCellStorageEntryData>>,
49}
50
51impl UnsyncStorage {
52 pub(crate) fn read(
53 pointer: GenerationalPointer<Self>,
54 ) -> BorrowResult<(AnyRef, GenerationalPointer<Self>)> {
55 Self::get_split_ref(pointer).map(|(resolved, guard)| {
56 (
57 Ref::map(guard, |data| match &data.data {
58 RefCellStorageEntryData::Data(data) => data,
59 RefCellStorageEntryData::Rc(data) => &data.data,
60 _ => unreachable!(),
61 }),
62 resolved,
63 )
64 })
65 }
66
67 pub(crate) fn get_split_ref(
68 mut pointer: GenerationalPointer<Self>,
69 ) -> BorrowResult<(GenerationalPointer<Self>, RefCellStorageEntryRef)> {
70 loop {
71 let borrow = pointer
72 .storage
73 .data
74 .try_borrow()
75 .map_err(|_| pointer.storage.borrow_info.borrow_error())?;
76 if !borrow.valid(&pointer.location) {
77 return Err(BorrowError::Dropped(ValueDroppedError::new_for_location(
78 pointer.location,
79 )));
80 }
81 match &borrow.data {
82 RefCellStorageEntryData::Reference(data) => {
84 pointer = *data;
85 }
86 RefCellStorageEntryData::Rc(_) | RefCellStorageEntryData::Data(_) => {
88 return Ok((pointer, borrow));
89 }
90 RefCellStorageEntryData::Empty => {
91 return Err(BorrowError::Dropped(ValueDroppedError::new_for_location(
92 pointer.location,
93 )));
94 }
95 }
96 }
97 }
98
99 pub(crate) fn write(
100 pointer: GenerationalPointer<Self>,
101 ) -> BorrowMutResult<(AnyRefMut, GenerationalPointer<Self>)> {
102 Self::get_split_mut(pointer).map(|(resolved, guard)| {
103 (
104 RefMut::map(guard, |data| match &mut data.data {
105 RefCellStorageEntryData::Data(data) => data,
106 RefCellStorageEntryData::Rc(data) => &mut data.data,
107 _ => unreachable!(),
108 }),
109 resolved,
110 )
111 })
112 }
113
114 pub(crate) fn get_split_mut(
115 mut pointer: GenerationalPointer<Self>,
116 ) -> BorrowMutResult<(GenerationalPointer<Self>, RefCellStorageEntryMut)> {
117 loop {
118 let borrow = pointer
119 .storage
120 .data
121 .try_borrow_mut()
122 .map_err(|_| pointer.storage.borrow_info.borrow_mut_error())?;
123 if !borrow.valid(&pointer.location) {
124 return Err(BorrowMutError::Dropped(
125 ValueDroppedError::new_for_location(pointer.location),
126 ));
127 }
128 match &borrow.data {
129 RefCellStorageEntryData::Reference(data) => {
131 pointer = *data;
132 }
133 RefCellStorageEntryData::Data(_) | RefCellStorageEntryData::Rc(_) => {
135 return Ok((pointer, borrow));
136 }
137 RefCellStorageEntryData::Empty => {
138 return Err(BorrowMutError::Dropped(
139 ValueDroppedError::new_for_location(pointer.location),
140 ));
141 }
142 }
143 }
144 }
145
146 fn create_new(
147 value: RefCellStorageEntryData,
148 #[allow(unused)] caller: &'static std::panic::Location<'static>,
149 ) -> GenerationalPointer<Self> {
150 UNSYNC_RUNTIME.with(|runtime| match runtime.borrow_mut().pop() {
151 Some(storage) => {
152 let mut write = storage.data.borrow_mut();
153 let location = GenerationalLocation {
154 generation: write.generation(),
155 #[cfg(any(debug_assertions, feature = "debug_borrows"))]
156 created_at: caller,
157 };
158 write.data = value;
159 GenerationalPointer { storage, location }
160 }
161 None => {
162 let storage: &'static Self = &*Box::leak(Box::new(Self {
163 borrow_info: Default::default(),
164 data: RefCell::new(StorageEntry::new(value)),
165 }));
166
167 let location = GenerationalLocation {
168 generation: NonZeroU64::MIN,
169 #[cfg(any(debug_assertions, feature = "debug_borrows"))]
170 created_at: caller,
171 };
172
173 GenerationalPointer { storage, location }
174 }
175 })
176 }
177}
178
179impl AnyStorage for UnsyncStorage {
180 type Ref<'a, R: ?Sized + 'a> = GenerationalRef<Ref<'a, R>>;
181 type Mut<'a, W: ?Sized + 'a> = GenerationalRefMut<RefMut<'a, W>>;
182
183 fn downcast_lifetime_ref<'a: 'b, 'b, T: ?Sized + 'a>(
184 ref_: Self::Ref<'a, T>,
185 ) -> Self::Ref<'b, T> {
186 ref_
187 }
188
189 fn downcast_lifetime_mut<'a: 'b, 'b, T: ?Sized + 'a>(
190 mut_: Self::Mut<'a, T>,
191 ) -> Self::Mut<'b, T> {
192 mut_
193 }
194
195 fn map<T: ?Sized, U: ?Sized>(
196 ref_: Self::Ref<'_, T>,
197 f: impl FnOnce(&T) -> &U,
198 ) -> Self::Ref<'_, U> {
199 ref_.map(|inner| Ref::map(inner, f))
200 }
201
202 fn map_mut<T: ?Sized, U: ?Sized>(
203 mut_ref: Self::Mut<'_, T>,
204 f: impl FnOnce(&mut T) -> &mut U,
205 ) -> Self::Mut<'_, U> {
206 mut_ref.map(|inner| RefMut::map(inner, f))
207 }
208
209 fn try_map<I: ?Sized, U: ?Sized>(
210 _self: Self::Ref<'_, I>,
211 f: impl FnOnce(&I) -> Option<&U>,
212 ) -> Option<Self::Ref<'_, U>> {
213 _self.try_map(|inner| Ref::filter_map(inner, f).ok())
214 }
215
216 fn try_map_mut<I: ?Sized, U: ?Sized>(
217 mut_ref: Self::Mut<'_, I>,
218 f: impl FnOnce(&mut I) -> Option<&mut U>,
219 ) -> Option<Self::Mut<'_, U>> {
220 mut_ref.try_map(|inner| RefMut::filter_map(inner, f).ok())
221 }
222
223 fn data_ptr(&self) -> *const () {
224 self.data.as_ptr() as *const ()
225 }
226
227 fn recycle(pointer: GenerationalPointer<Self>) {
228 let mut borrow_mut = pointer.storage.data.borrow_mut();
229
230 if !borrow_mut.valid(&pointer.location) {
232 return;
233 }
234
235 borrow_mut.increment_generation();
236 match &mut borrow_mut.data {
238 RefCellStorageEntryData::Data(_) => borrow_mut.data = RefCellStorageEntryData::Empty,
240 RefCellStorageEntryData::Rc(_) => {}
242 RefCellStorageEntryData::Reference(reference) => {
244 let reference = *reference;
245 drop(borrow_mut);
246 drop_ref(reference);
247 }
248 RefCellStorageEntryData::Empty => {}
249 }
250
251 UNSYNC_RUNTIME.with(|runtime| runtime.borrow_mut().push(pointer.storage));
252 }
253}
254
255fn drop_ref(pointer: GenerationalPointer<UnsyncStorage>) {
256 let mut borrow_mut = pointer.storage.data.borrow_mut();
257
258 if !borrow_mut.valid(&pointer.location) {
260 return;
261 }
262
263 if let RefCellStorageEntryData::Rc(entry) = &mut borrow_mut.data {
264 if entry.drop_ref() {
266 borrow_mut.data = RefCellStorageEntryData::Empty;
268 UNSYNC_RUNTIME.with(|runtime| runtime.borrow_mut().push(pointer.storage));
269 }
270 } else {
271 unreachable!("References should always point to a data entry directly",);
272 }
273}
274
275impl<T: 'static> Storage<T> for UnsyncStorage {
276 #[track_caller]
277 fn try_read(
278 pointer: GenerationalPointer<Self>,
279 ) -> Result<Self::Ref<'static, T>, error::BorrowError> {
280 let (read, pointer) = Self::read(pointer)?;
281
282 let ref_ = Ref::filter_map(read, |any| {
283 any.downcast_ref()
285 });
286 match ref_ {
287 Ok(guard) => Ok(GenerationalRef::new(
288 guard,
289 pointer.storage.borrow_info.borrow_guard(),
290 )),
291 Err(_) => Err(error::BorrowError::Dropped(
292 error::ValueDroppedError::new_for_location(pointer.location),
293 )),
294 }
295 }
296
297 #[track_caller]
298 fn try_write(
299 pointer: GenerationalPointer<Self>,
300 ) -> Result<Self::Mut<'static, T>, error::BorrowMutError> {
301 let (write, pointer) = Self::write(pointer)?;
302
303 let ref_mut = RefMut::filter_map(write, |any| {
304 any.downcast_mut()
306 });
307 match ref_mut {
308 Ok(guard) => Ok(GenerationalRefMut::new(
309 guard,
310 pointer.storage.borrow_info.borrow_mut_guard(),
311 )),
312 Err(_) => Err(error::BorrowMutError::Dropped(
313 error::ValueDroppedError::new_for_location(pointer.location),
314 )),
315 }
316 }
317
318 fn new(value: T, caller: &'static std::panic::Location<'static>) -> GenerationalPointer<Self> {
319 Self::create_new(RefCellStorageEntryData::Data(Box::new(value)), caller)
320 }
321
322 fn new_rc(
323 value: T,
324 caller: &'static std::panic::Location<'static>,
325 ) -> GenerationalPointer<Self> {
326 let data = Self::create_new(
328 RefCellStorageEntryData::Rc(RcStorageEntry::new(Box::new(value))),
329 caller,
330 );
331 Self::create_new(RefCellStorageEntryData::Reference(data), caller)
332 }
333
334 fn new_reference(
335 pointer: GenerationalPointer<Self>,
336 ) -> BorrowResult<GenerationalPointer<Self>> {
337 let (pointer, value) = Self::get_split_ref(pointer)?;
339 if let RefCellStorageEntryData::Rc(data) = &value.data {
340 data.add_ref();
341 } else {
342 unreachable!()
343 }
344 Ok(Self::create_new(
345 RefCellStorageEntryData::Reference(pointer),
346 pointer
347 .location
348 .created_at()
349 .unwrap_or(std::panic::Location::caller()),
350 ))
351 }
352
353 fn change_reference(
354 location: GenerationalPointer<Self>,
355 other: GenerationalPointer<Self>,
356 ) -> BorrowResult {
357 if location == other {
358 return Ok(());
359 }
360
361 let (other_final, other_write) = Self::get_split_ref(other)?;
362
363 let mut write = location.storage.data.borrow_mut();
364 if !write.valid(&location.location) {
366 return Err(BorrowError::Dropped(ValueDroppedError::new_for_location(
367 location.location,
368 )));
369 }
370
371 if let (RefCellStorageEntryData::Reference(reference), RefCellStorageEntryData::Rc(data)) =
372 (&mut write.data, &other_write.data)
373 {
374 if reference == &other_final {
375 return Ok(());
376 }
377 drop_ref(*reference);
378 *reference = other_final;
379 data.add_ref();
380 } else {
381 tracing::trace!(
382 "References should always point to a data entry directly found {:?} instead",
383 other_write.data
384 );
385 return Err(BorrowError::Dropped(ValueDroppedError::new_for_location(
386 other_final.location,
387 )));
388 }
389
390 Ok(())
391 }
392}