@@ -24,19 +24,24 @@ use sys_common::rwlock as sys;
24
24
/// of the underlying data (exclusive access) and the read portion of this lock
25
25
/// typically allows for read-only access (shared access).
26
26
///
27
+ /// In comparison, a [`Mutex`] does not distinguish between readers or writers
28
+ /// that aquire the lock, therefore blocking any threads waiting for the lock to
29
+ /// become available. An `RwLock` will allow any number of readers to aquire the
30
+ /// lock as long as a writer is not holding the lock.
31
+ ///
27
32
/// The priority policy of the lock is dependent on the underlying operating
28
33
/// system's implementation, and this type does not guarantee that any
29
34
/// particular policy will be used.
30
35
///
31
36
/// The type parameter `T` represents the data that this lock protects. It is
32
- /// required that `T` satisfies `Send` to be shared across threads and `Sync` to
33
- /// allow concurrent access through readers. The RAII guards returned from the
34
- /// locking methods implement `Deref` (and `DerefMut` for the `write` methods)
35
- /// to allow access to the contained of the lock.
37
+ /// required that `T` satisfies [ `Send`] to be shared across threads and
38
+ /// [`Sync`] to allow concurrent access through readers. The RAII guards
39
+ /// returned from the locking methods implement [ `Deref`][] (and [ `DerefMut`]
40
+ /// for the `write` methods) to allow access to the contained of the lock.
36
41
///
37
42
/// # Poisoning
38
43
///
39
- /// An `RwLock`, like `Mutex`, will become poisoned on a panic. Note, however,
44
+ /// An `RwLock`, like [ `Mutex`] , will become poisoned on a panic. Note, however,
40
45
/// that an `RwLock` may only be poisoned if a panic occurs while it is locked
41
46
/// exclusively (write mode). If a panic occurs in any reader, then the lock
42
47
/// will not be poisoned.
@@ -63,6 +68,12 @@ use sys_common::rwlock as sys;
63
68
/// assert_eq!(*w, 6);
64
69
/// } // write lock is dropped here
65
70
/// ```
71
+ ///
72
+ /// [`Deref`]: ../../std/ops/trait.Deref.html
73
+ /// [`DerefMut`]: ../../std/ops/trait.DerefMut.html
74
+ /// [`Send`]: ../../std/marker/trait.Send.html
75
+ /// [`Sync`]: ../../std/marker/trait.Sync.html
76
+ /// [`Mutex`]: struct.Mutex.html
66
77
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
67
78
pub struct RwLock < T : ?Sized > {
68
79
inner : Box < sys:: RWLock > ,
@@ -154,6 +165,24 @@ impl<T: ?Sized> RwLock<T> {
154
165
/// # Panics
155
166
///
156
167
/// This function might panic when called if the lock is already held by the current thread.
168
+ ///
169
+ /// # Examples
170
+ ///
171
+ /// ```
172
+ /// use std::sync::{Arc, RwLock};
173
+ /// use std::thread;
174
+ ///
175
+ /// let lock = Arc::new(RwLock::new(1));
176
+ /// let c_lock = lock.clone();
177
+ ///
178
+ /// let n = lock.read().unwrap();
179
+ /// assert_eq!(*n, 1);
180
+ ///
181
+ /// thread::spawn(move || {
182
+ /// let r = c_lock.read();
183
+ /// assert!(r.is_ok());
184
+ /// }).join().unwrap();
185
+ /// ```
157
186
#[ inline]
158
187
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
159
188
pub fn read ( & self ) -> LockResult < RwLockReadGuard < T > > {
@@ -180,6 +209,19 @@ impl<T: ?Sized> RwLock<T> {
180
209
/// is poisoned whenever a writer panics while holding an exclusive lock. An
181
210
/// error will only be returned if the lock would have otherwise been
182
211
/// acquired.
212
+ ///
213
+ /// # Examples
214
+ ///
215
+ /// ```
216
+ /// use std::sync::RwLock;
217
+ ///
218
+ /// let lock = RwLock::new(1);
219
+ ///
220
+ /// match lock.try_read() {
221
+ /// Ok(n) => assert_eq!(*n, 1),
222
+ /// Err(_) => unreachable!(),
223
+ /// };
224
+ /// ```
183
225
#[ inline]
184
226
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
185
227
pub fn try_read ( & self ) -> TryLockResult < RwLockReadGuard < T > > {
@@ -210,6 +252,19 @@ impl<T: ?Sized> RwLock<T> {
210
252
/// # Panics
211
253
///
212
254
/// This function might panic when called if the lock is already held by the current thread.
255
+ ///
256
+ /// # Examples
257
+ ///
258
+ /// ```
259
+ /// use std::sync::RwLock;
260
+ ///
261
+ /// let lock = RwLock::new(1);
262
+ ///
263
+ /// let mut n = lock.write().unwrap();
264
+ /// *n = 2;
265
+ ///
266
+ /// assert!(lock.try_read().is_err());
267
+ /// ```
213
268
#[ inline]
214
269
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
215
270
pub fn write ( & self ) -> LockResult < RwLockWriteGuard < T > > {
@@ -236,6 +291,19 @@ impl<T: ?Sized> RwLock<T> {
236
291
/// is poisoned whenever a writer panics while holding an exclusive lock. An
237
292
/// error will only be returned if the lock would have otherwise been
238
293
/// acquired.
294
+ ///
295
+ /// # Examples
296
+ ///
297
+ /// ```
298
+ /// use std::sync::RwLock;
299
+ ///
300
+ /// let lock = RwLock::new(1);
301
+ ///
302
+ /// let n = lock.read().unwrap();
303
+ /// assert_eq!(*n, 1);
304
+ ///
305
+ /// assert!(lock.try_write().is_err());
306
+ /// ```
239
307
#[ inline]
240
308
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
241
309
pub fn try_write ( & self ) -> TryLockResult < RwLockWriteGuard < T > > {
@@ -253,6 +321,22 @@ impl<T: ?Sized> RwLock<T> {
253
321
/// If another thread is active, the lock can still become poisoned at any
254
322
/// time. You should not trust a `false` value for program correctness
255
323
/// without additional synchronization.
324
+ ///
325
+ /// # Examples
326
+ ///
327
+ /// ```
328
+ /// use std::sync::{Arc, RwLock};
329
+ /// use std::thread;
330
+ ///
331
+ /// let lock = Arc::new(RwLock::new(0));
332
+ /// let c_lock = lock.clone();
333
+ ///
334
+ /// let _ = thread::spawn(move || {
335
+ /// let _lock = c_lock.write().unwrap();
336
+ /// panic!(); // the lock gets poisoned
337
+ /// }).join();
338
+ /// assert_eq!(lock.is_poisoned(), true);
339
+ /// ```
256
340
#[ inline]
257
341
#[ stable( feature = "sync_poison" , since = "1.2.0" ) ]
258
342
pub fn is_poisoned ( & self ) -> bool {
@@ -267,6 +351,19 @@ impl<T: ?Sized> RwLock<T> {
267
351
/// is poisoned whenever a writer panics while holding an exclusive lock. An
268
352
/// error will only be returned if the lock would have otherwise been
269
353
/// acquired.
354
+ ///
355
+ /// # Examples
356
+ ///
357
+ /// ```
358
+ /// use std::sync::RwLock;
359
+ ///
360
+ /// let lock = RwLock::new(String::new());
361
+ /// {
362
+ /// let mut s = lock.write().unwrap();
363
+ /// *s = "modified".to_owned();
364
+ /// }
365
+ /// assert_eq!(lock.into_inner().unwrap(), "modified");
366
+ /// ```
270
367
#[ stable( feature = "rwlock_into_inner" , since = "1.6.0" ) ]
271
368
pub fn into_inner ( self ) -> LockResult < T > where T : Sized {
272
369
// We know statically that there are no outstanding references to
@@ -282,7 +379,7 @@ impl<T: ?Sized> RwLock<T> {
282
379
( ptr:: read ( inner) , ptr:: read ( poison) , ptr:: read ( data) )
283
380
} ;
284
381
mem:: forget ( self ) ;
285
- inner. destroy ( ) ; // Keep in sync with the `Drop` impl.
382
+ inner. destroy ( ) ; // Keep in sync with the `Drop` impl.
286
383
drop ( inner) ;
287
384
288
385
poison:: map_result ( poison. borrow ( ) , |_| data. into_inner ( ) )
@@ -300,6 +397,16 @@ impl<T: ?Sized> RwLock<T> {
300
397
/// is poisoned whenever a writer panics while holding an exclusive lock. An
301
398
/// error will only be returned if the lock would have otherwise been
302
399
/// acquired.
400
+ ///
401
+ /// # Examples
402
+ ///
403
+ /// ```
404
+ /// use std::sync::RwLock;
405
+ ///
406
+ /// let mut lock = RwLock::new(0);
407
+ /// *lock.get_mut().unwrap() = 10;
408
+ /// assert_eq!(*lock.read().unwrap(), 10);
409
+ /// ```
303
410
#[ stable( feature = "rwlock_get_mut" , since = "1.6.0" ) ]
304
411
pub fn get_mut ( & mut self ) -> LockResult < & mut T > {
305
412
// We know statically that there are no other references to `self`, so
@@ -486,7 +593,7 @@ mod tests {
486
593
fn test_rw_arc_poison_wr ( ) {
487
594
let arc = Arc :: new ( RwLock :: new ( 1 ) ) ;
488
595
let arc2 = arc. clone ( ) ;
489
- let _: Result < ( ) , _ > = thread:: spawn ( move || {
596
+ let _: Result < ( ) , _ > = thread:: spawn ( move || {
490
597
let _lock = arc2. write ( ) . unwrap ( ) ;
491
598
panic ! ( ) ;
492
599
} ) . join ( ) ;
@@ -498,7 +605,7 @@ mod tests {
498
605
let arc = Arc :: new ( RwLock :: new ( 1 ) ) ;
499
606
assert ! ( !arc. is_poisoned( ) ) ;
500
607
let arc2 = arc. clone ( ) ;
501
- let _: Result < ( ) , _ > = thread:: spawn ( move || {
608
+ let _: Result < ( ) , _ > = thread:: spawn ( move || {
502
609
let _lock = arc2. write ( ) . unwrap ( ) ;
503
610
panic ! ( ) ;
504
611
} ) . join ( ) ;
@@ -510,7 +617,7 @@ mod tests {
510
617
fn test_rw_arc_no_poison_rr ( ) {
511
618
let arc = Arc :: new ( RwLock :: new ( 1 ) ) ;
512
619
let arc2 = arc. clone ( ) ;
513
- let _: Result < ( ) , _ > = thread:: spawn ( move || {
620
+ let _: Result < ( ) , _ > = thread:: spawn ( move || {
514
621
let _lock = arc2. read ( ) . unwrap ( ) ;
515
622
panic ! ( ) ;
516
623
} ) . join ( ) ;
@@ -521,7 +628,7 @@ mod tests {
521
628
fn test_rw_arc_no_poison_rw ( ) {
522
629
let arc = Arc :: new ( RwLock :: new ( 1 ) ) ;
523
630
let arc2 = arc. clone ( ) ;
524
- let _: Result < ( ) , _ > = thread:: spawn ( move || {
631
+ let _: Result < ( ) , _ > = thread:: spawn ( move || {
525
632
let _lock = arc2. read ( ) . unwrap ( ) ;
526
633
panic ! ( )
527
634
} ) . join ( ) ;
@@ -535,7 +642,7 @@ mod tests {
535
642
let arc2 = arc. clone ( ) ;
536
643
let ( tx, rx) = channel ( ) ;
537
644
538
- thread:: spawn ( move || {
645
+ thread:: spawn ( move || {
539
646
let mut lock = arc2. write ( ) . unwrap ( ) ;
540
647
for _ in 0 ..10 {
541
648
let tmp = * lock;
@@ -550,7 +657,7 @@ mod tests {
550
657
let mut children = Vec :: new ( ) ;
551
658
for _ in 0 ..5 {
552
659
let arc3 = arc. clone ( ) ;
553
- children. push ( thread:: spawn ( move || {
660
+ children. push ( thread:: spawn ( move || {
554
661
let lock = arc3. read ( ) . unwrap ( ) ;
555
662
assert ! ( * lock >= 0 ) ;
556
663
} ) ) ;
@@ -571,7 +678,7 @@ mod tests {
571
678
fn test_rw_arc_access_in_unwind ( ) {
572
679
let arc = Arc :: new ( RwLock :: new ( 1 ) ) ;
573
680
let arc2 = arc. clone ( ) ;
574
- let _ = thread:: spawn ( move || -> ( ) {
681
+ let _ = thread:: spawn ( move || -> ( ) {
575
682
struct Unwinder {
576
683
i : Arc < RwLock < isize > > ,
577
684
}
0 commit comments