Skip to main content

spin/
rwlock.rs

1//! A lock that provides data access to either one writer or many readers.
2
3use crate::{
4    atomic::{AtomicUsize, Ordering},
5    RelaxStrategy, Spin,
6};
7use core::{
8    cell::UnsafeCell,
9    fmt,
10    marker::PhantomData,
11    mem,
12    mem::ManuallyDrop,
13    ops::{Deref, DerefMut},
14};
15
16/// A lock that provides data access to either one writer or many readers.
17///
18/// This lock behaves in a similar manner to its namesake `std::sync::RwLock` but uses
19/// spinning for synchronisation instead. Unlike its namesake, this lock does not
20/// track lock poisoning.
21///
22/// This type of lock allows a number of readers or at most one writer at any
23/// point in time. The write portion of this lock typically allows modification
24/// of the underlying data (exclusive access) and the read portion of this lock
25/// typically allows for read-only access (shared access).
26///
27/// The type parameter `T` represents the data that this lock protects. It is
28/// required that `T` satisfies `Send` to be shared across tasks and `Sync` to
29/// allow concurrent access through readers. The RAII guards returned from the
30/// locking methods implement `Deref` (and `DerefMut` for the `write` methods)
31/// to allow access to the contained of the lock.
32///
33/// An [`RwLockUpgradableGuard`] can be upgraded to a writable guard through
34/// the [`RwLockUpgradableGuard::upgrade`] and [`RwLockUpgradableGuard::try_upgrade`]
35/// functions. Writable or upgradeable  guards can be downgraded through their
36/// respective `downgrade` functions.
37///
38/// Based on Facebook's
39/// [`folly/RWSpinLock.h`](https://github.com/facebook/folly/blob/a0394d84f2d5c3e50ebfd0566f9d3acb52cfab5a/folly/synchronization/RWSpinLock.h).
40/// This implementation is unfair to writers - if the lock always has readers, then no writers will
41/// ever get a chance. Using an upgradeable lock guard can *somewhat* alleviate this issue as no
42/// new readers are allowed when an upgradeable guard is held, but upgradeable guards can be taken
43/// when there are existing readers. However if the lock is that highly contended and writes are
44/// crucial then this implementation may be a poor choice.
45///
46/// # Examples
47///
48/// ```
49/// use spin;
50///
51/// let lock = spin::RwLock::new(5);
52///
53/// // many reader locks can be held at once
54/// {
55///     let r1 = lock.read();
56///     let r2 = lock.read();
57///     assert_eq!(*r1, 5);
58///     assert_eq!(*r2, 5);
59/// } // read locks are dropped at this point
60///
61/// // only one write lock may be held, however
62/// {
63///     let mut w = lock.write();
64///     *w += 1;
65///     assert_eq!(*w, 6);
66/// } // write lock is dropped here
67/// ```
68pub struct RwLock<T: ?Sized, R = Spin> {
69    phantom: PhantomData<R>,
70    lock: AtomicUsize,
71    data: UnsafeCell<T>,
72}
73
74const READER: usize = 1 << 2;
75const UPGRADED: usize = 1 << 1;
76const WRITER: usize = 1;
77
78/// A guard that provides immutable data access.
79///
80/// When the guard falls out of scope it will decrement the read count,
81/// potentially releasing the lock.
82pub struct RwLockReadGuard<'a, T: 'a + ?Sized, R = Spin> {
83    inner: &'a RwLock<T, R>,
84}
85
86/// A guard that provides mutable data access.
87///
88/// When the guard falls out of scope it will release the lock.
89pub struct RwLockWriteGuard<'a, T: 'a + ?Sized, R = Spin> {
90    inner: &'a RwLock<T, R>,
91}
92
93/// A guard that provides immutable data access but can be upgraded to [`RwLockWriteGuard`].
94///
95/// No writers or other upgradeable guards can exist while this is in scope. New reader
96/// creation is prevented (to alleviate writer starvation) but there may be existing readers
97/// when the lock is acquired.
98///
99/// When the guard falls out of scope it will release the lock.
100pub struct RwLockUpgradableGuard<'a, T: 'a + ?Sized, R = Spin> {
101    inner: &'a RwLock<T, R>,
102}
103
104// SAFETY: Same unsafe impls as `std::sync::RwLock`
105unsafe impl<T: ?Sized + Send, R> Send for RwLock<T, R> {}
106unsafe impl<T: ?Sized + Send + Sync, R> Sync for RwLock<T, R> {}
107
108// SAFETY: Write guards can be thought of as mutable reference to the inner data. In fact, this
109// would be their ideal representation if it were not for the need for the critical section to end
110// *after* the reference is no longer live.
111unsafe impl<T: ?Sized, R> Sync for RwLockWriteGuard<'_, T, R> where for<'a> &'a mut T: Sync {}
112unsafe impl<T: ?Sized, R> Send for RwLockWriteGuard<'_, T, R> where for<'a> &'a mut T: Send {}
113
114// SAFETY: Read guards can be thought of as immutable reference to the inner data. In fact, this
115// would be their ideal representation if it were not for the need for the critical section to end
116// *after* the reference is no longer live.
117unsafe impl<T: ?Sized, R> Sync for RwLockReadGuard<'_, T, R> where for<'a> &'a T: Sync {}
118unsafe impl<T: ?Sized, R> Send for RwLockReadGuard<'_, T, R> where for<'a> &'a T: Send {}
119
120// SAFETY: Read guards can be thought of as immutable reference to the inner data. In fact, this
121// would be their ideal representation if it were not for the need for the critical section to end
122// *after* the reference is no longer live. Note that the ability to upgrade the lock does not
123// result in extra requirements: those are already assured by `RwLockWriteGuard` on upgrade.
124unsafe impl<T: ?Sized> Sync for RwLockUpgradableGuard<'_, T> where for<'a> &'a T: Sync {}
125unsafe impl<T: ?Sized> Send for RwLockUpgradableGuard<'_, T> where for<'a> &'a T: Send {}
126
127impl<T, R> RwLock<T, R> {
128    /// Creates a new spinlock wrapping the supplied data.
129    ///
130    /// May be used statically:
131    ///
132    /// ```
133    /// use spin;
134    ///
135    /// static RW_LOCK: spin::RwLock<()> = spin::RwLock::new(());
136    ///
137    /// fn demo() {
138    ///     let lock = RW_LOCK.read();
139    ///     // do something with lock
140    ///     drop(lock);
141    /// }
142    /// ```
143    #[inline]
144    pub const fn new(data: T) -> Self {
145        RwLock {
146            phantom: PhantomData,
147            lock: AtomicUsize::new(0),
148            data: UnsafeCell::new(data),
149        }
150    }
151
152    /// Consumes this `RwLock`, returning the underlying data.
153    #[inline]
154    pub fn into_inner(self) -> T {
155        // We know statically that there are no outstanding references to
156        // `self` so there's no need to lock.
157        let RwLock { data, .. } = self;
158        data.into_inner()
159    }
160    /// Returns a mutable pointer to the underlying data.
161    ///
162    /// This is mostly meant to be used for applications which require manual unlocking, but where
163    /// storing both the lock and the pointer to the inner data gets inefficient.
164    ///
165    /// While this is safe, writing to the data is undefined behavior unless the current thread has
166    /// acquired a write lock, and reading requires either a read or write lock.
167    ///
168    /// # Example
169    /// ```
170    /// let lock = spin::RwLock::new(42);
171    ///
172    /// unsafe {
173    ///     core::mem::forget(lock.write());
174    ///
175    ///     assert_eq!(lock.as_mut_ptr().read(), 42);
176    ///     lock.as_mut_ptr().write(58);
177    ///
178    ///     lock.force_write_unlock();
179    /// }
180    ///
181    /// assert_eq!(*lock.read(), 58);
182    ///
183    /// ```
184    #[inline(always)]
185    pub fn as_mut_ptr(&self) -> *mut T {
186        self.data.get()
187    }
188}
189
190impl<T: ?Sized, R: RelaxStrategy> RwLock<T, R> {
191    /// Locks this rwlock with shared read access, blocking the current thread
192    /// until it can be acquired.
193    ///
194    /// The calling thread will be blocked until there are no more writers which
195    /// hold the lock. There may be other readers currently inside the lock when
196    /// this method returns. This method does not provide any guarantees with
197    /// respect to the ordering of whether contentious readers or writers will
198    /// acquire the lock first.
199    ///
200    /// Returns an RAII guard which will release this thread's shared access
201    /// once it is dropped.
202    ///
203    /// ```
204    /// let mylock = spin::RwLock::new(0);
205    /// {
206    ///     let mut data = mylock.read();
207    ///     // The lock is now locked and the data can be read
208    ///     println!("{}", *data);
209    ///     // The lock is dropped
210    /// }
211    /// ```
212    #[inline]
213    pub fn read(&self) -> RwLockReadGuard<'_, T, R> {
214        loop {
215            match self.try_read() {
216                Some(guard) => return guard,
217                None => R::relax(),
218            }
219        }
220    }
221
222    /// Lock this rwlock with exclusive write access, blocking the current
223    /// thread until it can be acquired.
224    ///
225    /// This function will not return while other writers or other readers
226    /// currently have access to the lock.
227    ///
228    /// Returns an RAII guard which will drop the write access of this rwlock
229    /// when dropped.
230    ///
231    /// ```
232    /// let mylock = spin::RwLock::new(0);
233    /// {
234    ///     let mut data = mylock.write();
235    ///     // The lock is now locked and the data can be written
236    ///     *data += 1;
237    ///     // The lock is dropped
238    /// }
239    /// ```
240    #[inline]
241    pub fn write(&self) -> RwLockWriteGuard<'_, T, R> {
242        loop {
243            match self.try_write_internal(false) {
244                Some(guard) => return guard,
245                None => R::relax(),
246            }
247        }
248    }
249
250    /// Obtain a readable lock guard that can later be upgraded to a writable lock guard.
251    /// Upgrades can be done through the [`RwLockUpgradableGuard::upgrade`](RwLockUpgradableGuard::upgrade) method.
252    #[inline]
253    pub fn upgradeable_read(&self) -> RwLockUpgradableGuard<'_, T, R> {
254        loop {
255            match self.try_upgradeable_read() {
256                Some(guard) => return guard,
257                None => R::relax(),
258            }
259        }
260    }
261}
262
263impl<T: ?Sized, R> RwLock<T, R> {
264    // Acquire a read lock, returning the new lock value.
265    fn acquire_reader(&self) -> usize {
266        // An arbitrary cap that allows us to catch overflows long before they happen
267        const MAX_READERS: usize = usize::MAX / READER / 2;
268
269        let value = self.lock.fetch_add(READER, Ordering::Acquire);
270
271        if value > MAX_READERS * READER {
272            self.lock.fetch_sub(READER, Ordering::Relaxed);
273            panic!("Too many lock readers, cannot safely proceed");
274        } else {
275            value
276        }
277    }
278
279    /// Attempt to acquire this lock with shared read access.
280    ///
281    /// This function will never block and will return immediately if `read`
282    /// would otherwise succeed. Returns `Some` of an RAII guard which will
283    /// release the shared access of this thread when dropped, or `None` if the
284    /// access could not be granted. This method does not provide any
285    /// guarantees with respect to the ordering of whether contentious readers
286    /// or writers will acquire the lock first.
287    ///
288    /// ```
289    /// let mylock = spin::RwLock::new(0);
290    /// {
291    ///     match mylock.try_read() {
292    ///         Some(data) => {
293    ///             // The lock is now locked and the data can be read
294    ///             println!("{}", *data);
295    ///             // The lock is dropped
296    ///         },
297    ///         None => (), // no cigar
298    ///     };
299    /// }
300    /// ```
301    #[inline]
302    pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T, R>> {
303        let value = self.acquire_reader();
304
305        // We check the UPGRADED bit here so that new readers are prevented when an UPGRADED lock is held.
306        // This helps reduce writer starvation.
307        if value & (WRITER | UPGRADED) != 0 {
308            // Lock is taken, undo.
309            self.lock.fetch_sub(READER, Ordering::Release);
310            None
311        } else {
312            Some(RwLockReadGuard { inner: self })
313        }
314    }
315
316    /// Return the number of readers that currently hold the lock (including upgradable readers).
317    ///
318    /// # Safety
319    ///
320    /// This function provides no synchronization guarantees and so its result should be considered 'out of date'
321    /// the instant it is called. Do not use it for synchronization purposes. However, it may be useful as a heuristic.
322    pub fn reader_count(&self) -> usize {
323        let state = self.lock.load(Ordering::Relaxed);
324        state / READER + (state & UPGRADED) / UPGRADED
325    }
326
327    /// Return the number of writers that currently hold the lock.
328    ///
329    /// Because [`RwLock`] guarantees exclusive mutable access, this function may only return either `0` or `1`.
330    ///
331    /// # Safety
332    ///
333    /// This function provides no synchronization guarantees and so its result should be considered 'out of date'
334    /// the instant it is called. Do not use it for synchronization purposes. However, it may be useful as a heuristic.
335    pub fn writer_count(&self) -> usize {
336        (self.lock.load(Ordering::Relaxed) & WRITER) / WRITER
337    }
338
339    /// Force decrement the reader count.
340    ///
341    /// # Safety
342    ///
343    /// This is *extremely* unsafe if there are outstanding `RwLockReadGuard`s
344    /// live, or if called more times than `read` has been called, but can be
345    /// useful in FFI contexts where the caller doesn't know how to deal with
346    /// RAII. The underlying atomic operation uses `Ordering::Release`.
347    #[inline]
348    pub unsafe fn force_read_decrement(&self) {
349        debug_assert!(self.lock.load(Ordering::Relaxed) & !WRITER > 0);
350        self.lock.fetch_sub(READER, Ordering::Release);
351    }
352
353    /// Force unlock exclusive write access.
354    ///
355    /// # Safety
356    ///
357    /// This is *extremely* unsafe if there are outstanding `RwLockWriteGuard`s
358    /// live, or if called when there are current readers, but can be useful in
359    /// FFI contexts where the caller doesn't know how to deal with RAII. The
360    /// underlying atomic operation uses `Ordering::Release`.
361    #[inline]
362    pub unsafe fn force_write_unlock(&self) {
363        debug_assert_eq!(self.lock.load(Ordering::Relaxed) & !(WRITER | UPGRADED), 0);
364        self.lock.fetch_and(!(WRITER | UPGRADED), Ordering::Release);
365    }
366
367    #[inline(always)]
368    fn try_write_internal(&self, strong: bool) -> Option<RwLockWriteGuard<'_, T, R>> {
369        if compare_exchange(
370            &self.lock,
371            0,
372            WRITER,
373            Ordering::Acquire,
374            Ordering::Relaxed,
375            strong,
376        )
377        .is_ok()
378        {
379            Some(RwLockWriteGuard { inner: self })
380        } else {
381            None
382        }
383    }
384
385    /// Attempt to lock this rwlock with exclusive write access.
386    ///
387    /// This function does not ever block, and it will return `None` if a call
388    /// to `write` would otherwise block. If successful, an RAII guard is
389    /// returned.
390    ///
391    /// ```
392    /// let mylock = spin::RwLock::new(0);
393    /// {
394    ///     match mylock.try_write() {
395    ///         Some(mut data) => {
396    ///             // The lock is now locked and the data can be written
397    ///             *data += 1;
398    ///             // The lock is implicitly dropped
399    ///         },
400    ///         None => (), // no cigar
401    ///     };
402    /// }
403    /// ```
404    #[inline]
405    pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, T, R>> {
406        self.try_write_internal(true)
407    }
408
409    /// Attempt to lock this rwlock with exclusive write access.
410    ///
411    /// Unlike [`RwLock::try_write`], this function is allowed to spuriously fail even when acquiring exclusive write access
412    /// would otherwise succeed, which can result in more efficient code on some platforms.
413    #[inline]
414    pub fn try_write_weak(&self) -> Option<RwLockWriteGuard<'_, T, R>> {
415        self.try_write_internal(false)
416    }
417
418    /// Tries to obtain an upgradeable lock guard.
419    #[inline]
420    pub fn try_upgradeable_read(&self) -> Option<RwLockUpgradableGuard<'_, T, R>> {
421        if self.lock.fetch_or(UPGRADED, Ordering::Acquire) & (WRITER | UPGRADED) == 0 {
422            Some(RwLockUpgradableGuard { inner: self })
423        } else {
424            // We can't unflip the UPGRADED bit back just yet as there is another upgradeable or write lock.
425            // When they unlock, they will clear the bit.
426            None
427        }
428    }
429
430    /// Returns a mutable reference to the underlying data.
431    ///
432    /// Since this call borrows the `RwLock` mutably, no actual locking needs to
433    /// take place -- the mutable borrow statically guarantees no locks exist.
434    ///
435    /// # Examples
436    ///
437    /// ```
438    /// let mut lock = spin::RwLock::new(0);
439    /// *lock.get_mut() = 10;
440    /// assert_eq!(*lock.read(), 10);
441    /// ```
442    pub fn get_mut(&mut self) -> &mut T {
443        // We know statically that there are no other references to `self`, so
444        // there's no need to lock the inner lock.
445        unsafe { &mut *self.data.get() }
446    }
447}
448
449impl<T: ?Sized + fmt::Debug, R> fmt::Debug for RwLock<T, R> {
450    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
451        match self.try_read() {
452            Some(guard) => write!(f, "RwLock {{ data: ")
453                .and_then(|()| (*guard).fmt(f))
454                .and_then(|()| write!(f, " }}")),
455            None => write!(f, "RwLock {{ <locked> }}"),
456        }
457    }
458}
459
460impl<T: Default, R> Default for RwLock<T, R> {
461    fn default() -> Self {
462        Self::new(Default::default())
463    }
464}
465
466impl<T, R> From<T> for RwLock<T, R> {
467    fn from(data: T) -> Self {
468        Self::new(data)
469    }
470}
471
472impl<'rwlock, T: ?Sized, R> RwLockReadGuard<'rwlock, T, R> {
473    /// Leak the lock guard, yielding a reference to the underlying data.
474    ///
475    /// Note that this function will permanently lock the original lock for all but reading locks.
476    ///
477    /// ```
478    /// let mylock = spin::RwLock::new(0);
479    ///
480    /// let data: &i32 = spin::RwLockReadGuard::leak(mylock.read());
481    ///
482    /// assert_eq!(*data, 0);
483    /// ```
484    #[inline]
485    pub fn leak(this: Self) -> &'rwlock T {
486        let this = ManuallyDrop::new(this);
487        // Safety: We know statically that only we are referencing data
488        unsafe { &*this.inner.data.get() }
489    }
490}
491
492impl<'rwlock, T: ?Sized + fmt::Debug, R> fmt::Debug for RwLockReadGuard<'rwlock, T, R> {
493    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
494        fmt::Debug::fmt(&**self, f)
495    }
496}
497
498impl<'rwlock, T: ?Sized + fmt::Display, R> fmt::Display for RwLockReadGuard<'rwlock, T, R> {
499    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
500        fmt::Display::fmt(&**self, f)
501    }
502}
503
504impl<'rwlock, T: ?Sized, R: RelaxStrategy> RwLockUpgradableGuard<'rwlock, T, R> {
505    /// Upgrades an upgradeable lock guard to a writable lock guard.
506    ///
507    /// ```
508    /// let mylock = spin::RwLock::new(0);
509    ///
510    /// let upgradeable = mylock.upgradeable_read(); // Readable, but not yet writable
511    /// let writable = upgradeable.upgrade();
512    /// ```
513    #[inline]
514    pub fn upgrade(mut self) -> RwLockWriteGuard<'rwlock, T, R> {
515        loop {
516            self = match self.try_upgrade_internal(false) {
517                Ok(guard) => return guard,
518                Err(e) => e,
519            };
520
521            R::relax();
522        }
523    }
524}
525
526impl<'rwlock, T: ?Sized, R> RwLockUpgradableGuard<'rwlock, T, R> {
527    #[inline(always)]
528    fn try_upgrade_internal(self, strong: bool) -> Result<RwLockWriteGuard<'rwlock, T, R>, Self> {
529        if compare_exchange(
530            &self.inner.lock,
531            UPGRADED,
532            WRITER,
533            Ordering::Acquire,
534            Ordering::Relaxed,
535            strong,
536        )
537        .is_ok()
538        {
539            let inner = self.inner;
540
541            // Forget the old guard so its destructor doesn't run (before mutably aliasing data below)
542            mem::forget(self);
543
544            // Upgrade successful
545            Ok(RwLockWriteGuard { inner })
546        } else {
547            Err(self)
548        }
549    }
550
551    /// Tries to upgrade an upgradeable lock guard to a writable lock guard.
552    ///
553    /// ```
554    /// let mylock = spin::RwLock::new(0);
555    /// let upgradeable = mylock.upgradeable_read(); // Readable, but not yet writable
556    ///
557    /// match upgradeable.try_upgrade() {
558    ///     Ok(writable) => /* upgrade successful - use writable lock guard */ (),
559    ///     Err(upgradeable) => /* upgrade unsuccessful */ (),
560    /// };
561    /// ```
562    #[inline]
563    pub fn try_upgrade(self) -> Result<RwLockWriteGuard<'rwlock, T, R>, Self> {
564        self.try_upgrade_internal(true)
565    }
566
567    /// Tries to upgrade an upgradeable lock guard to a writable lock guard.
568    ///
569    /// Unlike [`RwLockUpgradableGuard::try_upgrade`], this function is allowed to spuriously fail even when upgrading
570    /// would otherwise succeed, which can result in more efficient code on some platforms.
571    #[inline]
572    pub fn try_upgrade_weak(self) -> Result<RwLockWriteGuard<'rwlock, T, R>, Self> {
573        self.try_upgrade_internal(false)
574    }
575
576    #[inline]
577    /// Downgrades the upgradeable lock guard to a readable, shared lock guard. Cannot fail and is guaranteed not to spin.
578    ///
579    /// ```
580    /// let mylock = spin::RwLock::new(1);
581    ///
582    /// let upgradeable = mylock.upgradeable_read();
583    /// assert!(mylock.try_read().is_none());
584    /// assert_eq!(*upgradeable, 1);
585    ///
586    /// let readable = upgradeable.downgrade(); // This is guaranteed not to spin
587    /// assert!(mylock.try_read().is_some());
588    /// assert_eq!(*readable, 1);
589    /// ```
590    pub fn downgrade(self) -> RwLockReadGuard<'rwlock, T, R> {
591        // Reserve the read guard for ourselves
592        self.inner.acquire_reader();
593
594        let inner = self.inner;
595
596        // Dropping self removes the UPGRADED bit
597        mem::drop(self);
598
599        RwLockReadGuard { inner }
600    }
601
602    /// Leak the lock guard, yielding a reference to the underlying data.
603    ///
604    /// Note that this function will permanently lock the original lock.
605    ///
606    /// ```
607    /// let mylock = spin::RwLock::new(0);
608    ///
609    /// let data: &i32 = spin::RwLockUpgradableGuard::leak(mylock.upgradeable_read());
610    ///
611    /// assert_eq!(*data, 0);
612    /// ```
613    #[inline]
614    pub fn leak(this: Self) -> &'rwlock T {
615        let this = ManuallyDrop::new(this);
616        // Safety: We know statically that only we are referencing data
617        unsafe { &*this.inner.data.get() }
618    }
619}
620
621impl<'rwlock, T: ?Sized + fmt::Debug, R> fmt::Debug for RwLockUpgradableGuard<'rwlock, T, R> {
622    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
623        fmt::Debug::fmt(&**self, f)
624    }
625}
626
627impl<'rwlock, T: ?Sized + fmt::Display, R> fmt::Display for RwLockUpgradableGuard<'rwlock, T, R> {
628    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
629        fmt::Display::fmt(&**self, f)
630    }
631}
632
633impl<'rwlock, T: ?Sized, R> RwLockWriteGuard<'rwlock, T, R> {
634    /// Downgrades the writable lock guard to a readable, shared lock guard. Cannot fail and is guaranteed not to spin.
635    ///
636    /// ```
637    /// let mylock = spin::RwLock::new(0);
638    ///
639    /// let mut writable = mylock.write();
640    /// *writable = 1;
641    ///
642    /// let readable = writable.downgrade(); // This is guaranteed not to spin
643    /// # let readable_2 = mylock.try_read().unwrap();
644    /// assert_eq!(*readable, 1);
645    /// ```
646    #[inline]
647    pub fn downgrade(self) -> RwLockReadGuard<'rwlock, T, R> {
648        // Reserve the read guard for ourselves
649        self.inner.acquire_reader();
650
651        let inner = self.inner;
652
653        // Dropping self removes the UPGRADED bit
654        mem::drop(self);
655
656        RwLockReadGuard { inner }
657    }
658
659    /// Downgrades the writable lock guard to an upgradable, shared lock guard. Cannot fail and is guaranteed not to spin.
660    ///
661    /// ```
662    /// let mylock = spin::RwLock::new(0);
663    ///
664    /// let mut writable = mylock.write();
665    /// *writable = 1;
666    ///
667    /// let readable = writable.downgrade_to_upgradeable(); // This is guaranteed not to spin
668    /// assert_eq!(*readable, 1);
669    /// ```
670    #[inline]
671    pub fn downgrade_to_upgradeable(self) -> RwLockUpgradableGuard<'rwlock, T, R> {
672        debug_assert_eq!(
673            self.inner.lock.load(Ordering::Acquire) & (WRITER | UPGRADED),
674            WRITER
675        );
676
677        // Reserve the read guard for ourselves
678        self.inner.lock.store(UPGRADED, Ordering::Release);
679
680        let inner = self.inner;
681
682        // Dropping self removes the UPGRADED bit
683        mem::forget(self);
684
685        RwLockUpgradableGuard { inner }
686    }
687
688    /// Leak the lock guard, yielding a mutable reference to the underlying data.
689    ///
690    /// Note that this function will permanently lock the original lock.
691    ///
692    /// ```
693    /// let mylock = spin::RwLock::new(0);
694    ///
695    /// let data: &mut i32 = spin::RwLockWriteGuard::leak(mylock.write());
696    ///
697    /// *data = 1;
698    /// assert_eq!(*data, 1);
699    /// ```
700    #[inline]
701    pub fn leak(this: Self) -> &'rwlock mut T {
702        let this = ManuallyDrop::new(this);
703        // Safety: We know statically that only we are referencing data
704        unsafe { &mut *this.inner.data.get() }
705    }
706}
707
708impl<'rwlock, T: ?Sized + fmt::Debug, R> fmt::Debug for RwLockWriteGuard<'rwlock, T, R> {
709    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
710        fmt::Debug::fmt(&**self, f)
711    }
712}
713
714impl<'rwlock, T: ?Sized + fmt::Display, R> fmt::Display for RwLockWriteGuard<'rwlock, T, R> {
715    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
716        fmt::Display::fmt(&**self, f)
717    }
718}
719
720impl<'rwlock, T: ?Sized, R> Deref for RwLockReadGuard<'rwlock, T, R> {
721    type Target = T;
722
723    fn deref(&self) -> &T {
724        // Safety: We know statically that only we are referencing data
725        unsafe { &*self.inner.data.get() }
726    }
727}
728
729impl<'rwlock, T: ?Sized, R> Deref for RwLockUpgradableGuard<'rwlock, T, R> {
730    type Target = T;
731
732    fn deref(&self) -> &T {
733        // Safety: We know statically that only we are referencing data
734        unsafe { &*self.inner.data.get() }
735    }
736}
737
738impl<'rwlock, T: ?Sized, R> Deref for RwLockWriteGuard<'rwlock, T, R> {
739    type Target = T;
740
741    fn deref(&self) -> &T {
742        // Safety: We know statically that only we are referencing data
743        unsafe { &*self.inner.data.get() }
744    }
745}
746
747impl<'rwlock, T: ?Sized, R> DerefMut for RwLockWriteGuard<'rwlock, T, R> {
748    fn deref_mut(&mut self) -> &mut T {
749        // Safety: We know statically that only we are referencing data
750        unsafe { &mut *self.inner.data.get() }
751    }
752}
753
754impl<'rwlock, T: ?Sized, R> Drop for RwLockReadGuard<'rwlock, T, R> {
755    fn drop(&mut self) {
756        debug_assert!(self.inner.lock.load(Ordering::Relaxed) & !(WRITER | UPGRADED) > 0);
757        self.inner.lock.fetch_sub(READER, Ordering::Release);
758    }
759}
760
761impl<'rwlock, T: ?Sized, R> Drop for RwLockUpgradableGuard<'rwlock, T, R> {
762    fn drop(&mut self) {
763        debug_assert_eq!(
764            self.inner.lock.load(Ordering::Relaxed) & (WRITER | UPGRADED),
765            UPGRADED
766        );
767        self.inner.lock.fetch_sub(UPGRADED, Ordering::AcqRel);
768    }
769}
770
771impl<'rwlock, T: ?Sized, R> Drop for RwLockWriteGuard<'rwlock, T, R> {
772    fn drop(&mut self) {
773        debug_assert_eq!(self.inner.lock.load(Ordering::Relaxed) & WRITER, WRITER);
774
775        // Writer is responsible for clearing both WRITER and UPGRADED bits.
776        // The UPGRADED bit may be set if an upgradeable lock attempts an upgrade while this lock is held.
777        self.inner
778            .lock
779            .fetch_and(!(WRITER | UPGRADED), Ordering::Release);
780    }
781}
782
783#[inline(always)]
784fn compare_exchange(
785    atomic: &AtomicUsize,
786    current: usize,
787    new: usize,
788    success: Ordering,
789    failure: Ordering,
790    strong: bool,
791) -> Result<usize, usize> {
792    if strong {
793        atomic.compare_exchange(current, new, success, failure)
794    } else {
795        atomic.compare_exchange_weak(current, new, success, failure)
796    }
797}
798
799#[cfg(feature = "lock_api")]
800unsafe impl<R: RelaxStrategy> lock_api_crate::RawRwLock for RwLock<(), R> {
801    type GuardMarker = lock_api_crate::GuardSend;
802
803    const INIT: Self = Self::new(());
804
805    #[inline(always)]
806    fn lock_exclusive(&self) {
807        // Prevent guard destructor running
808        core::mem::forget(self.write());
809    }
810
811    #[inline(always)]
812    fn try_lock_exclusive(&self) -> bool {
813        // Prevent guard destructor running
814        self.try_write().map(core::mem::forget).is_some()
815    }
816
817    #[inline(always)]
818    unsafe fn unlock_exclusive(&self) {
819        drop(RwLockWriteGuard { inner: self });
820    }
821
822    #[inline(always)]
823    fn lock_shared(&self) {
824        // Prevent guard destructor running
825        core::mem::forget(self.read());
826    }
827
828    #[inline(always)]
829    fn try_lock_shared(&self) -> bool {
830        // Prevent guard destructor running
831        self.try_read().map(core::mem::forget).is_some()
832    }
833
834    #[inline(always)]
835    unsafe fn unlock_shared(&self) {
836        drop(RwLockReadGuard { inner: self });
837    }
838
839    #[inline(always)]
840    fn is_locked(&self) -> bool {
841        self.lock.load(Ordering::Relaxed) != 0
842    }
843}
844
845#[cfg(feature = "lock_api")]
846unsafe impl<R: RelaxStrategy> lock_api_crate::RawRwLockUpgrade for RwLock<(), R> {
847    #[inline(always)]
848    fn lock_upgradable(&self) {
849        // Prevent guard destructor running
850        core::mem::forget(self.upgradeable_read());
851    }
852
853    #[inline(always)]
854    fn try_lock_upgradable(&self) -> bool {
855        // Prevent guard destructor running
856        self.try_upgradeable_read().map(core::mem::forget).is_some()
857    }
858
859    #[inline(always)]
860    unsafe fn unlock_upgradable(&self) {
861        drop(RwLockUpgradableGuard { inner: self });
862    }
863
864    #[inline(always)]
865    unsafe fn upgrade(&self) {
866        let tmp_guard = RwLockUpgradableGuard { inner: self };
867        core::mem::forget(tmp_guard.upgrade());
868    }
869
870    #[inline(always)]
871    unsafe fn try_upgrade(&self) -> bool {
872        let tmp_guard = RwLockUpgradableGuard { inner: self };
873        let res = tmp_guard.try_upgrade();
874        let success = res.is_ok();
875        // We act 'as if' the guards still exist to maintain the lock state
876        core::mem::forget(res);
877        success
878    }
879}
880
881#[cfg(feature = "lock_api")]
882unsafe impl<R: RelaxStrategy> lock_api_crate::RawRwLockDowngrade for RwLock<(), R> {
883    unsafe fn downgrade(&self) {
884        let tmp_guard = RwLockWriteGuard { inner: self };
885        core::mem::forget(tmp_guard.downgrade());
886    }
887}
888
889#[cfg(feature = "lock_api")]
890unsafe impl<R: RelaxStrategy> lock_api_crate::RawRwLockUpgradeDowngrade for RwLock<(), R> {
891    unsafe fn downgrade_upgradable(&self) {
892        let tmp_guard = RwLockUpgradableGuard { inner: self };
893        core::mem::forget(tmp_guard.downgrade());
894    }
895
896    unsafe fn downgrade_to_upgradable(&self) {
897        let tmp_guard = RwLockWriteGuard { inner: self };
898        core::mem::forget(tmp_guard.downgrade_to_upgradeable());
899    }
900}
901
902#[cfg(test)]
903mod tests {
904    use std::prelude::v1::*;
905
906    use std::sync::atomic::{AtomicUsize, Ordering};
907    use std::sync::mpsc::channel;
908    use std::sync::Arc;
909    use std::thread;
910
911    type RwLock<T> = super::RwLock<T>;
912
913    #[derive(Eq, PartialEq, Debug)]
914    struct NonCopy(i32);
915
916    #[test]
917    fn smoke() {
918        let l = RwLock::new(());
919        drop(l.read());
920        drop(l.write());
921        drop((l.read(), l.read()));
922        drop(l.write());
923    }
924
925    // TODO: needs RNG
926    //#[test]
927    //fn frob() {
928    //    static R: RwLock = RwLock::new();
929    //    const N: usize = 10;
930    //    const M: usize = 1000;
931    //
932    //    let (tx, rx) = channel::<()>();
933    //    for _ in 0..N {
934    //        let tx = tx.clone();
935    //        thread::spawn(move|| {
936    //            let mut rng = rand::thread_rng();
937    //            for _ in 0..M {
938    //                if rng.gen_weighted_bool(N) {
939    //                    drop(R.write());
940    //                } else {
941    //                    drop(R.read());
942    //                }
943    //            }
944    //            drop(tx);
945    //        });
946    //    }
947    //    drop(tx);
948    //    let _ = rx.recv();
949    //    unsafe { R.destroy(); }
950    //}
951
952    #[test]
953    fn test_rw_arc() {
954        let arc = Arc::new(RwLock::new(0));
955        let arc2 = arc.clone();
956        let (tx, rx) = channel();
957
958        let t = thread::spawn(move || {
959            let mut lock = arc2.write();
960            for _ in 0..10 {
961                let tmp = *lock;
962                *lock = -1;
963                thread::yield_now();
964                *lock = tmp + 1;
965            }
966            tx.send(()).unwrap();
967        });
968
969        // Readers try to catch the writer in the act
970        let mut children = Vec::new();
971        for _ in 0..5 {
972            let arc3 = arc.clone();
973            children.push(thread::spawn(move || {
974                let lock = arc3.read();
975                assert!(*lock >= 0);
976            }));
977        }
978
979        // Wait for children to pass their asserts
980        for r in children {
981            assert!(r.join().is_ok());
982        }
983
984        // Wait for writer to finish
985        rx.recv().unwrap();
986        let lock = arc.read();
987        assert_eq!(*lock, 10);
988
989        assert!(t.join().is_ok());
990    }
991
992    #[test]
993    fn test_rw_access_in_unwind() {
994        let arc = Arc::new(RwLock::new(1));
995        let arc2 = arc.clone();
996        let _ = thread::spawn(move || -> () {
997            struct Unwinder {
998                i: Arc<RwLock<isize>>,
999            }
1000            impl Drop for Unwinder {
1001                fn drop(&mut self) {
1002                    let mut lock = self.i.write();
1003                    *lock += 1;
1004                }
1005            }
1006            let _u = Unwinder { i: arc2 };
1007            panic!();
1008        })
1009        .join();
1010        let lock = arc.read();
1011        assert_eq!(*lock, 2);
1012    }
1013
1014    #[test]
1015    fn test_rwlock_unsized() {
1016        let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]);
1017        {
1018            let b = &mut *rw.write();
1019            b[0] = 4;
1020            b[2] = 5;
1021        }
1022        let comp: &[i32] = &[4, 2, 5];
1023        assert_eq!(&*rw.read(), comp);
1024    }
1025
1026    #[test]
1027    fn test_rwlock_try_write() {
1028        use std::mem::drop;
1029
1030        let lock = RwLock::new(0isize);
1031        let read_guard = lock.read();
1032
1033        if lock.try_write().is_some() {
1034            panic!("try_write should not succeed while read_guard is in scope");
1035        }
1036
1037        drop(read_guard);
1038    }
1039
1040    #[test]
1041    fn test_rw_try_read() {
1042        let m = RwLock::new(0);
1043        ::std::mem::forget(m.write());
1044        assert!(m.try_read().is_none());
1045    }
1046
1047    #[test]
1048    fn test_into_inner() {
1049        let m = RwLock::new(NonCopy(10));
1050        assert_eq!(m.into_inner(), NonCopy(10));
1051    }
1052
1053    #[test]
1054    fn test_into_inner_drop() {
1055        struct Foo(Arc<AtomicUsize>);
1056        impl Drop for Foo {
1057            fn drop(&mut self) {
1058                self.0.fetch_add(1, Ordering::SeqCst);
1059            }
1060        }
1061        let num_drops = Arc::new(AtomicUsize::new(0));
1062        let m = RwLock::new(Foo(num_drops.clone()));
1063        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
1064        {
1065            let _inner = m.into_inner();
1066            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
1067        }
1068        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
1069    }
1070
1071    #[test]
1072    fn test_force_read_decrement() {
1073        let m = RwLock::new(());
1074        ::std::mem::forget(m.read());
1075        ::std::mem::forget(m.read());
1076        ::std::mem::forget(m.read());
1077        assert!(m.try_write().is_none());
1078        unsafe {
1079            m.force_read_decrement();
1080            m.force_read_decrement();
1081        }
1082        assert!(m.try_write().is_none());
1083        unsafe {
1084            m.force_read_decrement();
1085        }
1086        assert!(m.try_write().is_some());
1087    }
1088
1089    #[test]
1090    fn test_force_write_unlock() {
1091        let m = RwLock::new(());
1092        ::std::mem::forget(m.write());
1093        assert!(m.try_read().is_none());
1094        unsafe {
1095            m.force_write_unlock();
1096        }
1097        assert!(m.try_read().is_some());
1098    }
1099
1100    #[test]
1101    fn test_upgrade_downgrade() {
1102        let m = RwLock::new(());
1103        {
1104            let _r = m.read();
1105            let upg = m.try_upgradeable_read().unwrap();
1106            assert!(m.try_read().is_none());
1107            assert!(m.try_write().is_none());
1108            assert!(upg.try_upgrade().is_err());
1109        }
1110        {
1111            let w = m.write();
1112            assert!(m.try_upgradeable_read().is_none());
1113            let _r = w.downgrade();
1114            assert!(m.try_upgradeable_read().is_some());
1115            assert!(m.try_read().is_some());
1116            assert!(m.try_write().is_none());
1117        }
1118        {
1119            let _u = m.upgradeable_read();
1120            assert!(m.try_upgradeable_read().is_none());
1121        }
1122
1123        assert!(m.try_upgradeable_read().unwrap().try_upgrade().is_ok());
1124    }
1125
1126    #[test]
1127    fn no_premature_upgrade_drop_on_failure() {
1128        type RwLock<T> = lock_api_crate::RwLock<crate::rwlock::RwLock<()>, T>;
1129
1130        let lock = Arc::new(RwLock::new(42));
1131        std::thread::scope(|s| {
1132            let shared = lock.try_read().expect("shared read should succeed");
1133            let upgradable = lock.upgradable_read();
1134
1135            // Previously, UB occurred here: `try_upgrade` failure resulted in a temporary guard
1136            // being dropped, resulting in the UPGRADED bit being unset, leaving the lock unguarded.
1137            // This is not correct because upgrade failure shouldn't leave the lock open for writers
1138            let upgradable =
1139                match lock_api_crate::RwLockUpgradableReadGuard::try_upgrade(upgradable) {
1140                    Ok(_) => panic!("upgrade unexpectedly succeeded"),
1141                    Err(g) => g,
1142                };
1143
1144            drop(shared);
1145
1146            s.spawn(|| {
1147                if lock.try_write().is_some() {
1148                    panic!("try_write should not succeed because lock is held");
1149                }
1150            })
1151            .join()
1152            .unwrap();
1153
1154            std::hint::black_box(*upgradable);
1155
1156            core::mem::forget(upgradable);
1157        });
1158    }
1159}