1#[cfg(all(test, not(target_os = "emscripten")))]
2mod tests;
3
4use crate::cell::UnsafeCell;
5use crate::fmt;
6use crate::marker::PhantomData;
7use crate::mem::ManuallyDrop;
8use crate::ops::{Deref, DerefMut};
9use crate::ptr::NonNull;
10use crate::sync::{poison, LockResult, TryLockError, TryLockResult};
11use crate::sys::sync as sys;
12
13/// A reader-writer lock
14///
15/// This type of lock allows a number of readers or at most one writer at any
16/// point in time. The write portion of this lock typically allows modification
17/// of the underlying data (exclusive access) and the read portion of this lock
18/// typically allows for read-only access (shared access).
19///
20/// In comparison, a [`Mutex`] does not distinguish between readers or writers
21/// that acquire the lock, therefore blocking any threads waiting for the lock to
22/// become available. An `RwLock` will allow any number of readers to acquire the
23/// lock as long as a writer is not holding the lock.
24///
25/// The priority policy of the lock is dependent on the underlying operating
26/// system's implementation, and this type does not guarantee that any
27/// particular policy will be used. In particular, a writer which is waiting to
28/// acquire the lock in `write` might or might not block concurrent calls to
29/// `read`, e.g.:
30///
31/// <details><summary>Potential deadlock example</summary>
32///
33/// ```text
34/// // Thread 1 | // Thread 2
35/// let _rg1 = lock.read(); |
36/// | // will block
37/// | let _wg = lock.write();
38/// // may deadlock |
39/// let _rg2 = lock.read(); |
40/// ```
41///
42/// </details>
43///
44/// The type parameter `T` represents the data that this lock protects. It is
45/// required that `T` satisfies [`Send`] to be shared across threads and
46/// [`Sync`] to allow concurrent access through readers. The RAII guards
47/// returned from the locking methods implement [`Deref`] (and [`DerefMut`]
48/// for the `write` methods) to allow access to the content of the lock.
49///
50/// # Poisoning
51///
52/// An `RwLock`, like [`Mutex`], will become poisoned on a panic. Note, however,
53/// that an `RwLock` may only be poisoned if a panic occurs while it is locked
54/// exclusively (write mode). If a panic occurs in any reader, then the lock
55/// will not be poisoned.
56///
57/// # Examples
58///
59/// ```
60/// use std::sync::RwLock;
61///
62/// let lock = RwLock::new(5);
63///
64/// // many reader locks can be held at once
65/// {
66/// let r1 = lock.read().unwrap();
67/// let r2 = lock.read().unwrap();
68/// assert_eq!(*r1, 5);
69/// assert_eq!(*r2, 5);
70/// } // read locks are dropped at this point
71///
72/// // only one write lock may be held, however
73/// {
74/// let mut w = lock.write().unwrap();
75/// *w += 1;
76/// assert_eq!(*w, 6);
77/// } // write lock is dropped here
78/// ```
79///
80/// [`Mutex`]: super::Mutex
81#[stable(feature = "rust1", since = "1.0.0")]
82#[cfg_attr(not(test), rustc_diagnostic_item = "RwLock")]
83pub struct RwLock<T: ?Sized> {
84 inner: sys::RwLock,
85 poison: poison::Flag,
86 data: UnsafeCell<T>,
87}
88
89#[stable(feature = "rust1", since = "1.0.0")]
90unsafe impl<T: ?Sized + Send> Send for RwLock<T> {}
91#[stable(feature = "rust1", since = "1.0.0")]
92unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
93
94/// RAII structure used to release the shared read access of a lock when
95/// dropped.
96///
97/// This structure is created by the [`read`] and [`try_read`] methods on
98/// [`RwLock`].
99///
100/// [`read`]: RwLock::read
101/// [`try_read`]: RwLock::try_read
102#[must_use = "if unused the RwLock will immediately unlock"]
103#[must_not_suspend = "holding a RwLockReadGuard across suspend \
104 points can cause deadlocks, delays, \
105 and cause Futures to not implement `Send`"]
106#[stable(feature = "rust1", since = "1.0.0")]
107#[clippy::has_significant_drop]
108#[cfg_attr(not(test), rustc_diagnostic_item = "RwLockReadGuard")]
109pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
110 // NB: we use a pointer instead of `&'a T` to avoid `noalias` violations, because a
111 // `RwLockReadGuard` argument doesn't hold immutability for its whole scope, only until it drops.
112 // `NonNull` is also covariant over `T`, just like we would have with `&T`. `NonNull`
113 // is preferable over `const* T` to allow for niche optimization.
114 data: NonNull<T>,
115 inner_lock: &'a sys::RwLock,
116}
117
118#[stable(feature = "rust1", since = "1.0.0")]
119impl<T: ?Sized> !Send for RwLockReadGuard<'_, T> {}
120
121#[stable(feature = "rwlock_guard_sync", since = "1.23.0")]
122unsafe impl<T: ?Sized + Sync> Sync for RwLockReadGuard<'_, T> {}
123
124/// RAII structure used to release the exclusive write access of a lock when
125/// dropped.
126///
127/// This structure is created by the [`write`] and [`try_write`] methods
128/// on [`RwLock`].
129///
130/// [`write`]: RwLock::write
131/// [`try_write`]: RwLock::try_write
132#[must_use = "if unused the RwLock will immediately unlock"]
133#[must_not_suspend = "holding a RwLockWriteGuard across suspend \
134 points can cause deadlocks, delays, \
135 and cause Future's to not implement `Send`"]
136#[stable(feature = "rust1", since = "1.0.0")]
137#[clippy::has_significant_drop]
138#[cfg_attr(not(test), rustc_diagnostic_item = "RwLockWriteGuard")]
139pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
140 lock: &'a RwLock<T>,
141 poison: poison::Guard,
142}
143
144#[stable(feature = "rust1", since = "1.0.0")]
145impl<T: ?Sized> !Send for RwLockWriteGuard<'_, T> {}
146
147#[stable(feature = "rwlock_guard_sync", since = "1.23.0")]
148unsafe impl<T: ?Sized + Sync> Sync for RwLockWriteGuard<'_, T> {}
149
150/// RAII structure used to release the shared read access of a lock when
151/// dropped, which can point to a subfield of the protected data.
152///
153/// This structure is created by the [`map`] and [`try_map`] methods
154/// on [`RwLockReadGuard`].
155///
156/// [`map`]: RwLockReadGuard::map
157/// [`try_map`]: RwLockReadGuard::try_map
158#[must_use = "if unused the RwLock will immediately unlock"]
159#[must_not_suspend = "holding a MappedRwLockReadGuard across suspend \
160 points can cause deadlocks, delays, \
161 and cause Futures to not implement `Send`"]
162#[unstable(feature = "mapped_lock_guards", issue = "117108")]
163#[clippy::has_significant_drop]
164pub struct MappedRwLockReadGuard<'a, T: ?Sized + 'a> {
165 // NB: we use a pointer instead of `&'a T` to avoid `noalias` violations, because a
166 // `MappedRwLockReadGuard` argument doesn't hold immutability for its whole scope, only until it drops.
167 // `NonNull` is also covariant over `T`, just like we would have with `&T`. `NonNull`
168 // is preferable over `const* T` to allow for niche optimization.
169 data: NonNull<T>,
170 inner_lock: &'a sys::RwLock,
171}
172
173#[unstable(feature = "mapped_lock_guards", issue = "117108")]
174impl<T: ?Sized> !Send for MappedRwLockReadGuard<'_, T> {}
175
176#[unstable(feature = "mapped_lock_guards", issue = "117108")]
177unsafe impl<T: ?Sized + Sync> Sync for MappedRwLockReadGuard<'_, T> {}
178
179/// RAII structure used to release the exclusive write access of a lock when
180/// dropped, which can point to a subfield of the protected data.
181///
182/// This structure is created by the [`map`] and [`try_map`] methods
183/// on [`RwLockWriteGuard`].
184///
185/// [`map`]: RwLockWriteGuard::map
186/// [`try_map`]: RwLockWriteGuard::try_map
187#[must_use = "if unused the RwLock will immediately unlock"]
188#[must_not_suspend = "holding a MappedRwLockWriteGuard across suspend \
189 points can cause deadlocks, delays, \
190 and cause Future's to not implement `Send`"]
191#[unstable(feature = "mapped_lock_guards", issue = "117108")]
192#[clippy::has_significant_drop]
193pub struct MappedRwLockWriteGuard<'a, T: ?Sized + 'a> {
194 // NB: we use a pointer instead of `&'a mut T` to avoid `noalias` violations, because a
195 // `MappedRwLockWriteGuard` argument doesn't hold uniqueness for its whole scope, only until it drops.
196 // `NonNull` is covariant over `T`, so we add a `PhantomData<&'a mut T>` field
197 // below for the correct variance over `T` (invariance).
198 data: NonNull<T>,
199 inner_lock: &'a sys::RwLock,
200 poison_flag: &'a poison::Flag,
201 poison: poison::Guard,
202 _variance: PhantomData<&'a mut T>,
203}
204
205#[unstable(feature = "mapped_lock_guards", issue = "117108")]
206impl<T: ?Sized> !Send for MappedRwLockWriteGuard<'_, T> {}
207
208#[unstable(feature = "mapped_lock_guards", issue = "117108")]
209unsafe impl<T: ?Sized + Sync> Sync for MappedRwLockWriteGuard<'_, T> {}
210
211impl<T> RwLock<T> {
212 /// Creates a new instance of an `RwLock<T>` which is unlocked.
213 ///
214 /// # Examples
215 ///
216 /// ```
217 /// use std::sync::RwLock;
218 ///
219 /// let lock = RwLock::new(5);
220 /// ```
221 #[stable(feature = "rust1", since = "1.0.0")]
222 #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
223 #[inline]
224 pub const fn new(t: T) -> RwLock<T> {
225 RwLock { inner: sys::RwLock::new(), poison: poison::Flag::new(), data: UnsafeCell::new(t) }
226 }
227}
228
229impl<T: ?Sized> RwLock<T> {
230 /// Locks this `RwLock` with shared read access, blocking the current thread
231 /// until it can be acquired.
232 ///
233 /// The calling thread will be blocked until there are no more writers which
234 /// hold the lock. There may be other readers currently inside the lock when
235 /// this method returns. This method does not provide any guarantees with
236 /// respect to the ordering of whether contentious readers or writers will
237 /// acquire the lock first.
238 ///
239 /// Returns an RAII guard which will release this thread's shared access
240 /// once it is dropped.
241 ///
242 /// # Errors
243 ///
244 /// This function will return an error if the `RwLock` is poisoned. An
245 /// `RwLock` is poisoned whenever a writer panics while holding an exclusive
246 /// lock. The failure will occur immediately after the lock has been
247 /// acquired.
248 ///
249 /// # Panics
250 ///
251 /// This function might panic when called if the lock is already held by the current thread.
252 ///
253 /// # Examples
254 ///
255 /// ```
256 /// use std::sync::{Arc, RwLock};
257 /// use std::thread;
258 ///
259 /// let lock = Arc::new(RwLock::new(1));
260 /// let c_lock = Arc::clone(&lock);
261 ///
262 /// let n = lock.read().unwrap();
263 /// assert_eq!(*n, 1);
264 ///
265 /// thread::spawn(move || {
266 /// let r = c_lock.read();
267 /// assert!(r.is_ok());
268 /// }).join().unwrap();
269 /// ```
270 #[inline]
271 #[stable(feature = "rust1", since = "1.0.0")]
272 pub fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> {
273 unsafe {
274 self.inner.read();
275 RwLockReadGuard::new(self)
276 }
277 }
278
279 /// Attempts to acquire this `RwLock` with shared read access.
280 ///
281 /// If the access could not be granted at this time, then `Err` is returned.
282 /// Otherwise, an RAII guard is returned which will release the shared access
283 /// when it is dropped.
284 ///
285 /// This function does not block.
286 ///
287 /// This function does not provide any guarantees with respect to the ordering
288 /// of whether contentious readers or writers will acquire the lock first.
289 ///
290 /// # Errors
291 ///
292 /// This function will return the [`Poisoned`] error if the `RwLock` is
293 /// poisoned. An `RwLock` is poisoned whenever a writer panics while holding
294 /// an exclusive lock. `Poisoned` will only be returned if the lock would
295 /// have otherwise been acquired.
296 ///
297 /// This function will return the [`WouldBlock`] error if the `RwLock` could
298 /// not be acquired because it was already locked exclusively.
299 ///
300 /// [`Poisoned`]: TryLockError::Poisoned
301 /// [`WouldBlock`]: TryLockError::WouldBlock
302 ///
303 /// # Examples
304 ///
305 /// ```
306 /// use std::sync::RwLock;
307 ///
308 /// let lock = RwLock::new(1);
309 ///
310 /// match lock.try_read() {
311 /// Ok(n) => assert_eq!(*n, 1),
312 /// Err(_) => unreachable!(),
313 /// };
314 /// ```
315 #[inline]
316 #[stable(feature = "rust1", since = "1.0.0")]
317 pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'_, T>> {
318 unsafe {
319 if self.inner.try_read() {
320 Ok(RwLockReadGuard::new(self)?)
321 } else {
322 Err(TryLockError::WouldBlock)
323 }
324 }
325 }
326
327 /// Locks this `RwLock` with exclusive write access, blocking the current
328 /// thread until it can be acquired.
329 ///
330 /// This function will not return while other writers or other readers
331 /// currently have access to the lock.
332 ///
333 /// Returns an RAII guard which will drop the write access of this `RwLock`
334 /// when dropped.
335 ///
336 /// # Errors
337 ///
338 /// This function will return an error if the `RwLock` is poisoned. An
339 /// `RwLock` is poisoned whenever a writer panics while holding an exclusive
340 /// lock. An error will be returned when the lock is acquired.
341 ///
342 /// # Panics
343 ///
344 /// This function might panic when called if the lock is already held by the current thread.
345 ///
346 /// # Examples
347 ///
348 /// ```
349 /// use std::sync::RwLock;
350 ///
351 /// let lock = RwLock::new(1);
352 ///
353 /// let mut n = lock.write().unwrap();
354 /// *n = 2;
355 ///
356 /// assert!(lock.try_read().is_err());
357 /// ```
358 #[inline]
359 #[stable(feature = "rust1", since = "1.0.0")]
360 pub fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>> {
361 unsafe {
362 self.inner.write();
363 RwLockWriteGuard::new(self)
364 }
365 }
366
367 /// Attempts to lock this `RwLock` with exclusive write access.
368 ///
369 /// If the lock could not be acquired at this time, then `Err` is returned.
370 /// Otherwise, an RAII guard is returned which will release the lock when
371 /// it is dropped.
372 ///
373 /// This function does not block.
374 ///
375 /// This function does not provide any guarantees with respect to the ordering
376 /// of whether contentious readers or writers will acquire the lock first.
377 ///
378 /// # Errors
379 ///
380 /// This function will return the [`Poisoned`] error if the `RwLock` is
381 /// poisoned. An `RwLock` is poisoned whenever a writer panics while holding
382 /// an exclusive lock. `Poisoned` will only be returned if the lock would
383 /// have otherwise been acquired.
384 ///
385 /// This function will return the [`WouldBlock`] error if the `RwLock` could
386 /// not be acquired because it was already locked exclusively.
387 ///
388 /// [`Poisoned`]: TryLockError::Poisoned
389 /// [`WouldBlock`]: TryLockError::WouldBlock
390 ///
391 ///
392 /// # Examples
393 ///
394 /// ```
395 /// use std::sync::RwLock;
396 ///
397 /// let lock = RwLock::new(1);
398 ///
399 /// let n = lock.read().unwrap();
400 /// assert_eq!(*n, 1);
401 ///
402 /// assert!(lock.try_write().is_err());
403 /// ```
404 #[inline]
405 #[stable(feature = "rust1", since = "1.0.0")]
406 pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>> {
407 unsafe {
408 if self.inner.try_write() {
409 Ok(RwLockWriteGuard::new(self)?)
410 } else {
411 Err(TryLockError::WouldBlock)
412 }
413 }
414 }
415
416 /// Determines whether the lock is poisoned.
417 ///
418 /// If another thread is active, the lock can still become poisoned at any
419 /// time. You should not trust a `false` value for program correctness
420 /// without additional synchronization.
421 ///
422 /// # Examples
423 ///
424 /// ```
425 /// use std::sync::{Arc, RwLock};
426 /// use std::thread;
427 ///
428 /// let lock = Arc::new(RwLock::new(0));
429 /// let c_lock = Arc::clone(&lock);
430 ///
431 /// let _ = thread::spawn(move || {
432 /// let _lock = c_lock.write().unwrap();
433 /// panic!(); // the lock gets poisoned
434 /// }).join();
435 /// assert_eq!(lock.is_poisoned(), true);
436 /// ```
437 #[inline]
438 #[stable(feature = "sync_poison", since = "1.2.0")]
439 pub fn is_poisoned(&self) -> bool {
440 self.poison.get()
441 }
442
443 /// Clear the poisoned state from a lock.
444 ///
445 /// If the lock is poisoned, it will remain poisoned until this function is called. This allows
446 /// recovering from a poisoned state and marking that it has recovered. For example, if the
447 /// value is overwritten by a known-good value, then the lock can be marked as un-poisoned. Or
448 /// possibly, the value could be inspected to determine if it is in a consistent state, and if
449 /// so the poison is removed.
450 ///
451 /// # Examples
452 ///
453 /// ```
454 /// use std::sync::{Arc, RwLock};
455 /// use std::thread;
456 ///
457 /// let lock = Arc::new(RwLock::new(0));
458 /// let c_lock = Arc::clone(&lock);
459 ///
460 /// let _ = thread::spawn(move || {
461 /// let _lock = c_lock.write().unwrap();
462 /// panic!(); // the lock gets poisoned
463 /// }).join();
464 ///
465 /// assert_eq!(lock.is_poisoned(), true);
466 /// let guard = lock.write().unwrap_or_else(|mut e| {
467 /// **e.get_mut() = 1;
468 /// lock.clear_poison();
469 /// e.into_inner()
470 /// });
471 /// assert_eq!(lock.is_poisoned(), false);
472 /// assert_eq!(*guard, 1);
473 /// ```
474 #[inline]
475 #[stable(feature = "mutex_unpoison", since = "1.77.0")]
476 pub fn clear_poison(&self) {
477 self.poison.clear();
478 }
479
480 /// Consumes this `RwLock`, returning the underlying data.
481 ///
482 /// # Errors
483 ///
484 /// This function will return an error if the `RwLock` is poisoned. An
485 /// `RwLock` is poisoned whenever a writer panics while holding an exclusive
486 /// lock. An error will only be returned if the lock would have otherwise
487 /// been acquired.
488 ///
489 /// # Examples
490 ///
491 /// ```
492 /// use std::sync::RwLock;
493 ///
494 /// let lock = RwLock::new(String::new());
495 /// {
496 /// let mut s = lock.write().unwrap();
497 /// *s = "modified".to_owned();
498 /// }
499 /// assert_eq!(lock.into_inner().unwrap(), "modified");
500 /// ```
501 #[stable(feature = "rwlock_into_inner", since = "1.6.0")]
502 pub fn into_inner(self) -> LockResult<T>
503 where
504 T: Sized,
505 {
506 let data = self.data.into_inner();
507 poison::map_result(self.poison.borrow(), |()| data)
508 }
509
510 /// Returns a mutable reference to the underlying data.
511 ///
512 /// Since this call borrows the `RwLock` mutably, no actual locking needs to
513 /// take place -- the mutable borrow statically guarantees no locks exist.
514 ///
515 /// # Errors
516 ///
517 /// This function will return an error if the `RwLock` is poisoned. An
518 /// `RwLock` is poisoned whenever a writer panics while holding an exclusive
519 /// lock. An error will only be returned if the lock would have otherwise
520 /// been acquired.
521 ///
522 /// # Examples
523 ///
524 /// ```
525 /// use std::sync::RwLock;
526 ///
527 /// let mut lock = RwLock::new(0);
528 /// *lock.get_mut().unwrap() = 10;
529 /// assert_eq!(*lock.read().unwrap(), 10);
530 /// ```
531 #[stable(feature = "rwlock_get_mut", since = "1.6.0")]
532 pub fn get_mut(&mut self) -> LockResult<&mut T> {
533 let data = self.data.get_mut();
534 poison::map_result(self.poison.borrow(), |()| data)
535 }
536}
537
538#[stable(feature = "rust1", since = "1.0.0")]
539impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
540 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
541 let mut d: DebugStruct<'_, '_> = f.debug_struct(name:"RwLock");
542 match self.try_read() {
543 Ok(guard: RwLockReadGuard<'_, T>) => {
544 d.field(name:"data", &&*guard);
545 }
546 Err(TryLockError::Poisoned(err: PoisonError>)) => {
547 d.field(name:"data", &&**err.get_ref());
548 }
549 Err(TryLockError::WouldBlock) => {
550 d.field(name:"data", &format_args!("<locked>"));
551 }
552 }
553 d.field(name:"poisoned", &self.poison.get());
554 d.finish_non_exhaustive()
555 }
556}
557
558#[stable(feature = "rw_lock_default", since = "1.10.0")]
559impl<T: Default> Default for RwLock<T> {
560 /// Creates a new `RwLock<T>`, with the `Default` value for T.
561 fn default() -> RwLock<T> {
562 RwLock::new(Default::default())
563 }
564}
565
566#[stable(feature = "rw_lock_from", since = "1.24.0")]
567impl<T> From<T> for RwLock<T> {
568 /// Creates a new instance of an `RwLock<T>` which is unlocked.
569 /// This is equivalent to [`RwLock::new`].
570 fn from(t: T) -> Self {
571 RwLock::new(t)
572 }
573}
574
575impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
576 /// Create a new instance of `RwLockReadGuard<T>` from a `RwLock<T>`.
577 // SAFETY: if and only if `lock.inner.read()` (or `lock.inner.try_read()`) has been
578 // successfully called from the same thread before instantiating this object.
579 unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockReadGuard<'rwlock, T>> {
580 poison::map_result(result:lock.poison.borrow(), |()| RwLockReadGuard {
581 data: NonNull::new_unchecked(ptr:lock.data.get()),
582 inner_lock: &lock.inner,
583 })
584 }
585}
586
587impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
588 /// Create a new instance of `RwLockWriteGuard<T>` from a `RwLock<T>`.
589 // SAFETY: if and only if `lock.inner.write()` (or `lock.inner.try_write()`) has been
590 // successfully called from the same thread before instantiating this object.
591 unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockWriteGuard<'rwlock, T>> {
592 poison::map_result(result:lock.poison.guard(), |guard: Guard| RwLockWriteGuard { lock, poison: guard })
593 }
594}
595
596#[stable(feature = "std_debug", since = "1.16.0")]
597impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> {
598 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
599 (**self).fmt(f)
600 }
601}
602
603#[stable(feature = "std_guard_impls", since = "1.20.0")]
604impl<T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'_, T> {
605 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
606 (**self).fmt(f)
607 }
608}
609
610#[stable(feature = "std_debug", since = "1.16.0")]
611impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> {
612 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
613 (**self).fmt(f)
614 }
615}
616
617#[stable(feature = "std_guard_impls", since = "1.20.0")]
618impl<T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'_, T> {
619 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
620 (**self).fmt(f)
621 }
622}
623
624#[unstable(feature = "mapped_lock_guards", issue = "117108")]
625impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockReadGuard<'_, T> {
626 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
627 (**self).fmt(f)
628 }
629}
630
631#[unstable(feature = "mapped_lock_guards", issue = "117108")]
632impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockReadGuard<'_, T> {
633 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
634 (**self).fmt(f)
635 }
636}
637
638#[unstable(feature = "mapped_lock_guards", issue = "117108")]
639impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockWriteGuard<'_, T> {
640 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
641 (**self).fmt(f)
642 }
643}
644
645#[unstable(feature = "mapped_lock_guards", issue = "117108")]
646impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockWriteGuard<'_, T> {
647 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
648 (**self).fmt(f)
649 }
650}
651
652#[stable(feature = "rust1", since = "1.0.0")]
653impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
654 type Target = T;
655
656 fn deref(&self) -> &T {
657 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
658 unsafe { self.data.as_ref() }
659 }
660}
661
662#[stable(feature = "rust1", since = "1.0.0")]
663impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
664 type Target = T;
665
666 fn deref(&self) -> &T {
667 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
668 unsafe { &*self.lock.data.get() }
669 }
670}
671
672#[stable(feature = "rust1", since = "1.0.0")]
673impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
674 fn deref_mut(&mut self) -> &mut T {
675 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
676 unsafe { &mut *self.lock.data.get() }
677 }
678}
679
680#[unstable(feature = "mapped_lock_guards", issue = "117108")]
681impl<T: ?Sized> Deref for MappedRwLockReadGuard<'_, T> {
682 type Target = T;
683
684 fn deref(&self) -> &T {
685 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
686 // was created, and have been upheld throughout `map` and/or `try_map`.
687 unsafe { self.data.as_ref() }
688 }
689}
690
691#[unstable(feature = "mapped_lock_guards", issue = "117108")]
692impl<T: ?Sized> Deref for MappedRwLockWriteGuard<'_, T> {
693 type Target = T;
694
695 fn deref(&self) -> &T {
696 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
697 // was created, and have been upheld throughout `map` and/or `try_map`.
698 unsafe { self.data.as_ref() }
699 }
700}
701
702#[unstable(feature = "mapped_lock_guards", issue = "117108")]
703impl<T: ?Sized> DerefMut for MappedRwLockWriteGuard<'_, T> {
704 fn deref_mut(&mut self) -> &mut T {
705 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
706 // was created, and have been upheld throughout `map` and/or `try_map`.
707 unsafe { self.data.as_mut() }
708 }
709}
710
711#[stable(feature = "rust1", since = "1.0.0")]
712impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
713 fn drop(&mut self) {
714 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
715 unsafe {
716 self.inner_lock.read_unlock();
717 }
718 }
719}
720
721#[stable(feature = "rust1", since = "1.0.0")]
722impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
723 fn drop(&mut self) {
724 self.lock.poison.done(&self.poison);
725 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
726 unsafe {
727 self.lock.inner.write_unlock();
728 }
729 }
730}
731
732#[unstable(feature = "mapped_lock_guards", issue = "117108")]
733impl<T: ?Sized> Drop for MappedRwLockReadGuard<'_, T> {
734 fn drop(&mut self) {
735 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
736 // was created, and have been upheld throughout `map` and/or `try_map`.
737 unsafe {
738 self.inner_lock.read_unlock();
739 }
740 }
741}
742
743#[unstable(feature = "mapped_lock_guards", issue = "117108")]
744impl<T: ?Sized> Drop for MappedRwLockWriteGuard<'_, T> {
745 fn drop(&mut self) {
746 self.poison_flag.done(&self.poison);
747 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
748 // was created, and have been upheld throughout `map` and/or `try_map`.
749 unsafe {
750 self.inner_lock.write_unlock();
751 }
752 }
753}
754
755impl<'a, T: ?Sized> RwLockReadGuard<'a, T> {
756 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data, e.g.
757 /// an enum variant.
758 ///
759 /// The `RwLock` is already locked for reading, so this cannot fail.
760 ///
761 /// This is an associated function that needs to be used as
762 /// `RwLockReadGuard::map(...)`. A method would interfere with methods of
763 /// the same name on the contents of the `RwLockReadGuard` used through
764 /// `Deref`.
765 ///
766 /// # Panics
767 ///
768 /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will not be poisoned.
769 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
770 pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'a, U>
771 where
772 F: FnOnce(&T) -> &U,
773 U: ?Sized,
774 {
775 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
776 // was created, and have been upheld throughout `map` and/or `try_map`.
777 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
778 // passed to it. If the closure panics, the guard will be dropped.
779 let data = NonNull::from(f(unsafe { orig.data.as_ref() }));
780 let orig = ManuallyDrop::new(orig);
781 MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }
782 }
783
784 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data. The
785 /// original guard is returned as an `Err(...)` if the closure returns
786 /// `None`.
787 ///
788 /// The `RwLock` is already locked for reading, so this cannot fail.
789 ///
790 /// This is an associated function that needs to be used as
791 /// `RwLockReadGuard::try_map(...)`. A method would interfere with methods
792 /// of the same name on the contents of the `RwLockReadGuard` used through
793 /// `Deref`.
794 ///
795 /// # Panics
796 ///
797 /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will not be poisoned.
798 #[doc(alias = "filter_map")]
799 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
800 pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'a, U>, Self>
801 where
802 F: FnOnce(&T) -> Option<&U>,
803 U: ?Sized,
804 {
805 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
806 // was created, and have been upheld throughout `map` and/or `try_map`.
807 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
808 // passed to it. If the closure panics, the guard will be dropped.
809 match f(unsafe { orig.data.as_ref() }) {
810 Some(data) => {
811 let data = NonNull::from(data);
812 let orig = ManuallyDrop::new(orig);
813 Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock })
814 }
815 None => Err(orig),
816 }
817 }
818}
819
820impl<'a, T: ?Sized> MappedRwLockReadGuard<'a, T> {
821 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data,
822 /// e.g. an enum variant.
823 ///
824 /// The `RwLock` is already locked for reading, so this cannot fail.
825 ///
826 /// This is an associated function that needs to be used as
827 /// `MappedRwLockReadGuard::map(...)`. A method would interfere with
828 /// methods of the same name on the contents of the `MappedRwLockReadGuard`
829 /// used through `Deref`.
830 ///
831 /// # Panics
832 ///
833 /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will not be poisoned.
834 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
835 pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'a, U>
836 where
837 F: FnOnce(&T) -> &U,
838 U: ?Sized,
839 {
840 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
841 // was created, and have been upheld throughout `map` and/or `try_map`.
842 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
843 // passed to it. If the closure panics, the guard will be dropped.
844 let data = NonNull::from(f(unsafe { orig.data.as_ref() }));
845 let orig = ManuallyDrop::new(orig);
846 MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }
847 }
848
849 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data.
850 /// The original guard is returned as an `Err(...)` if the closure returns
851 /// `None`.
852 ///
853 /// The `RwLock` is already locked for reading, so this cannot fail.
854 ///
855 /// This is an associated function that needs to be used as
856 /// `MappedRwLockReadGuard::try_map(...)`. A method would interfere with
857 /// methods of the same name on the contents of the `MappedRwLockReadGuard`
858 /// used through `Deref`.
859 ///
860 /// # Panics
861 ///
862 /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will not be poisoned.
863 #[doc(alias = "filter_map")]
864 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
865 pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'a, U>, Self>
866 where
867 F: FnOnce(&T) -> Option<&U>,
868 U: ?Sized,
869 {
870 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
871 // was created, and have been upheld throughout `map` and/or `try_map`.
872 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
873 // passed to it. If the closure panics, the guard will be dropped.
874 match f(unsafe { orig.data.as_ref() }) {
875 Some(data) => {
876 let data = NonNull::from(data);
877 let orig = ManuallyDrop::new(orig);
878 Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock })
879 }
880 None => Err(orig),
881 }
882 }
883}
884
885impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> {
886 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data, e.g.
887 /// an enum variant.
888 ///
889 /// The `RwLock` is already locked for writing, so this cannot fail.
890 ///
891 /// This is an associated function that needs to be used as
892 /// `RwLockWriteGuard::map(...)`. A method would interfere with methods of
893 /// the same name on the contents of the `RwLockWriteGuard` used through
894 /// `Deref`.
895 ///
896 /// # Panics
897 ///
898 /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will be poisoned.
899 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
900 pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockWriteGuard<'a, U>
901 where
902 F: FnOnce(&mut T) -> &mut U,
903 U: ?Sized,
904 {
905 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
906 // was created, and have been upheld throughout `map` and/or `try_map`.
907 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
908 // passed to it. If the closure panics, the guard will be dropped.
909 let data = NonNull::from(f(unsafe { &mut *orig.lock.data.get() }));
910 let orig = ManuallyDrop::new(orig);
911 MappedRwLockWriteGuard {
912 data,
913 inner_lock: &orig.lock.inner,
914 poison_flag: &orig.lock.poison,
915 poison: orig.poison.clone(),
916 _variance: PhantomData,
917 }
918 }
919
920 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data. The
921 /// original guard is returned as an `Err(...)` if the closure returns
922 /// `None`.
923 ///
924 /// The `RwLock` is already locked for writing, so this cannot fail.
925 ///
926 /// This is an associated function that needs to be used as
927 /// `RwLockWriteGuard::try_map(...)`. A method would interfere with methods
928 /// of the same name on the contents of the `RwLockWriteGuard` used through
929 /// `Deref`.
930 ///
931 /// # Panics
932 ///
933 /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will be poisoned.
934 #[doc(alias = "filter_map")]
935 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
936 pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, U>, Self>
937 where
938 F: FnOnce(&mut T) -> Option<&mut U>,
939 U: ?Sized,
940 {
941 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
942 // was created, and have been upheld throughout `map` and/or `try_map`.
943 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
944 // passed to it. If the closure panics, the guard will be dropped.
945 match f(unsafe { &mut *orig.lock.data.get() }) {
946 Some(data) => {
947 let data = NonNull::from(data);
948 let orig = ManuallyDrop::new(orig);
949 Ok(MappedRwLockWriteGuard {
950 data,
951 inner_lock: &orig.lock.inner,
952 poison_flag: &orig.lock.poison,
953 poison: orig.poison.clone(),
954 _variance: PhantomData,
955 })
956 }
957 None => Err(orig),
958 }
959 }
960}
961
962impl<'a, T: ?Sized> MappedRwLockWriteGuard<'a, T> {
963 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data,
964 /// e.g. an enum variant.
965 ///
966 /// The `RwLock` is already locked for writing, so this cannot fail.
967 ///
968 /// This is an associated function that needs to be used as
969 /// `MappedRwLockWriteGuard::map(...)`. A method would interfere with
970 /// methods of the same name on the contents of the `MappedRwLockWriteGuard`
971 /// used through `Deref`.
972 ///
973 /// # Panics
974 ///
975 /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will be poisoned.
976 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
977 pub fn map<U, F>(mut orig: Self, f: F) -> MappedRwLockWriteGuard<'a, U>
978 where
979 F: FnOnce(&mut T) -> &mut U,
980 U: ?Sized,
981 {
982 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
983 // was created, and have been upheld throughout `map` and/or `try_map`.
984 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
985 // passed to it. If the closure panics, the guard will be dropped.
986 let data = NonNull::from(f(unsafe { orig.data.as_mut() }));
987 let orig = ManuallyDrop::new(orig);
988 MappedRwLockWriteGuard {
989 data,
990 inner_lock: orig.inner_lock,
991 poison_flag: orig.poison_flag,
992 poison: orig.poison.clone(),
993 _variance: PhantomData,
994 }
995 }
996
997 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data.
998 /// The original guard is returned as an `Err(...)` if the closure returns
999 /// `None`.
1000 ///
1001 /// The `RwLock` is already locked for writing, so this cannot fail.
1002 ///
1003 /// This is an associated function that needs to be used as
1004 /// `MappedRwLockWriteGuard::try_map(...)`. A method would interfere with
1005 /// methods of the same name on the contents of the `MappedRwLockWriteGuard`
1006 /// used through `Deref`.
1007 ///
1008 /// # Panics
1009 ///
1010 /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will be poisoned.
1011 #[doc(alias = "filter_map")]
1012 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
1013 pub fn try_map<U, F>(mut orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, U>, Self>
1014 where
1015 F: FnOnce(&mut T) -> Option<&mut U>,
1016 U: ?Sized,
1017 {
1018 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1019 // was created, and have been upheld throughout `map` and/or `try_map`.
1020 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
1021 // passed to it. If the closure panics, the guard will be dropped.
1022 match f(unsafe { orig.data.as_mut() }) {
1023 Some(data) => {
1024 let data = NonNull::from(data);
1025 let orig = ManuallyDrop::new(orig);
1026 Ok(MappedRwLockWriteGuard {
1027 data,
1028 inner_lock: orig.inner_lock,
1029 poison_flag: orig.poison_flag,
1030 poison: orig.poison.clone(),
1031 _variance: PhantomData,
1032 })
1033 }
1034 None => Err(orig),
1035 }
1036 }
1037}
1038