@@ -3,6 +3,7 @@ use crate::sync::{AtomicBool, ReadGuard, RwLock, WriteGuard};
3
3
use crate :: sync:: { DynSend , DynSync } ;
4
4
use std:: {
5
5
cell:: UnsafeCell ,
6
+ intrinsics:: likely,
6
7
marker:: PhantomData ,
7
8
ops:: { Deref , DerefMut } ,
8
9
sync:: atomic:: Ordering ,
@@ -27,7 +28,37 @@ unsafe impl<T: DynSync + DynSend> DynSync for FreezeLock<T> {}
27
28
impl < T > FreezeLock < T > {
28
29
#[ inline]
29
30
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
+ #[ inline]
49
+ pub fn is_frozen ( & self ) -> bool {
50
+ self . frozen . load ( Ordering :: Acquire )
51
+ }
52
+
53
+ /// Get the inner value if frozen.
54
+ #[ inline]
55
+ pub fn get ( & self ) -> Option < & T > {
56
+ if likely ( self . frozen . load ( Ordering :: Acquire ) ) {
57
+ // SAFETY: This is frozen so the data cannot be modified.
58
+ unsafe { Some ( & * self . data . get ( ) ) }
59
+ } else {
60
+ None
61
+ }
31
62
}
32
63
33
64
#[ inline]
@@ -42,13 +73,25 @@ impl<T> FreezeLock<T> {
42
73
}
43
74
}
44
75
76
+ #[ inline]
77
+ pub fn borrow ( & self ) -> FreezeReadGuard < ' _ , T > {
78
+ self . read ( )
79
+ }
80
+
45
81
#[ inline]
46
82
#[ track_caller]
47
83
pub fn write ( & self ) -> FreezeWriteGuard < ' _ , T > {
48
- let _lock_guard = self . lock . write ( ) ;
49
- // 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 }
84
+ self . try_write ( ) . expect ( "still mutable" )
85
+ }
86
+
87
+ #[ inline]
88
+ pub fn try_write ( & self ) -> Option < FreezeWriteGuard < ' _ , T > > {
89
+ if self . frozen . load ( Ordering :: Relaxed ) {
90
+ None
91
+ } else {
92
+ let _lock_guard = self . lock . write ( ) ;
93
+ Some ( FreezeWriteGuard { _lock_guard, lock : self , marker : PhantomData } )
94
+ }
52
95
}
53
96
54
97
#[ inline]
@@ -90,6 +133,15 @@ pub struct FreezeWriteGuard<'a, T> {
90
133
marker : PhantomData < & ' a mut T > ,
91
134
}
92
135
136
+ impl < ' a , T > FreezeWriteGuard < ' a , T > {
137
+ pub fn freeze ( self ) -> & ' a T {
138
+ self . lock . frozen . store ( true , Ordering :: Release ) ;
139
+
140
+ // SAFETY: This is frozen so the data cannot be modified and shared access is sound.
141
+ unsafe { & * self . lock . data . get ( ) }
142
+ }
143
+ }
144
+
93
145
impl < ' a , T : ' a > Deref for FreezeWriteGuard < ' a , T > {
94
146
type Target = T ;
95
147
#[ inline]
0 commit comments