@@ -121,7 +121,7 @@ pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock::new();
121
121
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
122
122
pub struct RwLockReadGuard < ' a , T : ?Sized + ' a > {
123
123
__lock : & ' a StaticRwLock ,
124
- __data : & ' a UnsafeCell < T > ,
124
+ __data : & ' a T ,
125
125
}
126
126
127
127
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -417,10 +417,37 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
417
417
poison:: map_result ( lock. poison . borrow ( ) , |_| {
418
418
RwLockReadGuard {
419
419
__lock : lock,
420
- __data : data,
420
+ __data : unsafe { & * data. get ( ) } ,
421
421
}
422
422
} )
423
423
}
424
+
425
+ /// Transform this guard to hold a sub-borrow of the original data.
426
+ ///
427
+ /// Applies the supplied closure to the data, returning a new lock
428
+ /// guard referencing the borrow returned by the closure.
429
+ ///
430
+ /// ```rust
431
+ /// # use std::sync::{RwLockReadGuard, RwLock};
432
+ /// let x = RwLock::new(vec![1, 2]);
433
+ ///
434
+ /// let y = RwLockReadGuard::map(x.read().unwrap(), |v| &v[0]);
435
+ /// assert_eq!(*y, 1);
436
+ /// ```
437
+ #[ unstable( feature = "guard_map" ,
438
+ reason = "recently added, needs RFC for stabilization" ,
439
+ issue = "0" ) ]
440
+ pub fn map < U : ?Sized , F > ( this : Self , cb : F ) -> RwLockReadGuard < ' rwlock , U >
441
+ where F : FnOnce ( & ' rwlock T ) -> & ' rwlock U {
442
+ let new = RwLockReadGuard {
443
+ __lock : this. __lock ,
444
+ __data : cb ( this. __data )
445
+ } ;
446
+
447
+ mem:: forget ( this) ;
448
+
449
+ new
450
+ }
424
451
}
425
452
426
453
impl < ' rwlock , T : ?Sized > RwLockWriteGuard < ' rwlock , T > {
@@ -434,13 +461,52 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
434
461
}
435
462
} )
436
463
}
464
+
465
+ /// Transform this guard to hold a sub-borrow of the original data.
466
+ ///
467
+ /// Applies the supplied closure to the data, returning a new lock
468
+ /// guard referencing the borrow returned by the closure.
469
+ ///
470
+ /// ```rust
471
+ /// # use std::sync::{RwLockWriteGuard, RwLock};
472
+ /// let x = RwLock::new(vec![1, 2]);
473
+ ///
474
+ /// {
475
+ /// let y = RwLockWriteGuard::map(x.write().unwrap(), |v| &mut v[0]);
476
+ /// assert_eq!(*y, 1);
477
+ ///
478
+ /// *y = 10;
479
+ /// }
480
+ ///
481
+ /// assert_eq!(&**x.read().unwrap(), &[10, 2]);
482
+ /// ```
483
+ #[ unstable( feature = "guard_map" ,
484
+ reason = "recently added, needs RFC for stabilization" ,
485
+ issue = "0" ) ]
486
+ pub fn map < U : ?Sized , F > ( this : Self , cb : F ) -> RwLockWriteGuard < ' rwlock , U >
487
+ where F : FnOnce ( & ' rwlock mut T ) -> & ' rwlock mut U {
488
+ let new_data = unsafe {
489
+ let data: & ' rwlock mut T = & mut * this. __data . get ( ) ;
490
+ mem:: transmute :: < & ' rwlock mut U , & ' rwlock UnsafeCell < U > > ( cb ( data) )
491
+ } ;
492
+
493
+ let poison = unsafe { ptr:: read ( & this. __poison ) } ;
494
+ let lock = unsafe { ptr:: read ( & this. __lock ) } ;
495
+ mem:: forget ( this) ;
496
+
497
+ RwLockWriteGuard {
498
+ __lock : lock,
499
+ __data : new_data,
500
+ __poison : poison
501
+ }
502
+ }
437
503
}
438
504
439
505
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
440
506
impl < ' rwlock , T : ?Sized > Deref for RwLockReadGuard < ' rwlock , T > {
441
507
type Target = T ;
442
508
443
- fn deref ( & self ) -> & T { unsafe { & * self . __data . get ( ) } }
509
+ fn deref ( & self ) -> & T { self . __data }
444
510
}
445
511
446
512
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -481,7 +547,7 @@ mod tests {
481
547
use rand:: { self , Rng } ;
482
548
use sync:: mpsc:: channel;
483
549
use thread;
484
- use sync:: { Arc , RwLock , StaticRwLock , TryLockError } ;
550
+ use sync:: { Arc , RwLock , StaticRwLock , TryLockError , RwLockWriteGuard } ;
485
551
use sync:: atomic:: { AtomicUsize , Ordering } ;
486
552
487
553
#[ derive( Eq , PartialEq , Debug ) ]
@@ -729,4 +795,20 @@ mod tests {
729
795
Ok ( x) => panic ! ( "get_mut of poisoned RwLock is Ok: {:?}" , x) ,
730
796
}
731
797
}
798
+
799
+ #[ test]
800
+ fn test_rwlock_write_map_poison ( ) {
801
+ let rwlock = Arc :: new ( RwLock :: new ( vec ! [ 1 , 2 ] ) ) ;
802
+ let rwlock2 = rwlock. clone ( ) ;
803
+
804
+ thread:: spawn ( move || {
805
+ let _ = RwLockWriteGuard :: map :: < usize , _ > ( rwlock2. write ( ) . unwrap ( ) , |_| panic ! ( ) ) ;
806
+ } ) . join ( ) . unwrap_err ( ) ;
807
+
808
+ match rwlock. read ( ) {
809
+ Ok ( r) => panic ! ( "Read lock on poisioned RwLock is Ok: {:?}" , & * r) ,
810
+ Err ( _) => { }
811
+ } ;
812
+ }
732
813
}
814
+
0 commit comments