@@ -38,6 +38,7 @@ impl<T: Sized> std::ops::Deref for PreemptibleRwLockReadGuard<'_, T> {
38
38
}
39
39
40
40
pub struct OwnedPreemptibleRwLockReadGuard < T : ?Sized , U : ?Sized = T > {
41
+ lock : Arc < PreemptibleRwLock < T > > ,
41
42
preemptor : watch:: Receiver < usize > ,
42
43
guard : OwnedRwLockReadGuard < T , U > ,
43
44
}
@@ -58,6 +59,7 @@ impl<T: ?Sized, U: ?Sized> OwnedPreemptibleRwLockReadGuard<T, U> {
58
59
F : FnOnce ( & U ) -> & V ,
59
60
{
60
61
OwnedPreemptibleRwLockReadGuard {
62
+ lock : self . lock ,
61
63
preemptor : self . preemptor ,
62
64
guard : OwnedRwLockReadGuard :: map ( self . guard , f) ,
63
65
}
@@ -106,7 +108,7 @@ impl<T: Sized> std::ops::DerefMut for PreemptibleRwLockWriteGuard<'_, T> {
106
108
/// readers get preempted, via `preempted()` method on the read guard that
107
109
/// readers can `tokio::select!` on.
108
110
#[ derive( Debug ) ]
109
- pub struct PreemptibleRwLock < T : Sized > {
111
+ pub struct PreemptibleRwLock < T : ? Sized > {
110
112
lock : Arc < RwLock < T > > ,
111
113
preemptor_lock : RwLock < ( ) > ,
112
114
// Used to track the number of writers waiting to acquire the lock and
@@ -134,6 +136,7 @@ impl<T: Sized> PreemptibleRwLock<T> {
134
136
pub async fn read_owned ( self : Arc < Self > ) -> OwnedPreemptibleRwLockReadGuard < T > {
135
137
let _guard = self . preemptor_lock . read ( ) . await ;
136
138
OwnedPreemptibleRwLockReadGuard {
139
+ lock : self . clone ( ) ,
137
140
preemptor : self . preemptor . 1 . clone ( ) ,
138
141
guard : self . lock . clone ( ) . read_owned ( ) . await ,
139
142
}
@@ -144,6 +147,7 @@ impl<T: Sized> PreemptibleRwLock<T> {
144
147
) -> Result < OwnedPreemptibleRwLockReadGuard < T > , TryLockError > {
145
148
let _guard = self . preemptor_lock . try_read ( ) ?;
146
149
Ok ( OwnedPreemptibleRwLockReadGuard {
150
+ lock : self . clone ( ) ,
147
151
preemptor : self . preemptor . 1 . clone ( ) ,
148
152
guard : self . lock . clone ( ) . try_read_owned ( ) ?,
149
153
} )
@@ -234,4 +238,25 @@ mod tests {
234
238
235
239
Ok ( ( ) )
236
240
}
241
+
242
+ #[ tokio:: test]
243
+ #[ allow( clippy:: disallowed_methods) ]
244
+ async fn test_preempt_owned_reader_after_lock_dropped ( ) -> Result < ( ) > {
245
+ let lock = Arc :: new ( PreemptibleRwLock :: new ( 42 ) ) ;
246
+
247
+ // Get an owned read guard
248
+ let reader = lock. clone ( ) . read_owned ( ) . await ;
249
+
250
+ // Drop the original Arc<PreemptibleRwLock>
251
+ drop ( lock) ;
252
+
253
+ // Verify that preempted() still works even after the original Arc is dropped
254
+ tokio:: select! {
255
+ biased; // Make sure peempted is checked first.
256
+ _ = reader. preempted( ) => assert!( false ) ,
257
+ _ = futures:: future:: ready( ( ) ) => ( ) ,
258
+ }
259
+
260
+ Ok ( ( ) )
261
+ }
237
262
}
0 commit comments