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 fn data_ptr(&self) -> *mut T {
499        self.data.get()
500    }
501}
502
503#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
504impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
505    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
506        let mut d = f.debug_struct("RwLock");
507        match self.try_read() {
508            Ok(guard) => {
509                d.field("data", &&*guard);
510            }
511            Err(WouldBlock) => {
512                d.field("data", &format_args!("<locked>"));
513            }
514        }
515        d.finish_non_exhaustive()
516    }
517}
518
519#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
520impl<T: Default> Default for RwLock<T> {
521    /// Creates a new `RwLock<T>`, with the `Default` value for T.
522    fn default() -> RwLock<T> {
523        RwLock::new(Default::default())
524    }
525}
526
527#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
528impl<T> From<T> for RwLock<T> {
529    /// Creates a new instance of an `RwLock<T>` which is unlocked.
530    /// This is equivalent to [`RwLock::new`].
531    fn from(t: T) -> Self {
532        RwLock::new(t)
533    }
534}
535
536impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
537    /// Creates a new instance of `RwLockReadGuard<T>` from a `RwLock<T>`.
538    ///
539    /// # Safety
540    ///
541    /// This function is safe if and only if the same thread has successfully and safely called
542    /// `lock.inner.read()`, `lock.inner.try_read()`, or `lock.inner.downgrade()` before
543    /// instantiating this object.
544    unsafe fn new(lock: &'rwlock RwLock<T>) -> RwLockReadGuard<'rwlock, T> {
545        RwLockReadGuard {
546            data: unsafe { NonNull::new_unchecked(lock.data.get()) },
547            inner_lock: &lock.inner,
548        }
549    }
550
551    /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data, e.g.
552    /// an enum variant.
553    ///
554    /// The `RwLock` is already locked for reading, so this cannot fail.
555    ///
556    /// This is an associated function that needs to be used as
557    /// `RwLockReadGuard::map(...)`. A method would interfere with methods of
558    /// the same name on the contents of the `RwLockReadGuard` used through
559    /// `Deref`.
560    ///
561    /// # Panics
562    ///
563    /// If the closure panics, the guard will be dropped (unlocked).
564    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
565    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
566    pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'rwlock, U>
567    where
568        F: FnOnce(&T) -> &U,
569        U: ?Sized,
570    {
571        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
572        // was created, and have been upheld throughout `map` and/or `filter_map`.
573        // The signature of the closure guarantees that it will not "leak" the lifetime of the
574        // reference passed to it. If the closure panics, the guard will be dropped.
575        let data = NonNull::from(f(unsafe { orig.data.as_ref() }));
576        let orig = ManuallyDrop::new(orig);
577        MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }
578    }
579
580    /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data. The
581    /// original guard is returned as an `Err(...)` if the closure returns
582    /// `None`.
583    ///
584    /// The `RwLock` is already locked for reading, so this cannot fail.
585    ///
586    /// This is an associated function that needs to be used as
587    /// `RwLockReadGuard::filter_map(...)`. A method would interfere with methods
588    /// of the same name on the contents of the `RwLockReadGuard` used through
589    /// `Deref`.
590    ///
591    /// # Panics
592    ///
593    /// If the closure panics, the guard will be dropped (unlocked).
594    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
595    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
596    pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'rwlock, U>, Self>
597    where
598        F: FnOnce(&T) -> Option<&U>,
599        U: ?Sized,
600    {
601        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
602        // was created, and have been upheld throughout `map` and/or `filter_map`.
603        // The signature of the closure guarantees that it will not "leak" the lifetime of the
604        // reference passed to it. If the closure panics, the guard will be dropped.
605        match f(unsafe { orig.data.as_ref() }) {
606            Some(data) => {
607                let data = NonNull::from(data);
608                let orig = ManuallyDrop::new(orig);
609                Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock })
610            }
611            None => Err(orig),
612        }
613    }
614}
615
616impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
617    /// Creates a new instance of `RwLockWriteGuard<T>` from a `RwLock<T>`.
618    ///
619    /// # Safety
620    ///
621    /// This function is safe if and only if the same thread has successfully and safely called
622    /// `lock.inner.write()`, `lock.inner.try_write()`, or `lock.inner.try_upgrade` before
623    /// instantiating this object.
624    unsafe fn new(lock: &'rwlock RwLock<T>) -> RwLockWriteGuard<'rwlock, T> {
625        RwLockWriteGuard { lock }
626    }
627
628    /// Downgrades a write-locked `RwLockWriteGuard` into a read-locked [`RwLockReadGuard`].
629    ///
630    /// Since we have the `RwLockWriteGuard`, the [`RwLock`] must already be locked for writing, so
631    /// this method cannot fail.
632    ///
633    /// After downgrading, other readers will be allowed to read the protected data.
634    ///
635    /// # Examples
636    ///
637    /// `downgrade` takes ownership of the `RwLockWriteGuard` and returns a [`RwLockReadGuard`].
638    ///
639    /// ```
640    /// #![feature(nonpoison_rwlock)]
641    /// #![feature(rwlock_downgrade)]
642    ///
643    /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard};
644    ///
645    /// let rw = RwLock::new(0);
646    ///
647    /// let mut write_guard = rw.write();
648    /// *write_guard = 42;
649    ///
650    /// let read_guard = RwLockWriteGuard::downgrade(write_guard);
651    /// assert_eq!(42, *read_guard);
652    /// ```
653    ///
654    /// `downgrade` will _atomically_ change the state of the [`RwLock`] from exclusive mode into
655    /// shared mode. This means that it is impossible for another writing thread to get in between a
656    /// thread calling `downgrade` and any reads it performs after downgrading.
657    ///
658    /// ```
659    /// #![feature(nonpoison_rwlock)]
660    /// #![feature(rwlock_downgrade)]
661    ///
662    /// use std::sync::Arc;
663    /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard};
664    ///
665    /// let rw = Arc::new(RwLock::new(1));
666    ///
667    /// // Put the lock in write mode.
668    /// let mut main_write_guard = rw.write();
669    ///
670    /// let rw_clone = rw.clone();
671    /// let evil_handle = std::thread::spawn(move || {
672    ///     // This will not return until the main thread drops the `main_read_guard`.
673    ///     let mut evil_guard = rw_clone.write();
674    ///
675    ///     assert_eq!(*evil_guard, 2);
676    ///     *evil_guard = 3;
677    /// });
678    ///
679    /// *main_write_guard = 2;
680    ///
681    /// // Atomically downgrade the write guard into a read guard.
682    /// let main_read_guard = RwLockWriteGuard::downgrade(main_write_guard);
683    ///
684    /// // Since `downgrade` is atomic, the writer thread cannot have changed the protected data.
685    /// assert_eq!(*main_read_guard, 2, "`downgrade` was not atomic");
686    /// #
687    /// # drop(main_read_guard);
688    /// # evil_handle.join().unwrap();
689    /// #
690    /// # let final_check = rw.read();
691    /// # assert_eq!(*final_check, 3);
692    /// ```
693    #[unstable(feature = "rwlock_downgrade", issue = "128203")]
694    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
695    pub fn downgrade(s: Self) -> RwLockReadGuard<'rwlock, T> {
696        let lock = s.lock;
697
698        // We don't want to call the destructor since that calls `write_unlock`.
699        forget(s);
700
701        // SAFETY: We take ownership of a write guard, so we must already have the `RwLock` in write
702        // mode, satisfying the `downgrade` contract.
703        unsafe { lock.inner.downgrade() };
704
705        // SAFETY: We have just successfully called `downgrade`, so we fulfill the safety contract.
706        unsafe { RwLockReadGuard::new(lock) }
707    }
708
709    /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data, e.g.
710    /// an enum variant.
711    ///
712    /// The `RwLock` is already locked for writing, so this cannot fail.
713    ///
714    /// This is an associated function that needs to be used as
715    /// `RwLockWriteGuard::map(...)`. A method would interfere with methods of
716    /// the same name on the contents of the `RwLockWriteGuard` used through
717    /// `Deref`.
718    ///
719    /// # Panics
720    ///
721    /// If the closure panics, the guard will be dropped (unlocked).
722    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
723    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
724    pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U>
725    where
726        F: FnOnce(&mut T) -> &mut U,
727        U: ?Sized,
728    {
729        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
730        // was created, and have been upheld throughout `map` and/or `filter_map`.
731        // The signature of the closure guarantees that it will not "leak" the lifetime of the
732        // reference passed to it. If the closure panics, the guard will be dropped.
733        let data = NonNull::from(f(unsafe { &mut *orig.lock.data.get() }));
734        let orig = ManuallyDrop::new(orig);
735        MappedRwLockWriteGuard { data, inner_lock: &orig.lock.inner, _variance: PhantomData }
736    }
737
738    /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data. The
739    /// original guard is returned as an `Err(...)` if the closure returns
740    /// `None`.
741    ///
742    /// The `RwLock` is already locked for writing, so this cannot fail.
743    ///
744    /// This is an associated function that needs to be used as
745    /// `RwLockWriteGuard::filter_map(...)`. A method would interfere with methods
746    /// of the same name on the contents of the `RwLockWriteGuard` used through
747    /// `Deref`.
748    ///
749    /// # Panics
750    ///
751    /// If the closure panics, the guard will be dropped (unlocked).
752    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
753    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
754    pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self>
755    where
756        F: FnOnce(&mut T) -> Option<&mut U>,
757        U: ?Sized,
758    {
759        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
760        // was created, and have been upheld throughout `map` and/or `filter_map`.
761        // The signature of the closure guarantees that it will not "leak" the lifetime of the
762        // reference passed to it. If the closure panics, the guard will be dropped.
763        match f(unsafe { &mut *orig.lock.data.get() }) {
764            Some(data) => {
765                let data = NonNull::from(data);
766                let orig = ManuallyDrop::new(orig);
767                Ok(MappedRwLockWriteGuard {
768                    data,
769                    inner_lock: &orig.lock.inner,
770                    _variance: PhantomData,
771                })
772            }
773            None => Err(orig),
774        }
775    }
776}
777
778impl<'rwlock, T: ?Sized> MappedRwLockReadGuard<'rwlock, T> {
779    /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data,
780    /// e.g. an enum variant.
781    ///
782    /// The `RwLock` is already locked for reading, so this cannot fail.
783    ///
784    /// This is an associated function that needs to be used as
785    /// `MappedRwLockReadGuard::map(...)`. A method would interfere with
786    /// methods of the same name on the contents of the `MappedRwLockReadGuard`
787    /// used through `Deref`.
788    ///
789    /// # Panics
790    ///
791    /// If the closure panics, the guard will be dropped (unlocked).
792    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
793    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
794    pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'rwlock, U>
795    where
796        F: FnOnce(&T) -> &U,
797        U: ?Sized,
798    {
799        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
800        // was created, and have been upheld throughout `map` and/or `filter_map`.
801        // The signature of the closure guarantees that it will not "leak" the lifetime of the
802        // reference passed to it. If the closure panics, the guard will be dropped.
803        let data = NonNull::from(f(unsafe { orig.data.as_ref() }));
804        let orig = ManuallyDrop::new(orig);
805        MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }
806    }
807
808    /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data.
809    /// The original guard is returned as an `Err(...)` if the closure returns
810    /// `None`.
811    ///
812    /// The `RwLock` is already locked for reading, so this cannot fail.
813    ///
814    /// This is an associated function that needs to be used as
815    /// `MappedRwLockReadGuard::filter_map(...)`. A method would interfere with
816    /// methods of the same name on the contents of the `MappedRwLockReadGuard`
817    /// used through `Deref`.
818    ///
819    /// # Panics
820    ///
821    /// If the closure panics, the guard will be dropped (unlocked).
822    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
823    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
824    pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'rwlock, U>, Self>
825    where
826        F: FnOnce(&T) -> Option<&U>,
827        U: ?Sized,
828    {
829        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
830        // was created, and have been upheld throughout `map` and/or `filter_map`.
831        // The signature of the closure guarantees that it will not "leak" the lifetime of the
832        // reference passed to it. If the closure panics, the guard will be dropped.
833        match f(unsafe { orig.data.as_ref() }) {
834            Some(data) => {
835                let data = NonNull::from(data);
836                let orig = ManuallyDrop::new(orig);
837                Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock })
838            }
839            None => Err(orig),
840        }
841    }
842}
843
844impl<'rwlock, T: ?Sized> MappedRwLockWriteGuard<'rwlock, T> {
845    /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data,
846    /// e.g. an enum variant.
847    ///
848    /// The `RwLock` is already locked for writing, so this cannot fail.
849    ///
850    /// This is an associated function that needs to be used as
851    /// `MappedRwLockWriteGuard::map(...)`. A method would interfere with
852    /// methods of the same name on the contents of the `MappedRwLockWriteGuard`
853    /// used through `Deref`.
854    ///
855    /// # Panics
856    ///
857    /// If the closure panics, the guard will be dropped (unlocked).
858    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
859    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
860    pub fn map<U, F>(mut orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U>
861    where
862        F: FnOnce(&mut T) -> &mut U,
863        U: ?Sized,
864    {
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        // The signature of the closure guarantees that it will not "leak" the lifetime of the
868        // reference passed to it. If the closure panics, the guard will be dropped.
869        let data = NonNull::from(f(unsafe { orig.data.as_mut() }));
870        let orig = ManuallyDrop::new(orig);
871        MappedRwLockWriteGuard { data, inner_lock: orig.inner_lock, _variance: PhantomData }
872    }
873
874    /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data.
875    /// The original guard is returned as an `Err(...)` if the closure returns
876    /// `None`.
877    ///
878    /// The `RwLock` is already locked for writing, so this cannot fail.
879    ///
880    /// This is an associated function that needs to be used as
881    /// `MappedRwLockWriteGuard::filter_map(...)`. A method would interfere with
882    /// methods of the same name on the contents of the `MappedRwLockWriteGuard`
883    /// used through `Deref`.
884    ///
885    /// # Panics
886    ///
887    /// If the closure panics, the guard will be dropped (unlocked).
888    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
889    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
890    pub fn filter_map<U, F>(
891        mut orig: Self,
892        f: F,
893    ) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self>
894    where
895        F: FnOnce(&mut T) -> Option<&mut U>,
896        U: ?Sized,
897    {
898        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
899        // was created, and have been upheld throughout `map` and/or `filter_map`.
900        // The signature of the closure guarantees that it will not "leak" the lifetime of the
901        // reference passed to it. If the closure panics, the guard will be dropped.
902        match f(unsafe { orig.data.as_mut() }) {
903            Some(data) => {
904                let data = NonNull::from(data);
905                let orig = ManuallyDrop::new(orig);
906                Ok(MappedRwLockWriteGuard {
907                    data,
908                    inner_lock: orig.inner_lock,
909                    _variance: PhantomData,
910                })
911            }
912            None => Err(orig),
913        }
914    }
915}
916
917#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
918impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
919    fn drop(&mut self) {
920        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
921        unsafe {
922            self.inner_lock.read_unlock();
923        }
924    }
925}
926
927#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
928impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
929    fn drop(&mut self) {
930        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
931        unsafe {
932            self.lock.inner.write_unlock();
933        }
934    }
935}
936
937#[unstable(feature = "mapped_lock_guards", issue = "117108")]
938// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
939impl<T: ?Sized> Drop for MappedRwLockReadGuard<'_, T> {
940    fn drop(&mut self) {
941        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
942        // was created, and have been upheld throughout `map` and/or `filter_map`.
943        unsafe {
944            self.inner_lock.read_unlock();
945        }
946    }
947}
948
949#[unstable(feature = "mapped_lock_guards", issue = "117108")]
950// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
951impl<T: ?Sized> Drop for MappedRwLockWriteGuard<'_, T> {
952    fn drop(&mut self) {
953        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
954        // was created, and have been upheld throughout `map` and/or `filter_map`.
955        unsafe {
956            self.inner_lock.write_unlock();
957        }
958    }
959}
960
961#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
962impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
963    type Target = T;
964
965    fn deref(&self) -> &T {
966        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
967        unsafe { self.data.as_ref() }
968    }
969}
970
971#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
972impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
973    type Target = T;
974
975    fn deref(&self) -> &T {
976        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
977        unsafe { &*self.lock.data.get() }
978    }
979}
980
981#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
982impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
983    fn deref_mut(&mut self) -> &mut T {
984        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
985        unsafe { &mut *self.lock.data.get() }
986    }
987}
988
989#[unstable(feature = "mapped_lock_guards", issue = "117108")]
990// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
991impl<T: ?Sized> Deref for MappedRwLockReadGuard<'_, T> {
992    type Target = T;
993
994    fn deref(&self) -> &T {
995        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
996        // was created, and have been upheld throughout `map` and/or `filter_map`.
997        unsafe { self.data.as_ref() }
998    }
999}
1000
1001#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1002// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1003impl<T: ?Sized> Deref for MappedRwLockWriteGuard<'_, T> {
1004    type Target = T;
1005
1006    fn deref(&self) -> &T {
1007        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1008        // was created, and have been upheld throughout `map` and/or `filter_map`.
1009        unsafe { self.data.as_ref() }
1010    }
1011}
1012
1013#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1014// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1015impl<T: ?Sized> DerefMut for MappedRwLockWriteGuard<'_, T> {
1016    fn deref_mut(&mut self) -> &mut T {
1017        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1018        // was created, and have been upheld throughout `map` and/or `filter_map`.
1019        unsafe { self.data.as_mut() }
1020    }
1021}
1022
1023#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1024impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> {
1025    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1026        (**self).fmt(f)
1027    }
1028}
1029
1030#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1031impl<T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'_, T> {
1032    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1033        (**self).fmt(f)
1034    }
1035}
1036
1037#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1038impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> {
1039    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1040        (**self).fmt(f)
1041    }
1042}
1043
1044#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1045impl<T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'_, T> {
1046    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1047        (**self).fmt(f)
1048    }
1049}
1050
1051#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1052// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1053impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockReadGuard<'_, T> {
1054    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1055        (**self).fmt(f)
1056    }
1057}
1058
1059#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1060// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1061impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockReadGuard<'_, T> {
1062    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1063        (**self).fmt(f)
1064    }
1065}
1066
1067#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1068// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1069impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockWriteGuard<'_, T> {
1070    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1071        (**self).fmt(f)
1072    }
1073}
1074
1075#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1076// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1077impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockWriteGuard<'_, T> {
1078    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1079        (**self).fmt(f)
1080    }
1081}