1616 */
1717
1818use slab:: Slab ;
19- use std:: cell:: { Cell , RefCell , RefMut } ;
19+ use std:: cell:: { Cell , RefCell } ;
20+ use std:: fmt;
2021use std:: marker:: PhantomData ;
2122use std:: mem;
2223use std:: ops:: { Deref , DerefMut } ;
2324use std:: process:: abort;
2425use std:: ptr:: NonNull ;
2526use std:: sync:: { Mutex , MutexGuard } ;
2627
27- pub struct EntryGuard < ' a , T > {
28- entries : RefMut < ' a , Slab < T > > ,
29- entry : & ' a mut T ,
30- key : usize ,
31- }
32-
33- impl < T > EntryGuard < ' _ , T > {
34- fn remove ( mut self ) {
35- self . entries . remove ( self . key ) ;
36- }
37- }
38-
39- impl < T > Deref for EntryGuard < ' _ , T > {
40- type Target = T ;
28+ pub struct InsertError < T > ( pub T ) ;
4129
42- fn deref ( & self ) -> & Self :: Target {
43- self . entry
44- }
45- }
46-
47- impl < T > DerefMut for EntryGuard < ' _ , T > {
48- fn deref_mut ( & mut self ) -> & mut Self :: Target {
49- self . entry
30+ impl < T > fmt:: Debug for InsertError < T > {
31+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
32+ f. debug_struct ( "InsertError" ) . finish_non_exhaustive ( )
5033 }
5134}
5235
5336// This is essentially a sharable slab for use within a single thread.
54- // operations are protected by a RefCell. When an element is retrieved for
55- // reading or modification, it is wrapped in a EntryGuard which keeps the
56- // entire slab borrowed until the caller is done working with the element
37+ // Operations are protected by a RefCell, however lookup operations return
38+ // pointers that can be used without RefCell protection.
5739pub struct Memory < T > {
5840 entries : RefCell < Slab < T > > ,
5941}
@@ -70,58 +52,44 @@ impl<T> Memory<T> {
7052
7153 #[ cfg( test) ]
7254 pub fn len ( & self ) -> usize {
73- let entries = self . entries . borrow ( ) ;
74-
75- entries. len ( )
55+ self . entries . borrow ( ) . len ( )
7656 }
7757
78- fn insert ( & self , e : T ) -> Result < usize , ( ) > {
58+ fn insert ( & self , e : T ) -> Result < usize , InsertError < T > > {
7959 let mut entries = self . entries . borrow_mut ( ) ;
8060
8161 // Out of capacity. By preventing inserts beyond the capacity, we
82- // ensure the underlying memory won't get moved due to a realloc
62+ // ensure the underlying memory won't get moved due to a realloc.
8363 if entries. len ( ) == entries. capacity ( ) {
84- return Err ( ( ) ) ;
64+ return Err ( InsertError ( e ) ) ;
8565 }
8666
8767 Ok ( entries. insert ( e) )
8868 }
8969
90- fn get < ' a > ( & ' a self , key : usize ) -> Option < EntryGuard < ' a , T > > {
91- let mut entries = self . entries . borrow_mut ( ) ;
70+ fn remove ( & self , key : usize ) {
71+ self . entries . borrow_mut ( ) . remove ( key) ;
72+ }
9273
93- let entry = entries. get_mut ( key) ?;
74+ // Returns a pointer to an entry if it exists.
75+ //
76+ // SAFETY: The returned pointer is guaranteed to be valid until the entry
77+ // is removed or the Memory is dropped.
78+ fn addr_of ( & self , key : usize ) -> Option < * const T > {
79+ let entries = self . entries . borrow ( ) ;
80+
81+ let entry = entries. get ( key) ?;
9482
9583 // Slab element addresses are guaranteed to be stable once created,
96- // and the only place we remove the element is in EntryGuard's
97- // remove method which consumes itself, therefore it is safe to
98- // assume the element will live at least as long as the EntryGuard
99- // and we can extend the lifetime of the reference beyond the
100- // RefMut
101- let entry = unsafe { mem:: transmute :: < & mut T , & ' a mut T > ( entry) } ;
84+ // therefore we can return a pointer to the element and guarantee
85+ // its validity until the element is removed.
10286
103- Some ( EntryGuard {
104- entries,
105- entry,
106- key,
107- } )
87+ Some ( entry as * const T )
10888 }
10989
11090 fn key_of ( & self , present_element : & T ) -> usize {
11191 self . entries . borrow ( ) . key_of ( present_element)
11292 }
113-
114- // For tests, as a way to confirm the memory isn't moving. Be careful
115- // with this. The very first element inserted will be at index 0, but
116- // if the slab has been used and cleared, then the next element
117- // inserted may not be at index 0 and calling this method afterward
118- // will panic
119- #[ cfg( test) ]
120- fn entry0_ptr ( & self ) -> * const T {
121- let entries = self . entries . borrow ( ) ;
122-
123- entries. get ( 0 ) . unwrap ( ) as * const T
124- }
12593}
12694
12795pub struct SyncEntryGuard < ' a , T > {
@@ -370,18 +338,21 @@ pub struct Rc<T> {
370338
371339impl < T > Rc < T > {
372340 #[ allow( clippy:: result_unit_err) ]
373- pub fn new ( v : T , memory : & std:: rc:: Rc < RcMemory < T > > ) -> Result < Self , ( ) > {
374- let key = memory. insert ( RcInner {
375- refs : Cell :: new ( 1 ) ,
376- memory : std:: rc:: Rc :: clone ( memory) ,
377- value : v,
378- } ) ?;
341+ pub fn new ( v : T , memory : & std:: rc:: Rc < RcMemory < T > > ) -> Result < Self , InsertError < T > > {
342+ let key = memory
343+ . insert ( RcInner {
344+ refs : Cell :: new ( 1 ) ,
345+ memory : std:: rc:: Rc :: clone ( memory) ,
346+ value : v,
347+ } )
348+ . map_err ( |e| InsertError ( e. 0 . value ) ) ?;
379349
380350 // Guaranteed to succeed since we inserted the element above
381- let mut inner = memory. get ( key) . unwrap ( ) ;
351+ let ptr : * const RcInner < T > = memory. addr_of ( key) . unwrap ( ) ;
382352
383- // Get a pointer to the inner data
384- let ptr = ( & mut * inner) . into ( ) ;
353+ // SAFETY: ptr is not null and we promise to only use it immutably
354+ // despite casting it to *mut in order to construct NonNull
355+ let ptr = unsafe { NonNull :: new_unchecked ( ptr as * mut RcInner < T > ) } ;
385356
386357 Ok ( Self {
387358 ptr,
@@ -417,10 +388,21 @@ impl<T> Rc<T> {
417388
418389 #[ inline( never) ]
419390 fn drop_slow ( & mut self ) {
420- let inner = self . inner ( ) ;
421- let key = inner. memory . key_of ( inner) ;
422- let entry = inner. memory . get ( key) . unwrap ( ) ;
423- entry. remove ( ) ;
391+ // Entries contain a std::rc::Rc to the Memory they are contained in,
392+ // and we need to be careful the Memory is not dropped while an entry
393+ // is being removed. To ensure this, we clone the Rc to the Memory
394+ // before removing the entry.
395+
396+ let memory = {
397+ let inner = self . inner ( ) ;
398+ let memory = std:: rc:: Rc :: clone ( & inner. memory ) ;
399+ memory. remove ( memory. key_of ( inner) ) ;
400+
401+ memory
402+ } ;
403+
404+ // The entry has been removed by this point
405+ drop ( memory) ;
424406 }
425407}
426408
@@ -626,15 +608,15 @@ mod tests {
626608
627609 let e0a = Rc :: new ( 123 as i32 , & memory) . unwrap ( ) ;
628610 assert_eq ! ( memory. len( ) , 1 ) ;
629- let p = memory. entry0_ptr ( ) ;
611+ let p = memory. addr_of ( 0 ) . unwrap ( ) ;
630612
631613 let e0b = Rc :: clone ( & e0a) ;
632614 assert_eq ! ( memory. len( ) , 1 ) ;
633- assert_eq ! ( memory. entry0_ptr ( ) , p) ;
615+ assert_eq ! ( memory. addr_of ( 0 ) . unwrap ( ) , p) ;
634616
635617 let e1a = Rc :: new ( 456 as i32 , & memory) . unwrap ( ) ;
636618 assert_eq ! ( memory. len( ) , 2 ) ;
637- assert_eq ! ( memory. entry0_ptr ( ) , p) ;
619+ assert_eq ! ( memory. addr_of ( 0 ) . unwrap ( ) , p) ;
638620
639621 // No room
640622 assert ! ( Rc :: new( 789 as i32 , & memory) . is_err( ) ) ;
@@ -645,7 +627,7 @@ mod tests {
645627
646628 mem:: drop ( e0b) ;
647629 assert_eq ! ( memory. len( ) , 2 ) ;
648- assert_eq ! ( memory. entry0_ptr ( ) , p) ;
630+ assert_eq ! ( memory. addr_of ( 0 ) . unwrap ( ) , p) ;
649631
650632 mem:: drop ( e0a) ;
651633 assert_eq ! ( memory. len( ) , 1 ) ;
0 commit comments