@@ -6,6 +6,7 @@ use std::{
6
6
intrinsics:: likely,
7
7
marker:: PhantomData ,
8
8
ops:: { Deref , DerefMut } ,
9
+ ptr:: NonNull ,
9
10
sync:: atomic:: Ordering ,
10
11
} ;
11
12
@@ -79,7 +80,7 @@ impl<T> FreezeLock<T> {
79
80
} else {
80
81
Some ( self . lock . read ( ) )
81
82
} ,
82
- lock : self ,
83
+ data : unsafe { NonNull :: new_unchecked ( self . data . get ( ) ) } ,
83
84
}
84
85
}
85
86
@@ -101,7 +102,12 @@ impl<T> FreezeLock<T> {
101
102
if self . frozen . load ( Ordering :: Relaxed ) {
102
103
None
103
104
} else {
104
- Some ( FreezeWriteGuard { _lock_guard, lock : self , marker : PhantomData } )
105
+ Some ( FreezeWriteGuard {
106
+ _lock_guard,
107
+ data : unsafe { NonNull :: new_unchecked ( self . data . get ( ) ) } ,
108
+ frozen : & self . frozen ,
109
+ marker : PhantomData ,
110
+ } )
105
111
}
106
112
}
107
113
@@ -120,52 +126,75 @@ impl<T> FreezeLock<T> {
120
126
121
127
/// A guard holding shared access to a `FreezeLock` which is in a locked state or frozen.
122
128
#[ must_use = "if unused the FreezeLock may immediately unlock" ]
123
- pub struct FreezeReadGuard < ' a , T > {
129
+ pub struct FreezeReadGuard < ' a , T : ? Sized > {
124
130
_lock_guard : Option < ReadGuard < ' a , ( ) > > ,
125
- lock : & ' a FreezeLock < T > ,
131
+ data : NonNull < T > ,
126
132
}
127
133
128
- impl < ' a , T : ' a > Deref for FreezeReadGuard < ' a , T > {
134
+ impl < ' a , T : ? Sized + ' a > Deref for FreezeReadGuard < ' a , T > {
129
135
type Target = T ;
130
136
#[ inline]
131
137
fn deref ( & self ) -> & T {
132
- // SAFETY: If ` lock` is not frozen, `_lock_guard` holds the lock to the `UnsafeCell` so
133
- // this has shared access until the `FreezeReadGuard` is dropped. If ` lock` is frozen,
138
+ // SAFETY: If the lock is not frozen, `_lock_guard` holds the lock to the `UnsafeCell` so
139
+ // this has shared access until the `FreezeReadGuard` is dropped. If the lock is frozen,
134
140
// the data cannot be modified and shared access is sound.
135
- unsafe { & * self . lock . data . get ( ) }
141
+ unsafe { & * self . data . as_ptr ( ) }
142
+ }
143
+ }
144
+
145
+ impl < ' a , T : ?Sized > FreezeReadGuard < ' a , T > {
146
+ #[ inline]
147
+ pub fn map < U : ?Sized > ( this : Self , f : impl FnOnce ( & T ) -> & U ) -> FreezeReadGuard < ' a , U > {
148
+ FreezeReadGuard { data : NonNull :: from ( f ( & * this) ) , _lock_guard : this. _lock_guard }
136
149
}
137
150
}
138
151
139
152
/// A guard holding mutable access to a `FreezeLock` which is in a locked state or frozen.
140
153
#[ must_use = "if unused the FreezeLock may immediately unlock" ]
141
- pub struct FreezeWriteGuard < ' a , T > {
154
+ pub struct FreezeWriteGuard < ' a , T : ? Sized > {
142
155
_lock_guard : WriteGuard < ' a , ( ) > ,
143
- lock : & ' a FreezeLock < T > ,
156
+ frozen : & ' a AtomicBool ,
157
+ data : NonNull < T > ,
144
158
marker : PhantomData < & ' a mut T > ,
145
159
}
146
160
147
161
impl < ' a , T > FreezeWriteGuard < ' a , T > {
148
162
pub fn freeze ( self ) -> & ' a T {
149
- self . lock . frozen . store ( true , Ordering :: Release ) ;
163
+ self . frozen . store ( true , Ordering :: Release ) ;
150
164
151
165
// SAFETY: This is frozen so the data cannot be modified and shared access is sound.
152
- unsafe { & * self . lock . data . get ( ) }
166
+ unsafe { & * self . data . as_ptr ( ) }
167
+ }
168
+ }
169
+
170
+ impl < ' a , T : ?Sized > FreezeWriteGuard < ' a , T > {
171
+ #[ inline]
172
+ pub fn map < U : ?Sized > (
173
+ mut this : Self ,
174
+ f : impl FnOnce ( & mut T ) -> & mut U ,
175
+ ) -> FreezeWriteGuard < ' a , U > {
176
+ FreezeWriteGuard {
177
+ data : NonNull :: from ( f ( & mut * this) ) ,
178
+ _lock_guard : this. _lock_guard ,
179
+ frozen : this. frozen ,
180
+ marker : PhantomData ,
181
+ }
153
182
}
154
183
}
155
184
156
- impl < ' a , T : ' a > Deref for FreezeWriteGuard < ' a , T > {
185
+ impl < ' a , T : ? Sized + ' a > Deref for FreezeWriteGuard < ' a , T > {
157
186
type Target = T ;
158
187
#[ inline]
159
188
fn deref ( & self ) -> & T {
160
189
// SAFETY: `self._lock_guard` holds the lock to the `UnsafeCell` so this has shared access.
161
- unsafe { & * self . lock . data . get ( ) }
190
+ unsafe { & * self . data . as_ptr ( ) }
162
191
}
163
192
}
164
193
165
- impl < ' a , T : ' a > DerefMut for FreezeWriteGuard < ' a , T > {
194
+ impl < ' a , T : ? Sized + ' a > DerefMut for FreezeWriteGuard < ' a , T > {
166
195
#[ inline]
167
196
fn deref_mut ( & mut self ) -> & mut T {
168
197
// SAFETY: `self._lock_guard` holds the lock to the `UnsafeCell` so this has mutable access.
169
- unsafe { & mut * self . lock . data . get ( ) }
198
+ unsafe { & mut * self . data . as_ptr ( ) }
170
199
}
171
200
}
0 commit comments