1- use std:: cell:: { RefCell , UnsafeCell } ;
1+ use std:: cell:: RefCell ;
22
33#[ cfg( feature = "serde" ) ]
44use serde:: ser:: { Serialize , Serializer } ;
55
66use crate :: error:: { Error , Result } ;
77use crate :: types:: XRc ;
88
9- use super :: lock:: { RawLock , UserDataLock } ;
9+ use super :: lock:: { RawLock , RwLock , UserDataLock } ;
1010use super :: r#ref:: { UserDataRef , UserDataRefMut } ;
1111
1212#[ cfg( all( feature = "serde" , not( feature = "send" ) ) ) ]
@@ -80,10 +80,12 @@ impl<T> UserDataVariant<T> {
8080 return Err ( Error :: UserDataBorrowMutError ) ;
8181 }
8282 Ok ( match self {
83- Self :: Default ( inner) => XRc :: into_inner ( inner) . unwrap ( ) . value . into_inner ( ) ,
83+ Self :: Default ( inner) => XRc :: into_inner ( inner) . unwrap ( ) . into_value ( ) ,
8484 #[ cfg( feature = "serde" ) ]
8585 Self :: Serializable ( inner) => unsafe {
86- let raw = Box :: into_raw ( XRc :: into_inner ( inner) . unwrap ( ) . value . into_inner ( ) ) ;
86+ // The serde variant erases `T` to `Box<DynSerialize>`, so we
87+ // must cast the raw pointer back to recover the concrete type.
88+ let raw = Box :: into_raw ( XRc :: into_inner ( inner) . unwrap ( ) . into_value ( ) ) ;
8789 * Box :: from_raw ( raw as * mut T )
8890 } ,
8991 } )
@@ -101,18 +103,18 @@ impl<T> UserDataVariant<T> {
101103 #[ inline( always) ]
102104 pub ( super ) fn raw_lock ( & self ) -> & RawLock {
103105 match self {
104- Self :: Default ( inner) => & inner. raw_lock ,
106+ Self :: Default ( inner) => unsafe { inner. raw_lock ( ) } ,
105107 #[ cfg( feature = "serde" ) ]
106- Self :: Serializable ( inner) => & inner. raw_lock ,
108+ Self :: Serializable ( inner) => unsafe { inner. raw_lock ( ) } ,
107109 }
108110 }
109111
110112 #[ inline( always) ]
111113 pub ( super ) fn as_ptr ( & self ) -> * mut T {
112114 match self {
113- Self :: Default ( inner) => inner. value . get ( ) ,
115+ Self :: Default ( inner) => inner. as_ptr ( ) ,
114116 #[ cfg( feature = "serde" ) ]
115- Self :: Serializable ( inner) => unsafe { & mut * * ( inner. value . get ( ) as * mut Box < T > ) } ,
117+ Self :: Serializable ( inner) => unsafe { ( & mut * * inner. as_ptr ( ) ) as * mut DynSerialize as * mut T } ,
116118 }
117119 }
118120}
@@ -124,31 +126,40 @@ impl Serialize for UserDataStorage<()> {
124126 Self :: Owned ( variant @ UserDataVariant :: Serializable ( inner) ) => unsafe {
125127 let _guard = ( variant. raw_lock ( ) . try_lock_shared_guarded ( ) )
126128 . map_err ( |_| serde:: ser:: Error :: custom ( Error :: UserDataBorrowError ) ) ?;
127- ( * inner. value . get ( ) ) . serialize ( serializer)
129+ ( * inner. as_ptr ( ) ) . serialize ( serializer)
128130 } ,
129131 _ => Err ( serde:: ser:: Error :: custom ( "cannot serialize <userdata>" ) ) ,
130132 }
131133 }
132134}
133135
134136/// A type that provides interior mutability for a userdata value (thread-safe).
135- pub ( crate ) struct UserDataCell < T > {
136- raw_lock : RawLock ,
137- value : UnsafeCell < T > ,
138- }
139-
140- #[ cfg( feature = "send" ) ]
141- unsafe impl < T : Send > Send for UserDataCell < T > { }
142- #[ cfg( feature = "send" ) ]
143- unsafe impl < T : Send > Sync for UserDataCell < T > { }
137+ pub ( crate ) struct UserDataCell < T > ( RwLock < T > ) ;
144138
145139impl < T > UserDataCell < T > {
146140 #[ inline( always) ]
147141 fn new ( value : T ) -> Self {
148- UserDataCell {
149- raw_lock : RawLock :: INIT ,
150- value : UnsafeCell :: new ( value) ,
151- }
142+ UserDataCell ( RwLock :: new ( value) )
143+ }
144+
145+ /// Returns a reference to the underlying raw lock.
146+ #[ inline( always) ]
147+ pub ( super ) unsafe fn raw_lock ( & self ) -> & RawLock {
148+ self . 0 . raw ( )
149+ }
150+
151+ /// Returns a raw pointer to the wrapped value.
152+ ///
153+ /// The caller is responsible for ensuring the appropriate lock is held.
154+ #[ inline( always) ]
155+ pub ( super ) fn as_ptr ( & self ) -> * mut T {
156+ self . 0 . data_ptr ( )
157+ }
158+
159+ /// Consumes the cell and returns the inner value.
160+ #[ inline( always) ]
161+ pub ( super ) fn into_value ( self ) -> T {
162+ self . 0 . into_inner ( )
152163 }
153164}
154165
0 commit comments