sync.rs 13 KB

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