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