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