1use parking_lot::{
2 MappedRwLockReadGuard, MappedRwLockWriteGuard, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard,
3};
4use std::{
5 any::Any,
6 fmt::Debug,
7 num::NonZeroU64,
8 sync::{Arc, OnceLock},
9};
10
11use crate::{
12 entry::{MemoryLocationBorrowInfo, RcStorageEntry, StorageEntry},
13 error::{self, ValueDroppedError},
14 references::{GenerationalRef, GenerationalRefMut},
15 AnyStorage, BorrowError, BorrowMutError, BorrowMutResult, BorrowResult, GenerationalLocation,
16 GenerationalPointer, Storage,
17};
18
19type RwLockStorageEntryRef = RwLockReadGuard<'static, StorageEntry<RwLockStorageEntryData>>;
20type RwLockStorageEntryMut = RwLockWriteGuard<'static, StorageEntry<RwLockStorageEntryData>>;
21
22pub(crate) enum RwLockStorageEntryData {
23 Reference(GenerationalPointer<SyncStorage>),
24 Rc(RcStorageEntry<Box<dyn Any + Send + Sync>>),
25 Data(Box<dyn Any + Send + Sync>),
26 Empty,
27}
28
29impl Default for RwLockStorageEntryData {
30 fn default() -> Self {
31 Self::Empty
32 }
33}
34
35impl Debug for RwLockStorageEntryData {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 match self {
38 Self::Reference(location) => write!(f, "Reference({:?})", location),
39 Self::Rc(_) => write!(f, "Rc"),
40 Self::Data(_) => write!(f, "Data"),
41 Self::Empty => write!(f, "Empty"),
42 }
43 }
44}
45
46impl RwLockStorageEntryData {
47 pub const fn new_full(data: Box<dyn Any + Send + Sync>) -> Self {
48 Self::Data(data)
49 }
50}
51
52#[derive(Default)]
54pub struct SyncStorage {
55 borrow_info: MemoryLocationBorrowInfo,
56 data: RwLock<StorageEntry<RwLockStorageEntryData>>,
57}
58
59impl SyncStorage {
60 pub(crate) fn read(
61 pointer: GenerationalPointer<Self>,
62 ) -> BorrowResult<MappedRwLockReadGuard<'static, Box<dyn Any + Send + Sync + 'static>>> {
63 Self::get_split_ref(pointer).map(|(_, guard)| {
64 RwLockReadGuard::map(guard, |data| match &data.data {
65 RwLockStorageEntryData::Data(data) => data,
66 RwLockStorageEntryData::Rc(data) => &data.data,
67 _ => unreachable!(),
68 })
69 })
70 }
71
72 pub(crate) fn get_split_ref(
73 mut pointer: GenerationalPointer<Self>,
74 ) -> BorrowResult<(GenerationalPointer<Self>, RwLockStorageEntryRef)> {
75 loop {
76 let borrow = pointer.storage.data.read();
77 if !borrow.valid(&pointer.location) {
78 return Err(BorrowError::Dropped(ValueDroppedError::new_for_location(
79 pointer.location,
80 )));
81 }
82 match &borrow.data {
83 RwLockStorageEntryData::Reference(data) => {
85 pointer = *data;
86 }
87 RwLockStorageEntryData::Data(_) | RwLockStorageEntryData::Rc(_) => {
89 return Ok((pointer, borrow));
90 }
91 RwLockStorageEntryData::Empty => {
92 return Err(BorrowError::Dropped(ValueDroppedError::new_for_location(
93 pointer.location,
94 )));
95 }
96 }
97 }
98 }
99
100 pub(crate) fn write(
101 pointer: GenerationalPointer<Self>,
102 ) -> BorrowMutResult<MappedRwLockWriteGuard<'static, Box<dyn Any + Send + Sync + 'static>>>
103 {
104 Self::get_split_mut(pointer).map(|(_, guard)| {
105 RwLockWriteGuard::map(guard, |data| match &mut data.data {
106 RwLockStorageEntryData::Data(data) => data,
107 RwLockStorageEntryData::Rc(data) => &mut data.data,
108 _ => unreachable!(),
109 })
110 })
111 }
112
113 pub(crate) fn get_split_mut(
114 mut pointer: GenerationalPointer<Self>,
115 ) -> BorrowMutResult<(GenerationalPointer<Self>, RwLockStorageEntryMut)> {
116 loop {
117 let borrow = pointer.storage.data.write();
118 if !borrow.valid(&pointer.location) {
119 return Err(BorrowMutError::Dropped(
120 ValueDroppedError::new_for_location(pointer.location),
121 ));
122 }
123 match &borrow.data {
124 RwLockStorageEntryData::Reference(data) => {
126 pointer = *data;
127 }
128 RwLockStorageEntryData::Data(_) | RwLockStorageEntryData::Rc(_) => {
130 return Ok((pointer, borrow));
131 }
132 RwLockStorageEntryData::Empty => {
133 return Err(BorrowMutError::Dropped(
134 ValueDroppedError::new_for_location(pointer.location),
135 ));
136 }
137 }
138 }
139 }
140
141 fn create_new(
142 value: RwLockStorageEntryData,
143 #[allow(unused)] caller: &'static std::panic::Location<'static>,
144 ) -> GenerationalPointer<Self> {
145 match sync_runtime().lock().pop() {
146 Some(storage) => {
147 let mut write = storage.data.write();
148 let location = GenerationalLocation {
149 generation: write.generation(),
150 #[cfg(any(debug_assertions, feature = "debug_borrows"))]
151 created_at: caller,
152 };
153 write.data = value;
154 GenerationalPointer { storage, location }
155 }
156 None => {
157 let storage: &'static Self = &*Box::leak(Box::new(Self {
158 borrow_info: Default::default(),
159 data: RwLock::new(StorageEntry::new(value)),
160 }));
161
162 let location = GenerationalLocation {
163 generation: NonZeroU64::MIN,
164 #[cfg(any(debug_assertions, feature = "debug_borrows"))]
165 created_at: caller,
166 };
167
168 GenerationalPointer { storage, location }
169 }
170 }
171 }
172}
173
174static SYNC_RUNTIME: OnceLock<Arc<Mutex<Vec<&'static SyncStorage>>>> = OnceLock::new();
175
176fn sync_runtime() -> &'static Arc<Mutex<Vec<&'static SyncStorage>>> {
177 SYNC_RUNTIME.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
178}
179
180impl AnyStorage for SyncStorage {
181 type Ref<'a, R: ?Sized + 'static> = GenerationalRef<MappedRwLockReadGuard<'a, R>>;
182 type Mut<'a, W: ?Sized + 'static> = GenerationalRefMut<MappedRwLockWriteGuard<'a, W>>;
183
184 fn downcast_lifetime_ref<'a: 'b, 'b, T: ?Sized + 'static>(
185 ref_: Self::Ref<'a, T>,
186 ) -> Self::Ref<'b, T> {
187 ref_
188 }
189
190 fn downcast_lifetime_mut<'a: 'b, 'b, T: ?Sized + 'static>(
191 mut_: Self::Mut<'a, T>,
192 ) -> Self::Mut<'b, T> {
193 mut_
194 }
195
196 fn map<T: ?Sized + 'static, U: ?Sized + 'static>(
197 ref_: Self::Ref<'_, T>,
198 f: impl FnOnce(&T) -> &U,
199 ) -> Self::Ref<'_, U> {
200 ref_.map(|inner| MappedRwLockReadGuard::map(inner, f))
201 }
202
203 fn map_mut<T: ?Sized + 'static, U: ?Sized + 'static>(
204 mut_ref: Self::Mut<'_, T>,
205 f: impl FnOnce(&mut T) -> &mut U,
206 ) -> Self::Mut<'_, U> {
207 mut_ref.map(|inner| MappedRwLockWriteGuard::map(inner, f))
208 }
209
210 fn try_map<I: ?Sized + 'static, U: ?Sized + 'static>(
211 ref_: Self::Ref<'_, I>,
212 f: impl FnOnce(&I) -> Option<&U>,
213 ) -> Option<Self::Ref<'_, U>> {
214 ref_.try_map(|inner| MappedRwLockReadGuard::try_map(inner, f).ok())
215 }
216
217 fn try_map_mut<I: ?Sized + 'static, U: ?Sized + 'static>(
218 mut_ref: Self::Mut<'_, I>,
219 f: impl FnOnce(&mut I) -> Option<&mut U>,
220 ) -> Option<Self::Mut<'_, U>> {
221 mut_ref.try_map(|inner| MappedRwLockWriteGuard::try_map(inner, f).ok())
222 }
223
224 fn data_ptr(&self) -> *const () {
225 self.data.data_ptr() as *const ()
226 }
227
228 fn recycle(pointer: GenerationalPointer<Self>) {
229 let mut borrow_mut = pointer.storage.data.write();
230
231 if !borrow_mut.valid(&pointer.location) {
233 return;
234 }
235
236 borrow_mut.increment_generation();
237
238 match &mut borrow_mut.data {
240 RwLockStorageEntryData::Data(_) => borrow_mut.data = RwLockStorageEntryData::Empty,
242 RwLockStorageEntryData::Rc(_) => {}
244 RwLockStorageEntryData::Reference(reference) => {
246 drop_ref(*reference);
247 }
248 RwLockStorageEntryData::Empty => {}
249 }
250
251 sync_runtime().lock().push(pointer.storage);
252 }
253}
254
255fn drop_ref(pointer: GenerationalPointer<SyncStorage>) {
256 let mut borrow_mut = pointer.storage.data.write();
257
258 if !borrow_mut.valid(&pointer.location) {
260 return;
261 }
262
263 if let RwLockStorageEntryData::Rc(entry) = &mut borrow_mut.data {
264 if entry.drop_ref() {
266 borrow_mut.data = RwLockStorageEntryData::Empty;
268 sync_runtime().lock().push(pointer.storage);
269 }
270 } else {
271 unreachable!("References should always point to a data entry directly");
272 }
273}
274
275impl<T: Sync + Send + 'static> Storage<T> for SyncStorage {
276 #[track_caller]
277 fn try_read(
278 pointer: GenerationalPointer<Self>,
279 ) -> Result<Self::Ref<'static, T>, error::BorrowError> {
280 let read = Self::read(pointer)?;
281
282 let read = MappedRwLockReadGuard::try_map(read, |any| {
283 any.downcast_ref()
285 });
286 match read {
287 Ok(guard) => Ok(GenerationalRef::new(
288 guard,
289 pointer.storage.borrow_info.borrow_guard(),
290 )),
291 Err(_) => Err(error::BorrowError::Dropped(
292 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 = Self::write(pointer)?;
302
303 let write = MappedRwLockWriteGuard::try_map(write, |any| {
304 any.downcast_mut()
306 });
307 match write {
308 Ok(guard) => Ok(GenerationalRefMut::new(
309 guard,
310 pointer.storage.borrow_info.borrow_mut_guard(),
311 )),
312 Err(_) => Err(error::BorrowMutError::Dropped(
313 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(RwLockStorageEntryData::new_full(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 RwLockStorageEntryData::Rc(RcStorageEntry::new(Box::new(value))),
329 caller,
330 );
331 Self::create_new(RwLockStorageEntryData::Reference(data), caller)
332 }
333
334 fn new_reference(
335 location: GenerationalPointer<Self>,
336 ) -> BorrowResult<GenerationalPointer<Self>> {
337 let (location, value) = Self::get_split_ref(location)?;
339 if let RwLockStorageEntryData::Rc(data) = &value.data {
340 data.add_ref();
341 } else {
342 unreachable!()
343 }
344 Ok(Self::create_new(
345 RwLockStorageEntryData::Reference(location),
346 location
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.write();
364 if !write.valid(&location.location) {
366 return Err(BorrowError::Dropped(ValueDroppedError::new_for_location(
367 location.location,
368 )));
369 }
370
371 if let (RwLockStorageEntryData::Reference(reference), RwLockStorageEntryData::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}