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    /// #![feature(rwlock_downgrade)]
704    ///
705    /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard};
706    ///
707    /// let rw = RwLock::new(0);
708    ///
709    /// let mut write_guard = rw.write();
710    /// *write_guard = 42;
711    ///
712    /// let read_guard = RwLockWriteGuard::downgrade(write_guard);
713    /// assert_eq!(42, *read_guard);
714    /// ```
715    ///
716    /// `downgrade` will _atomically_ change the state of the [`RwLock`] from exclusive mode into
717    /// shared mode. This means that it is impossible for another writing thread to get in between a
718    /// thread calling `downgrade` and any reads it performs after downgrading.
719    ///
720    /// ```
721    /// #![feature(nonpoison_rwlock)]
722    /// #![feature(rwlock_downgrade)]
723    ///
724    /// use std::sync::Arc;
725    /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard};
726    ///
727    /// let rw = Arc::new(RwLock::new(1));
728    ///
729    /// // Put the lock in write mode.
730    /// let mut main_write_guard = rw.write();
731    ///
732    /// let rw_clone = rw.clone();
733    /// let evil_handle = std::thread::spawn(move || {
734    ///     // This will not return until the main thread drops the `main_read_guard`.
735    ///     let mut evil_guard = rw_clone.write();
736    ///
737    ///     assert_eq!(*evil_guard, 2);
738    ///     *evil_guard = 3;
739    /// });
740    ///
741    /// *main_write_guard = 2;
742    ///
743    /// // Atomically downgrade the write guard into a read guard.
744    /// let main_read_guard = RwLockWriteGuard::downgrade(main_write_guard);
745    ///
746    /// // Since `downgrade` is atomic, the writer thread cannot have changed the protected data.
747    /// assert_eq!(*main_read_guard, 2, "`downgrade` was not atomic");
748    /// #
749    /// # drop(main_read_guard);
750    /// # evil_handle.join().unwrap();
751    /// #
752    /// # let final_check = rw.read();
753    /// # assert_eq!(*final_check, 3);
754    /// ```
755    #[unstable(feature = "rwlock_downgrade", issue = "128203")]
756    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
757    pub fn downgrade(s: Self) -> RwLockReadGuard<'rwlock, T> {
758        let lock = s.lock;
759
760        // We don't want to call the destructor since that calls `write_unlock`.
761        forget(s);
762
763        // SAFETY: We take ownership of a write guard, so we must already have the `RwLock` in write
764        // mode, satisfying the `downgrade` contract.
765        unsafe { lock.inner.downgrade() };
766
767        // SAFETY: We have just successfully called `downgrade`, so we fulfill the safety contract.
768        unsafe { RwLockReadGuard::new(lock) }
769    }
770
771    /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data, e.g.
772    /// an enum variant.
773    ///
774    /// The `RwLock` is already locked for writing, so this cannot fail.
775    ///
776    /// This is an associated function that needs to be used as
777    /// `RwLockWriteGuard::map(...)`. A method would interfere with methods of
778    /// the same name on the contents of the `RwLockWriteGuard` used through
779    /// `Deref`.
780    ///
781    /// # Panics
782    ///
783    /// If the closure panics, the guard will be dropped (unlocked).
784    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
785    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
786    pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U>
787    where
788        F: FnOnce(&mut T) -> &mut U,
789        U: ?Sized,
790    {
791        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
792        // was created, and have been upheld throughout `map` and/or `filter_map`.
793        // The signature of the closure guarantees that it will not "leak" the lifetime of the
794        // reference passed to it. If the closure panics, the guard will be dropped.
795        let data = NonNull::from(f(unsafe { &mut *orig.lock.data.get() }));
796        let orig = ManuallyDrop::new(orig);
797        MappedRwLockWriteGuard { data, inner_lock: &orig.lock.inner, _variance: PhantomData }
798    }
799
800    /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data. The
801    /// original guard is returned as an `Err(...)` if the closure returns
802    /// `None`.
803    ///
804    /// The `RwLock` is already locked for writing, so this cannot fail.
805    ///
806    /// This is an associated function that needs to be used as
807    /// `RwLockWriteGuard::filter_map(...)`. A method would interfere with methods
808    /// of the same name on the contents of the `RwLockWriteGuard` used through
809    /// `Deref`.
810    ///
811    /// # Panics
812    ///
813    /// If the closure panics, the guard will be dropped (unlocked).
814    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
815    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
816    pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self>
817    where
818        F: FnOnce(&mut T) -> Option<&mut U>,
819        U: ?Sized,
820    {
821        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
822        // was created, and have been upheld throughout `map` and/or `filter_map`.
823        // The signature of the closure guarantees that it will not "leak" the lifetime of the
824        // reference passed to it. If the closure panics, the guard will be dropped.
825        match f(unsafe { &mut *orig.lock.data.get() }) {
826            Some(data) => {
827                let data = NonNull::from(data);
828                let orig = ManuallyDrop::new(orig);
829                Ok(MappedRwLockWriteGuard {
830                    data,
831                    inner_lock: &orig.lock.inner,
832                    _variance: PhantomData,
833                })
834            }
835            None => Err(orig),
836        }
837    }
838}
839
840impl<'rwlock, T: ?Sized> MappedRwLockReadGuard<'rwlock, T> {
841    /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data,
842    /// e.g. an enum variant.
843    ///
844    /// The `RwLock` is already locked for reading, so this cannot fail.
845    ///
846    /// This is an associated function that needs to be used as
847    /// `MappedRwLockReadGuard::map(...)`. A method would interfere with
848    /// methods of the same name on the contents of the `MappedRwLockReadGuard`
849    /// used through `Deref`.
850    ///
851    /// # Panics
852    ///
853    /// If the closure panics, the guard will be dropped (unlocked).
854    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
855    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
856    pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'rwlock, U>
857    where
858        F: FnOnce(&T) -> &U,
859        U: ?Sized,
860    {
861        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
862        // was created, and have been upheld throughout `map` and/or `filter_map`.
863        // The signature of the closure guarantees that it will not "leak" the lifetime of the
864        // reference passed to it. If the closure panics, the guard will be dropped.
865        let data = NonNull::from(f(unsafe { orig.data.as_ref() }));
866        let orig = ManuallyDrop::new(orig);
867        MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }
868    }
869
870    /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data.
871    /// The original guard is returned as an `Err(...)` if the closure returns
872    /// `None`.
873    ///
874    /// The `RwLock` is already locked for reading, so this cannot fail.
875    ///
876    /// This is an associated function that needs to be used as
877    /// `MappedRwLockReadGuard::filter_map(...)`. A method would interfere with
878    /// methods of the same name on the contents of the `MappedRwLockReadGuard`
879    /// used through `Deref`.
880    ///
881    /// # Panics
882    ///
883    /// If the closure panics, the guard will be dropped (unlocked).
884    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
885    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
886    pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'rwlock, U>, Self>
887    where
888        F: FnOnce(&T) -> Option<&U>,
889        U: ?Sized,
890    {
891        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
892        // was created, and have been upheld throughout `map` and/or `filter_map`.
893        // The signature of the closure guarantees that it will not "leak" the lifetime of the
894        // reference passed to it. If the closure panics, the guard will be dropped.
895        match f(unsafe { orig.data.as_ref() }) {
896            Some(data) => {
897                let data = NonNull::from(data);
898                let orig = ManuallyDrop::new(orig);
899                Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock })
900            }
901            None => Err(orig),
902        }
903    }
904}
905
906impl<'rwlock, T: ?Sized> MappedRwLockWriteGuard<'rwlock, T> {
907    /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data,
908    /// e.g. an enum variant.
909    ///
910    /// The `RwLock` is already locked for writing, so this cannot fail.
911    ///
912    /// This is an associated function that needs to be used as
913    /// `MappedRwLockWriteGuard::map(...)`. A method would interfere with
914    /// methods of the same name on the contents of the `MappedRwLockWriteGuard`
915    /// used through `Deref`.
916    ///
917    /// # Panics
918    ///
919    /// If the closure panics, the guard will be dropped (unlocked).
920    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
921    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
922    pub fn map<U, F>(mut orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U>
923    where
924        F: FnOnce(&mut T) -> &mut U,
925        U: ?Sized,
926    {
927        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
928        // was created, and have been upheld throughout `map` and/or `filter_map`.
929        // The signature of the closure guarantees that it will not "leak" the lifetime of the
930        // reference passed to it. If the closure panics, the guard will be dropped.
931        let data = NonNull::from(f(unsafe { orig.data.as_mut() }));
932        let orig = ManuallyDrop::new(orig);
933        MappedRwLockWriteGuard { data, inner_lock: orig.inner_lock, _variance: PhantomData }
934    }
935
936    /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data.
937    /// The original guard is returned as an `Err(...)` if the closure returns
938    /// `None`.
939    ///
940    /// The `RwLock` is already locked for writing, so this cannot fail.
941    ///
942    /// This is an associated function that needs to be used as
943    /// `MappedRwLockWriteGuard::filter_map(...)`. A method would interfere with
944    /// methods of the same name on the contents of the `MappedRwLockWriteGuard`
945    /// used through `Deref`.
946    ///
947    /// # Panics
948    ///
949    /// If the closure panics, the guard will be dropped (unlocked).
950    #[unstable(feature = "mapped_lock_guards", issue = "117108")]
951    // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
952    pub fn filter_map<U, F>(
953        mut orig: Self,
954        f: F,
955    ) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self>
956    where
957        F: FnOnce(&mut T) -> Option<&mut U>,
958        U: ?Sized,
959    {
960        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
961        // was created, and have been upheld throughout `map` and/or `filter_map`.
962        // The signature of the closure guarantees that it will not "leak" the lifetime of the
963        // reference passed to it. If the closure panics, the guard will be dropped.
964        match f(unsafe { orig.data.as_mut() }) {
965            Some(data) => {
966                let data = NonNull::from(data);
967                let orig = ManuallyDrop::new(orig);
968                Ok(MappedRwLockWriteGuard {
969                    data,
970                    inner_lock: orig.inner_lock,
971                    _variance: PhantomData,
972                })
973            }
974            None => Err(orig),
975        }
976    }
977}
978
979#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
980impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
981    fn drop(&mut self) {
982        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
983        unsafe {
984            self.inner_lock.read_unlock();
985        }
986    }
987}
988
989#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
990impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
991    fn drop(&mut self) {
992        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
993        unsafe {
994            self.lock.inner.write_unlock();
995        }
996    }
997}
998
999#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1000// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1001impl<T: ?Sized> Drop for MappedRwLockReadGuard<'_, T> {
1002    fn drop(&mut self) {
1003        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
1004        // was created, and have been upheld throughout `map` and/or `filter_map`.
1005        unsafe {
1006            self.inner_lock.read_unlock();
1007        }
1008    }
1009}
1010
1011#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1012// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1013impl<T: ?Sized> Drop for MappedRwLockWriteGuard<'_, T> {
1014    fn drop(&mut self) {
1015        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1016        // was created, and have been upheld throughout `map` and/or `filter_map`.
1017        unsafe {
1018            self.inner_lock.write_unlock();
1019        }
1020    }
1021}
1022
1023#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1024impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
1025    type Target = T;
1026
1027    fn deref(&self) -> &T {
1028        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
1029        unsafe { self.data.as_ref() }
1030    }
1031}
1032
1033#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1034impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
1035    type Target = T;
1036
1037    fn deref(&self) -> &T {
1038        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
1039        unsafe { &*self.lock.data.get() }
1040    }
1041}
1042
1043#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1044impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
1045    fn deref_mut(&mut self) -> &mut T {
1046        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
1047        unsafe { &mut *self.lock.data.get() }
1048    }
1049}
1050
1051#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1052// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1053impl<T: ?Sized> Deref for MappedRwLockReadGuard<'_, T> {
1054    type Target = T;
1055
1056    fn deref(&self) -> &T {
1057        // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
1058        // was created, and have been upheld throughout `map` and/or `filter_map`.
1059        unsafe { self.data.as_ref() }
1060    }
1061}
1062
1063#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1064// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1065impl<T: ?Sized> Deref for MappedRwLockWriteGuard<'_, T> {
1066    type Target = T;
1067
1068    fn deref(&self) -> &T {
1069        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1070        // was created, and have been upheld throughout `map` and/or `filter_map`.
1071        unsafe { self.data.as_ref() }
1072    }
1073}
1074
1075#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1076// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1077impl<T: ?Sized> DerefMut for MappedRwLockWriteGuard<'_, T> {
1078    fn deref_mut(&mut self) -> &mut T {
1079        // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1080        // was created, and have been upheld throughout `map` and/or `filter_map`.
1081        unsafe { self.data.as_mut() }
1082    }
1083}
1084
1085#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1086impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> {
1087    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1088        (**self).fmt(f)
1089    }
1090}
1091
1092#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1093impl<T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'_, T> {
1094    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1095        (**self).fmt(f)
1096    }
1097}
1098
1099#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1100impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> {
1101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1102        (**self).fmt(f)
1103    }
1104}
1105
1106#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1107impl<T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'_, T> {
1108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1109        (**self).fmt(f)
1110    }
1111}
1112
1113#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1114// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1115impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockReadGuard<'_, T> {
1116    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1117        (**self).fmt(f)
1118    }
1119}
1120
1121#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1122// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1123impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockReadGuard<'_, T> {
1124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1125        (**self).fmt(f)
1126    }
1127}
1128
1129#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1130// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1131impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockWriteGuard<'_, T> {
1132    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1133        (**self).fmt(f)
1134    }
1135}
1136
1137#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1138// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1139impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockWriteGuard<'_, T> {
1140    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1141        (**self).fmt(f)
1142    }
1143}