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        tmp_guard.try_upgrade().map(core::mem::forget).is_ok()
874    }
875}
876
877#[cfg(feature = "lock_api")]
878unsafe impl<R: RelaxStrategy> lock_api_crate::RawRwLockDowngrade for RwLock<(), R> {
879    unsafe fn downgrade(&self) {
880        let tmp_guard = RwLockWriteGuard { inner: self };
881        core::mem::forget(tmp_guard.downgrade());
882    }
883}
884
885#[cfg(feature = "lock_api")]
886unsafe impl<R: RelaxStrategy> lock_api_crate::RawRwLockUpgradeDowngrade for RwLock<(), R> {
887    unsafe fn downgrade_upgradable(&self) {
888        let tmp_guard = RwLockUpgradableGuard { inner: self };
889        core::mem::forget(tmp_guard.downgrade());
890    }
891
892    unsafe fn downgrade_to_upgradable(&self) {
893        let tmp_guard = RwLockWriteGuard { inner: self };
894        core::mem::forget(tmp_guard.downgrade_to_upgradeable());
895    }
896}
897
898#[cfg(test)]
899mod tests {
900    use std::prelude::v1::*;
901
902    use std::sync::atomic::{AtomicUsize, Ordering};
903    use std::sync::mpsc::channel;
904    use std::sync::Arc;
905    use std::thread;
906
907    type RwLock<T> = super::RwLock<T>;
908
909    #[derive(Eq, PartialEq, Debug)]
910    struct NonCopy(i32);
911
912    #[test]
913    fn smoke() {
914        let l = RwLock::new(());
915        drop(l.read());
916        drop(l.write());
917        drop((l.read(), l.read()));
918        drop(l.write());
919    }
920
921    // TODO: needs RNG
922    //#[test]
923    //fn frob() {
924    //    static R: RwLock = RwLock::new();
925    //    const N: usize = 10;
926    //    const M: usize = 1000;
927    //
928    //    let (tx, rx) = channel::<()>();
929    //    for _ in 0..N {
930    //        let tx = tx.clone();
931    //        thread::spawn(move|| {
932    //            let mut rng = rand::thread_rng();
933    //            for _ in 0..M {
934    //                if rng.gen_weighted_bool(N) {
935    //                    drop(R.write());
936    //                } else {
937    //                    drop(R.read());
938    //                }
939    //            }
940    //            drop(tx);
941    //        });
942    //    }
943    //    drop(tx);
944    //    let _ = rx.recv();
945    //    unsafe { R.destroy(); }
946    //}
947
948    #[test]
949    fn test_rw_arc() {
950        let arc = Arc::new(RwLock::new(0));
951        let arc2 = arc.clone();
952        let (tx, rx) = channel();
953
954        let t = thread::spawn(move || {
955            let mut lock = arc2.write();
956            for _ in 0..10 {
957                let tmp = *lock;
958                *lock = -1;
959                thread::yield_now();
960                *lock = tmp + 1;
961            }
962            tx.send(()).unwrap();
963        });
964
965        // Readers try to catch the writer in the act
966        let mut children = Vec::new();
967        for _ in 0..5 {
968            let arc3 = arc.clone();
969            children.push(thread::spawn(move || {
970                let lock = arc3.read();
971                assert!(*lock >= 0);
972            }));
973        }
974
975        // Wait for children to pass their asserts
976        for r in children {
977            assert!(r.join().is_ok());
978        }
979
980        // Wait for writer to finish
981        rx.recv().unwrap();
982        let lock = arc.read();
983        assert_eq!(*lock, 10);
984
985        assert!(t.join().is_ok());
986    }
987
988    #[test]
989    fn test_rw_access_in_unwind() {
990        let arc = Arc::new(RwLock::new(1));
991        let arc2 = arc.clone();
992        let _ = thread::spawn(move || -> () {
993            struct Unwinder {
994                i: Arc<RwLock<isize>>,
995            }
996            impl Drop for Unwinder {
997                fn drop(&mut self) {
998                    let mut lock = self.i.write();
999                    *lock += 1;
1000                }
1001            }
1002            let _u = Unwinder { i: arc2 };
1003            panic!();
1004        })
1005        .join();
1006        let lock = arc.read();
1007        assert_eq!(*lock, 2);
1008    }
1009
1010    #[test]
1011    fn test_rwlock_unsized() {
1012        let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]);
1013        {
1014            let b = &mut *rw.write();
1015            b[0] = 4;
1016            b[2] = 5;
1017        }
1018        let comp: &[i32] = &[4, 2, 5];
1019        assert_eq!(&*rw.read(), comp);
1020    }
1021
1022    #[test]
1023    fn test_rwlock_try_write() {
1024        use std::mem::drop;
1025
1026        let lock = RwLock::new(0isize);
1027        let read_guard = lock.read();
1028
1029        if lock.try_write().is_some() {
1030            panic!("try_write should not succeed while read_guard is in scope");
1031        }
1032
1033        drop(read_guard);
1034    }
1035
1036    #[test]
1037    fn test_rw_try_read() {
1038        let m = RwLock::new(0);
1039        ::std::mem::forget(m.write());
1040        assert!(m.try_read().is_none());
1041    }
1042
1043    #[test]
1044    fn test_into_inner() {
1045        let m = RwLock::new(NonCopy(10));
1046        assert_eq!(m.into_inner(), NonCopy(10));
1047    }
1048
1049    #[test]
1050    fn test_into_inner_drop() {
1051        struct Foo(Arc<AtomicUsize>);
1052        impl Drop for Foo {
1053            fn drop(&mut self) {
1054                self.0.fetch_add(1, Ordering::SeqCst);
1055            }
1056        }
1057        let num_drops = Arc::new(AtomicUsize::new(0));
1058        let m = RwLock::new(Foo(num_drops.clone()));
1059        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
1060        {
1061            let _inner = m.into_inner();
1062            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
1063        }
1064        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
1065    }
1066
1067    #[test]
1068    fn test_force_read_decrement() {
1069        let m = RwLock::new(());
1070        ::std::mem::forget(m.read());
1071        ::std::mem::forget(m.read());
1072        ::std::mem::forget(m.read());
1073        assert!(m.try_write().is_none());
1074        unsafe {
1075            m.force_read_decrement();
1076            m.force_read_decrement();
1077        }
1078        assert!(m.try_write().is_none());
1079        unsafe {
1080            m.force_read_decrement();
1081        }
1082        assert!(m.try_write().is_some());
1083    }
1084
1085    #[test]
1086    fn test_force_write_unlock() {
1087        let m = RwLock::new(());
1088        ::std::mem::forget(m.write());
1089        assert!(m.try_read().is_none());
1090        unsafe {
1091            m.force_write_unlock();
1092        }
1093        assert!(m.try_read().is_some());
1094    }
1095
1096    #[test]
1097    fn test_upgrade_downgrade() {
1098        let m = RwLock::new(());
1099        {
1100            let _r = m.read();
1101            let upg = m.try_upgradeable_read().unwrap();
1102            assert!(m.try_read().is_none());
1103            assert!(m.try_write().is_none());
1104            assert!(upg.try_upgrade().is_err());
1105        }
1106        {
1107            let w = m.write();
1108            assert!(m.try_upgradeable_read().is_none());
1109            let _r = w.downgrade();
1110            assert!(m.try_upgradeable_read().is_some());
1111            assert!(m.try_read().is_some());
1112            assert!(m.try_write().is_none());
1113        }
1114        {
1115            let _u = m.upgradeable_read();
1116            assert!(m.try_upgradeable_read().is_none());
1117        }
1118
1119        assert!(m.try_upgradeable_read().unwrap().try_upgrade().is_ok());
1120    }
1121}