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