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