shadow_shim_helper_rs/rootedcell/
rc.rs
1use std::{
2 cell::{Cell, UnsafeCell},
3 ptr::NonNull,
4};
5
6use crate::explicit_drop::ExplicitDrop;
7
8use super::{Root, Tag};
9
10struct RootedRcInternal<T> {
11 val: UnsafeCell<Option<T>>,
12 strong_count: Cell<u32>,
13 weak_count: Cell<u32>,
14}
15
16impl<T> RootedRcInternal<T> {
17 pub fn new(val: T) -> Self {
18 Self {
19 val: UnsafeCell::new(Some(val)),
20 strong_count: Cell::new(1),
21 weak_count: Cell::new(0),
22 }
23 }
24
25 pub fn inc_strong(&self) {
26 self.strong_count.set(self.strong_count.get() + 1)
27 }
28
29 pub fn dec_strong(&self) {
30 self.strong_count.set(self.strong_count.get() - 1)
31 }
32
33 pub fn inc_weak(&self) {
34 self.weak_count.set(self.weak_count.get() + 1)
35 }
36
37 pub fn dec_weak(&self) {
38 self.weak_count.set(self.weak_count.get() - 1)
39 }
40}
41
42enum RefType {
43 Weak,
44 Strong,
45}
46
47struct RootedRcCommon<T> {
49 tag: Tag,
50 internal: Option<NonNull<RootedRcInternal<T>>>,
51}
52
53impl<T> RootedRcCommon<T> {
54 pub fn new(root: &Root, val: T) -> Self {
55 Self {
56 tag: root.tag(),
57 internal: Some(
58 NonNull::new(Box::into_raw(Box::new(RootedRcInternal::new(val)))).unwrap(),
59 ),
60 }
61 }
62
63 pub fn borrow_internal(&self, root: &Root) -> &RootedRcInternal<T> {
66 assert_eq!(
67 root.tag, self.tag,
68 "Tried using root {:?} instead of {:?}",
69 root.tag, self.tag
70 );
71 unsafe { self.internal.unwrap().as_ref() }
76 }
77
78 pub fn safely_drop(mut self, root: &Root, t: RefType) -> Option<T> {
80 let internal: &RootedRcInternal<T> = self.borrow_internal(root);
81 match t {
82 RefType::Weak => internal.dec_weak(),
83 RefType::Strong => internal.dec_strong(),
84 };
85 let strong_count = internal.strong_count.get();
86 let weak_count = internal.weak_count.get();
87
88 let val: Option<T> = if strong_count == 0 {
93 unsafe { internal.val.get().as_mut().unwrap().take() }
96 } else {
97 None
98 };
99
100 let internal: NonNull<RootedRcInternal<T>> = self.internal.take().unwrap();
102
103 if strong_count == 0 && weak_count == 0 {
105 drop(unsafe { Box::from_raw(internal.as_ptr()) });
109 }
110
111 val
112 }
113
114 pub fn clone(&self, root: &Root, t: RefType) -> Self {
115 let internal: &RootedRcInternal<T> = self.borrow_internal(root);
116 match t {
117 RefType::Weak => internal.inc_weak(),
118 RefType::Strong => internal.inc_strong(),
119 };
120 Self {
121 tag: self.tag,
122 internal: self.internal,
123 }
124 }
125}
126
127impl<T> Drop for RootedRcCommon<T> {
128 #[inline]
129 fn drop(&mut self) {
130 if self.internal.is_some() {
131 log::error!("Dropped without calling `explicit_drop`");
133
134 #[cfg(debug_assertions)]
145 if !std::thread::panicking() {
146 panic!("Dropped without calling `explicit_drop`");
147 }
148 }
149 }
150}
151
152unsafe impl<T: Sync + Send> Send for RootedRcCommon<T> {}
156unsafe impl<T: Sync + Send> Sync for RootedRcCommon<T> {}
157
158pub struct RootedRc<T> {
173 common: RootedRcCommon<T>,
174}
175
176impl<T> RootedRc<T> {
177 #[inline]
179 pub fn new(root: &Root, val: T) -> Self {
180 Self {
181 common: RootedRcCommon::new(root, val),
182 }
183 }
184
185 #[inline]
190 pub fn downgrade(this: &Self, root: &Root) -> RootedRcWeak<T> {
191 RootedRcWeak {
192 common: this.common.clone(root, RefType::Weak),
193 }
194 }
195
196 #[inline]
202 pub fn clone(&self, root: &Root) -> Self {
203 Self {
204 common: self.common.clone(root, RefType::Strong),
205 }
206 }
207
208 #[inline]
211 pub fn into_inner(this: Self, root: &Root) -> Option<T> {
212 this.common.safely_drop(root, RefType::Strong)
213 }
214
215 pub fn explicit_drop_recursive(
218 self,
219 root: &Root,
220 param: &T::ExplicitDropParam,
221 ) -> Option<T::ExplicitDropResult>
222 where
223 T: ExplicitDrop,
224 {
225 Self::into_inner(self, root).map(|val| val.explicit_drop(param))
226 }
227}
228
229impl<T> ExplicitDrop for RootedRc<T> {
230 type ExplicitDropParam = Root;
231
232 type ExplicitDropResult = ();
233
234 fn explicit_drop(self, root: &Self::ExplicitDropParam) -> Self::ExplicitDropResult {
238 self.common.safely_drop(root, RefType::Strong);
239 }
240}
241
242impl<T> std::ops::Deref for RootedRc<T> {
243 type Target = T;
244
245 #[inline]
246 fn deref(&self) -> &Self::Target {
247 let internal = unsafe { self.common.internal.unwrap().as_ref() };
253
254 let val = unsafe { &*internal.val.get() };
259 val.as_ref().unwrap()
260 }
261}
262
263#[cfg(test)]
264mod test_rooted_rc {
265 use std::{sync::Arc, thread};
266
267 use super::*;
268
269 #[test]
270 fn construct_and_drop() {
271 let root = Root::new();
272 let rc = RootedRc::new(&root, 0);
273 rc.explicit_drop(&root)
274 }
275
276 #[test]
277 #[cfg(debug_assertions)]
278 #[should_panic]
279 fn drop_without_lock_panics_with_debug_assertions() {
280 let root = Root::new();
281 drop(RootedRc::new(&root, 0));
282 }
283
284 #[test]
285 #[cfg(not(debug_assertions))]
286 fn drop_without_lock_leaks_without_debug_assertions() {
287 let root = Root::new();
288 let rc = std::rc::Rc::new(());
289 let rrc = RootedRc::new(&root, rc.clone());
290 drop(rrc);
291 assert_eq!(std::rc::Rc::strong_count(&rc), 2);
294 }
295
296 #[test]
297 fn send_to_worker_thread() {
298 let root = Root::new();
299 let rc = RootedRc::new(&root, 0);
300 thread::spawn(move || {
301 let _ = *rc + 2;
303 rc.explicit_drop(&root)
305 })
306 .join()
307 .unwrap();
308 }
309
310 #[test]
311 fn send_to_worker_thread_and_retrieve() {
312 let root = Root::new();
313 let root = thread::spawn(move || {
314 let rc = RootedRc::new(&root, 0);
315 rc.explicit_drop(&root);
316 root
317 })
318 .join()
319 .unwrap();
320 let rc = RootedRc::new(&root, 0);
321 rc.explicit_drop(&root)
322 }
323
324 #[test]
325 fn clone_to_worker_thread() {
326 let root = Root::new();
327 let rc = RootedRc::new(&root, 0);
328
329 let rc_thread = rc.clone(&root);
331
332 let root = thread::spawn(move || {
335 let _ = *rc_thread;
336 rc_thread.explicit_drop(&root);
337 root
338 })
339 .join()
340 .unwrap();
341
342 rc.explicit_drop(&root);
344 }
345
346 #[test]
347 fn threads_contend_over_lock() {
348 let root = Arc::new(std::sync::Mutex::new(Root::new()));
349 let rc = RootedRc::new(&root.lock().unwrap(), 0);
350
351 let threads: Vec<_> = (0..100)
352 .map(|_| {
353 let rc = rc.clone(&root.lock().unwrap());
355 let root = root.clone();
356
357 thread::spawn(move || {
358 let rootlock = root.lock().unwrap();
359 let rc2 = rc.clone(&rootlock);
360 rc.explicit_drop(&rootlock);
361 rc2.explicit_drop(&rootlock);
362 })
363 })
364 .collect();
365
366 for handle in threads {
367 handle.join().unwrap();
368 }
369
370 rc.explicit_drop(&root.lock().unwrap());
371 }
372
373 #[test]
374 fn into_inner_recursive() {
375 let root = Root::new();
376 let inner = RootedRc::new(&root, ());
377 let outer1 = RootedRc::new(&root, inner);
378 let outer2 = outer1.clone(&root);
379
380 assert!(RootedRc::into_inner(outer1, &root).is_none());
382
383 let inner = RootedRc::into_inner(outer2, &root).unwrap();
385
386 inner.explicit_drop(&root);
388 }
389
390 #[test]
391 fn explicit_drop() {
392 let root = Root::new();
393 let rc = RootedRc::new(&root, ());
394 rc.explicit_drop(&root);
395 }
396
397 #[test]
398 fn explicit_drop_recursive() {
399 struct MyOuter(RootedRc<()>);
402 impl ExplicitDrop for MyOuter {
403 type ExplicitDropParam = Root;
404 type ExplicitDropResult = ();
405
406 fn explicit_drop(self, root: &Self::ExplicitDropParam) -> Self::ExplicitDropResult {
407 self.0.explicit_drop(root);
408 }
409 }
410
411 let root = Root::new();
412 let inner = RootedRc::new(&root, ());
413 let outer1 = RootedRc::new(&root, MyOuter(inner));
414 let outer2 = RootedRc::new(&root, MyOuter(outer1.0.clone(&root)));
415 outer1.explicit_drop_recursive(&root, &root);
416 outer2.explicit_drop_recursive(&root, &root);
417 }
418}
419
420pub struct RootedRcWeak<T> {
421 common: RootedRcCommon<T>,
422}
423
424impl<T> RootedRcWeak<T> {
425 #[inline]
426 pub fn upgrade(&self, root: &Root) -> Option<RootedRc<T>> {
427 let internal = self.common.borrow_internal(root);
428
429 if internal.strong_count.get() == 0 {
430 return None;
431 }
432
433 Some(RootedRc {
434 common: self.common.clone(root, RefType::Strong),
435 })
436 }
437
438 #[inline]
444 pub fn clone(&self, root: &Root) -> Self {
445 Self {
446 common: self.common.clone(root, RefType::Weak),
447 }
448 }
449}
450
451impl<T> ExplicitDrop for RootedRcWeak<T> {
452 type ExplicitDropParam = Root;
453
454 type ExplicitDropResult = ();
455
456 #[inline]
457 fn explicit_drop(self, root: &Self::ExplicitDropParam) -> Self::ExplicitDropResult {
458 let val = self.common.safely_drop(root, RefType::Weak);
459 debug_assert!(val.is_none());
462 }
463}
464
465unsafe impl<T: Sync + Send> Send for RootedRcWeak<T> {}
469unsafe impl<T: Sync + Send> Sync for RootedRcWeak<T> {}
470
471#[cfg(test)]
472mod test_rooted_rc_weak {
473 use super::*;
474
475 #[test]
476 fn successful_upgrade() {
477 let root = Root::new();
478 let strong = RootedRc::new(&root, 42);
479 let weak = RootedRc::downgrade(&strong, &root);
480
481 let upgraded = weak.upgrade(&root).unwrap();
482
483 assert_eq!(*upgraded, *strong);
484
485 upgraded.explicit_drop(&root);
486 weak.explicit_drop(&root);
487 strong.explicit_drop(&root);
488 }
489
490 #[test]
491 fn failed_upgrade() {
492 let root = Root::new();
493 let strong = RootedRc::new(&root, 42);
494 let weak = RootedRc::downgrade(&strong, &root);
495
496 strong.explicit_drop(&root);
497
498 assert!(weak.upgrade(&root).is_none());
499
500 weak.explicit_drop(&root);
501 }
502
503 #[test]
504 #[cfg(debug_assertions)]
505 #[should_panic]
506 fn drop_without_lock_panics_with_debug_assertions() {
507 let root = Root::new();
508 let strong = RootedRc::new(&root, 42);
509 drop(RootedRc::downgrade(&strong, &root));
510 strong.explicit_drop(&root);
511 }
512
513 #[test]
515 fn circular_reference() {
516 std::thread_local! {
517 static THREAD_ROOT: Root = Root::new();
518 }
519
520 struct MyStruct {
521 weak_self: Cell<Option<RootedRcWeak<Self>>>,
523 }
524 impl MyStruct {
525 fn new() -> RootedRc<Self> {
526 THREAD_ROOT.with(|root| {
527 let rv = RootedRc::new(
528 root,
529 MyStruct {
530 weak_self: Cell::new(None),
531 },
532 );
533 let weak = RootedRc::downgrade(&rv, root);
534 rv.weak_self.set(Some(weak));
535 rv
536 })
537 }
538 }
539 impl Drop for MyStruct {
540 fn drop(&mut self) {
541 let weak = self.weak_self.replace(None).unwrap();
542 THREAD_ROOT.with(|root| {
543 weak.explicit_drop(root);
544 });
545 }
546 }
547
548 let val = MyStruct::new();
549 THREAD_ROOT.with(|root| {
550 val.explicit_drop(root);
551 })
552 }
553
554 #[test]
555 #[cfg(not(debug_assertions))]
556 fn drop_without_lock_doesnt_leak_value() {
557 let root = Root::new();
558 let rc = std::rc::Rc::new(());
559 let strong = RootedRc::new(&root, rc.clone());
560 drop(RootedRc::downgrade(&strong, &root));
561 strong.explicit_drop(&root);
562
563 assert_eq!(std::rc::Rc::strong_count(&rc), 1);
568 }
569}