@@ -3,6 +3,7 @@ use crate::sync::{AtomicBool, ReadGuard, RwLock, WriteGuard};
33use crate :: sync:: { DynSend , DynSync } ;
44use std:: {
55 cell:: UnsafeCell ,
6+ intrinsics:: likely,
67 marker:: PhantomData ,
78 ops:: { Deref , DerefMut } ,
89 sync:: atomic:: Ordering ,
@@ -27,7 +28,47 @@ unsafe impl<T: DynSync + DynSend> DynSync for FreezeLock<T> {}
2728impl < T > FreezeLock < T > {
2829 #[ inline]
2930 pub fn new ( value : T ) -> Self {
30- Self { data : UnsafeCell :: new ( value) , frozen : AtomicBool :: new ( false ) , lock : RwLock :: new ( ( ) ) }
31+ Self :: with ( value, false )
32+ }
33+
34+ #[ inline]
35+ pub fn frozen ( value : T ) -> Self {
36+ Self :: with ( value, true )
37+ }
38+
39+ #[ inline]
40+ pub fn with ( value : T , frozen : bool ) -> Self {
41+ Self {
42+ data : UnsafeCell :: new ( value) ,
43+ frozen : AtomicBool :: new ( frozen) ,
44+ lock : RwLock :: new ( ( ) ) ,
45+ }
46+ }
47+
48+ /// Clones the inner value along with the frozen state.
49+ #[ inline]
50+ pub fn clone ( & self ) -> Self
51+ where
52+ T : Clone ,
53+ {
54+ let lock = self . read ( ) ;
55+ Self :: with ( lock. clone ( ) , self . is_frozen ( ) )
56+ }
57+
58+ #[ inline]
59+ pub fn is_frozen ( & self ) -> bool {
60+ self . frozen . load ( Ordering :: Acquire )
61+ }
62+
63+ /// Get the inner value if frozen.
64+ #[ inline]
65+ pub fn get ( & self ) -> Option < & T > {
66+ if likely ( self . frozen . load ( Ordering :: Acquire ) ) {
67+ // SAFETY: This is frozen so the data cannot be modified.
68+ unsafe { Some ( & * self . data . get ( ) ) }
69+ } else {
70+ None
71+ }
3172 }
3273
3374 #[ inline]
@@ -42,13 +83,26 @@ impl<T> FreezeLock<T> {
4283 }
4384 }
4485
86+ #[ inline]
87+ pub fn borrow ( & self ) -> FreezeReadGuard < ' _ , T > {
88+ self . read ( )
89+ }
90+
4591 #[ inline]
4692 #[ track_caller]
4793 pub fn write ( & self ) -> FreezeWriteGuard < ' _ , T > {
94+ self . try_write ( ) . expect ( "still mutable" )
95+ }
96+
97+ #[ inline]
98+ pub fn try_write ( & self ) -> Option < FreezeWriteGuard < ' _ , T > > {
4899 let _lock_guard = self . lock . write ( ) ;
49100 // Use relaxed ordering since we're in the write lock.
50- assert ! ( !self . frozen. load( Ordering :: Relaxed ) , "still mutable" ) ;
51- FreezeWriteGuard { _lock_guard, lock : self , marker : PhantomData }
101+ if self . frozen . load ( Ordering :: Relaxed ) {
102+ None
103+ } else {
104+ Some ( FreezeWriteGuard { _lock_guard, lock : self , marker : PhantomData } )
105+ }
52106 }
53107
54108 #[ inline]
@@ -90,6 +144,15 @@ pub struct FreezeWriteGuard<'a, T> {
90144 marker : PhantomData < & ' a mut T > ,
91145}
92146
147+ impl < ' a , T > FreezeWriteGuard < ' a , T > {
148+ pub fn freeze ( self ) -> & ' a T {
149+ self . lock . frozen . store ( true , Ordering :: Release ) ;
150+
151+ // SAFETY: This is frozen so the data cannot be modified and shared access is sound.
152+ unsafe { & * self . lock . data . get ( ) }
153+ }
154+ }
155+
93156impl < ' a , T : ' a > Deref for FreezeWriteGuard < ' a , T > {
94157 type Target = T ;
95158 #[ inline]
0 commit comments