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}