diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-06-15 21:44:30 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-06-15 21:44:30 +0000 |
commit | 9b611f95ea7f7d5e89d2dd8e82bfbc1efbb4e021 (patch) | |
tree | 2463dc1fc3604e2b96a0e336af6b3d2cf0fff867 | |
parent | ce53fc365b446e1304c4fff6bef40df9bef8cbb4 (diff) | |
parent | f7b39d462728d7e5dfb7c8cb27007cde42ebbc7b (diff) | |
download | lock_api-aml_tz3_314012010.tar.gz |
Snap for 8730993 from f7b39d462728d7e5dfb7c8cb27007cde42ebbc7b to mainline-tzdata3-releaseaml_tz3_314012070aml_tz3_314012050aml_tz3_314012010aml_tz3_313110000aml_tz3_312511020aml_tz3_312511010aml_tz3_312410020aml_tz3_312410010android12-mainline-tzdata3-releaseaml_tz3_314012010
Change-Id: Ie9e7fa2072795e5173ec1b3921c5649a35e90ab6
-rw-r--r-- | .cargo_vcs_info.json | 7 | ||||
-rw-r--r-- | Android.bp | 34 | ||||
-rw-r--r-- | Cargo.toml | 14 | ||||
-rw-r--r-- | Cargo.toml.orig | 5 | ||||
-rw-r--r-- | METADATA | 10 | ||||
-rw-r--r-- | TEST_MAPPING | 6 | ||||
-rw-r--r-- | cargo2android.json | 11 | ||||
-rw-r--r-- | src/lib.rs | 9 | ||||
-rw-r--r-- | src/mutex.rs | 189 | ||||
-rw-r--r-- | src/remutex.rs | 197 | ||||
-rw-r--r-- | src/rwlock.rs | 828 |
11 files changed, 47 insertions, 1263 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index 9ed45c2..e1a0b04 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,5 @@ { "git": { - "sha1": "a75875b0bf904287a9749e8eabea919b5e9dd8a9" - }, - "path_in_vcs": "lock_api" -}
\ No newline at end of file + "sha1": "86969fd7baf94312520e0b5a5f3b0861a0fd411b" + } +} @@ -1,5 +1,4 @@ -// This file is generated by cargo2android.py --config cargo2android.json. -// Do not modify this file as changes will be overridden on upgrade. +// This file is generated by cargo2android.py --run --device --dependencies --tests. package { default_applicable_licenses: ["external_rust_crates_lock_api_license"], @@ -41,17 +40,34 @@ rust_library { name: "liblock_api", host_supported: true, crate_name: "lock_api", - cargo_env_compat: true, - cargo_pkg_version: "0.4.6", srcs: ["src/lib.rs"], edition: "2018", rustlibs: [ "libscopeguard", ], - apex_available: [ - "//apex_available:platform", - "com.android.bluetooth", - "com.android.virt", +} + +rust_defaults { + name: "lock_api_defaults", + crate_name: "lock_api", + srcs: ["src/lib.rs"], + test_suites: ["general-tests"], + auto_gen_config: true, + edition: "2018", + rustlibs: [ + "libscopeguard", ], - min_sdk_version: "29", } + +rust_test_host { + name: "lock_api_host_test_src_lib", + defaults: ["lock_api_defaults"], +} + +rust_test { + name: "lock_api_device_test_src_lib", + defaults: ["lock_api_defaults"], +} + +// dependent_library ["feature_list"] +// scopeguard-1.1.0 @@ -3,16 +3,17 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. +# to registry (e.g., crates.io) dependencies # -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) [package] edition = "2018" name = "lock_api" -version = "0.4.6" +version = "0.4.2" authors = ["Amanieu d'Antras <amanieu@gmail.com>"] description = "Wrappers to create fully-featured Mutex and RwLock types. Compatible with no_std." keywords = ["mutex", "rwlock", "lock", "no_std"] @@ -28,10 +29,9 @@ version = "1.1.0" default-features = false [dependencies.serde] -version = "1.0.126" +version = "1.0.114" optional = true default-features = false [features] -arc_lock = [] nightly = [] diff --git a/Cargo.toml.orig b/Cargo.toml.orig index e6a805f..9e884a4 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "lock_api" -version = "0.4.6" +version = "0.4.2" authors = ["Amanieu d'Antras <amanieu@gmail.com>"] description = "Wrappers to create fully-featured Mutex and RwLock types. Compatible with no_std." license = "Apache-2.0/MIT" @@ -16,8 +16,7 @@ owning_ref = { version = "0.4.1", optional = true } # Optional dependency for supporting serde. Optional crates automatically # create a feature with the same name as the crate, so if you need serde # support, just pass "--features serde" when building this crate. -serde = { version = "1.0.126", default-features = false, optional = true } +serde = { version = "1.0.114", default-features = false, optional = true } [features] nightly = [] -arc_lock = [] @@ -7,13 +7,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/lock_api/lock_api-0.4.6.crate" + value: "https://static.crates.io/crates/lock_api/lock_api-0.4.2.crate" } - version: "0.4.6" + version: "0.4.2" license_type: NOTICE last_upgrade_date { - year: 2022 - month: 3 - day: 1 + year: 2020 + month: 11 + day: 17 } } diff --git a/TEST_MAPPING b/TEST_MAPPING index f439cf8..738f5ec 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -1,8 +1,8 @@ -// Generated by update_crate_tests.py for tests that depend on this crate. +// Generated by cargo2android.py for tests in Android.bp { - "imports": [ + "presubmit": [ { - "path": "external/rust/crates/vulkano" + "name": "lock_api_device_test_src_lib" } ] } diff --git a/cargo2android.json b/cargo2android.json deleted file mode 100644 index 22531ba..0000000 --- a/cargo2android.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "apex-available": [ - "//apex_available:platform", - "com.android.bluetooth", - "com.android.virt" - ], - "device": true, - "min-sdk-version": "29", - "run": true, - "tests": true -} @@ -79,25 +79,20 @@ //! //! # Cargo features //! -//! This crate supports three cargo features: +//! This crate supports two cargo features: //! //! - `owning_ref`: Allows your lock types to be used with the `owning_ref` crate. -//! - `arc_lock`: Enables locking from an `Arc`. This enables types such as `ArcMutexGuard`. Note that this -//! requires the `alloc` crate to be present. //! - `nightly`: Enables nightly-only features. At the moment the only such //! feature is `const fn` constructors for lock types. #![no_std] #![warn(missing_docs)] #![warn(rust_2018_idioms)] -#![cfg_attr(feature = "nightly", feature(const_fn_trait_bound))] +#![cfg_attr(feature = "nightly", feature(const_fn))] #[macro_use] extern crate scopeguard; -#[cfg(feature = "arc_lock")] -extern crate alloc; - /// Marker type which indicates that the Guard type for a lock is `Send`. pub struct GuardSend(()); diff --git a/src/mutex.rs b/src/mutex.rs index 81c25fb..aded96d 100644 --- a/src/mutex.rs +++ b/src/mutex.rs @@ -11,13 +11,6 @@ use core::marker::PhantomData; use core::mem; use core::ops::{Deref, DerefMut}; -#[cfg(feature = "arc_lock")] -use alloc::sync::Arc; -#[cfg(feature = "arc_lock")] -use core::mem::ManuallyDrop; -#[cfg(feature = "arc_lock")] -use core::ptr; - #[cfg(feature = "owning_ref")] use owning_ref::StableAddress; @@ -293,45 +286,6 @@ impl<R: RawMutex, T: ?Sized> Mutex<R, T> { pub fn data_ptr(&self) -> *mut T { self.data.get() } - - /// # Safety - /// - /// The lock needs to be held for the behavior of this function to be defined. - #[cfg(feature = "arc_lock")] - #[inline] - unsafe fn guard_arc(self: &Arc<Self>) -> ArcMutexGuard<R, T> { - ArcMutexGuard { - mutex: self.clone(), - marker: PhantomData, - } - } - - /// Acquires a lock through an `Arc`. - /// - /// This method is similar to the `lock` method; however, it requires the `Mutex` to be inside of an `Arc` - /// and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn lock_arc(self: &Arc<Self>) -> ArcMutexGuard<R, T> { - self.raw.lock(); - // SAFETY: the locking guarantee is upheld - unsafe { self.guard_arc() } - } - - /// Attempts to acquire a lock through an `Arc`. - /// - /// This method is similar to the `try_lock` method; however, it requires the `Mutex` to be inside of an - /// `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_lock_arc(self: &Arc<Self>) -> Option<ArcMutexGuard<R, T>> { - if self.raw.try_lock() { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.guard_arc() }) - } else { - None - } - } } impl<R: RawMutexFair, T: ?Sized> Mutex<R, T> { @@ -382,39 +336,6 @@ impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> { None } } - - /// Attempts to acquire this lock through an `Arc` until a timeout is reached. - /// - /// This method is similar to the `try_lock_for` method; however, it requires the `Mutex` to be inside of an - /// `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_lock_arc_for(self: &Arc<Self>, timeout: R::Duration) -> Option<ArcMutexGuard<R, T>> { - if self.raw.try_lock_for(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.guard_arc() }) - } else { - None - } - } - - /// Attempts to acquire this lock through an `Arc` until a timeout is reached. - /// - /// This method is similar to the `try_lock_until` method; however, it requires the `Mutex` to be inside of - /// an `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_lock_arc_until( - self: &Arc<Self>, - timeout: R::Instant, - ) -> Option<ArcMutexGuard<R, T>> { - if self.raw.try_lock_until(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.guard_arc() }) - } else { - None - } - } } impl<R: RawMutex, T: ?Sized + Default> Default for Mutex<R, T> { @@ -662,116 +583,6 @@ impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display for Mutex #[cfg(feature = "owning_ref")] unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'a, R, T> {} -/// An RAII mutex guard returned by the `Arc` locking operations on `Mutex`. -/// -/// This is similar to the `MutexGuard` struct, except instead of using a reference to unlock the `Mutex` it -/// uses an `Arc<Mutex>`. This has several advantages, most notably that it has an `'static` lifetime. -#[cfg(feature = "arc_lock")] -#[must_use = "if unused the Mutex will immediately unlock"] -pub struct ArcMutexGuard<R: RawMutex, T: ?Sized> { - mutex: Arc<Mutex<R, T>>, - marker: PhantomData<R::GuardMarker>, -} - -#[cfg(feature = "arc_lock")] -impl<R: RawMutex, T: ?Sized> ArcMutexGuard<R, T> { - /// Returns a reference to the `Mutex` this is guarding, contained in its `Arc`. - #[inline] - pub fn mutex(&self) -> &Arc<Mutex<R, T>> { - &self.mutex - } - - /// Temporarily unlocks the mutex to execute the given function. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the mutex. - #[inline] - pub fn unlocked<F, U>(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.mutex.raw.unlock(); - } - defer!(s.mutex.raw.lock()); - f() - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawMutexFair, T: ?Sized> ArcMutexGuard<R, T> { - /// Unlocks the mutex using a fair unlock protocol. - /// - /// This is functionally identical to the `unlock_fair` method on [`MutexGuard`]. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.mutex.raw.unlock_fair(); - } - - // SAFETY: make sure the Arc gets it reference decremented - let mut s = ManuallyDrop::new(s); - unsafe { ptr::drop_in_place(&mut s.mutex) }; - } - - /// Temporarily unlocks the mutex to execute the given function. - /// - /// This is functionally identical to the `unlocked_fair` method on [`MutexGuard`]. - #[inline] - pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.mutex.raw.unlock_fair(); - } - defer!(s.mutex.raw.lock()); - f() - } - - /// Temporarily yields the mutex to a waiting thread if there is one. - /// - /// This is functionally identical to the `bump` method on [`MutexGuard`]. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.mutex.raw.bump(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawMutex, T: ?Sized> Deref for ArcMutexGuard<R, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.mutex.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawMutex, T: ?Sized> DerefMut for ArcMutexGuard<R, T> { - #[inline] - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.mutex.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawMutex, T: ?Sized> Drop for ArcMutexGuard<R, T> { - #[inline] - fn drop(&mut self) { - // Safety: A MutexGuard always holds the lock. - unsafe { - self.mutex.raw.unlock(); - } - } -} - /// An RAII mutex guard returned by `MutexGuard::map`, which can point to a /// subfield of the protected data. /// diff --git a/src/remutex.rs b/src/remutex.rs index dd992b4..09833b0 100644 --- a/src/remutex.rs +++ b/src/remutex.rs @@ -19,13 +19,6 @@ use core::{ sync::atomic::{AtomicUsize, Ordering}, }; -#[cfg(feature = "arc_lock")] -use alloc::sync::Arc; -#[cfg(feature = "arc_lock")] -use core::mem::ManuallyDrop; -#[cfg(feature = "arc_lock")] -use core::ptr; - #[cfg(feature = "owning_ref")] use owning_ref::StableAddress; @@ -142,13 +135,6 @@ impl<R: RawMutex, G: GetThreadId> RawReentrantMutex<R, G> { pub fn is_locked(&self) -> bool { self.mutex.is_locked() } - - /// Checks whether the mutex is currently held by the current thread. - #[inline] - pub fn is_owned_by_current_thread(&self) -> bool { - let id = self.get_thread_id.nonzero_thread_id().get(); - self.owner.load(Ordering::Relaxed) == id - } } impl<R: RawMutexFair, G: GetThreadId> RawReentrantMutex<R, G> { @@ -347,12 +333,6 @@ impl<R: RawMutex, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> { self.raw.is_locked() } - /// Checks whether the mutex is currently held by the current thread. - #[inline] - pub fn is_owned_by_current_thread(&self) -> bool { - self.raw.is_owned_by_current_thread() - } - /// Forcibly unlocks the mutex. /// /// This is useful when combined with `mem::forget` to hold a lock without @@ -399,45 +379,6 @@ impl<R: RawMutex, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> { pub fn data_ptr(&self) -> *mut T { self.data.get() } - - /// # Safety - /// - /// The lock must be held before calling this method. - #[cfg(feature = "arc_lock")] - #[inline] - unsafe fn guard_arc(self: &Arc<Self>) -> ArcReentrantMutexGuard<R, G, T> { - ArcReentrantMutexGuard { - remutex: self.clone(), - marker: PhantomData, - } - } - - /// Acquires a reentrant mutex through an `Arc`. - /// - /// This method is similar to the `lock` method; however, it requires the `ReentrantMutex` to be inside of an - /// `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn lock_arc(self: &Arc<Self>) -> ArcReentrantMutexGuard<R, G, T> { - self.raw.lock(); - // SAFETY: locking guarantee is upheld - unsafe { self.guard_arc() } - } - - /// Attempts to acquire a reentrant mutex through an `Arc`. - /// - /// This method is similar to the `try_lock` method; however, it requires the `ReentrantMutex` to be inside - /// of an `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_lock_arc(self: &Arc<Self>) -> Option<ArcReentrantMutexGuard<R, G, T>> { - if self.raw.try_lock() { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.guard_arc() }) - } else { - None - } - } } impl<R: RawMutexFair, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> { @@ -488,42 +429,6 @@ impl<R: RawMutexTimed, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> { None } } - - /// Attempts to acquire this lock until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_lock_for` method; however, it requires the `ReentrantMutex` to be - /// inside of an `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_lock_arc_for( - self: &Arc<Self>, - timeout: R::Duration, - ) -> Option<ArcReentrantMutexGuard<R, G, T>> { - if self.raw.try_lock_for(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.guard_arc() }) - } else { - None - } - } - - /// Attempts to acquire this lock until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_lock_until` method; however, it requires the `ReentrantMutex` to be - /// inside of an `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_lock_arc_until( - self: &Arc<Self>, - timeout: R::Instant, - ) -> Option<ArcReentrantMutexGuard<R, G, T>> { - if self.raw.try_lock_until(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.guard_arc() }) - } else { - None - } - } } impl<R: RawMutex, G: GetThreadId, T: ?Sized + Default> Default for ReentrantMutex<R, G, T> { @@ -788,108 +693,6 @@ unsafe impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> StableAdd { } -/// An RAII mutex guard returned by the `Arc` locking operations on `ReentrantMutex`. -/// -/// This is similar to the `ReentrantMutexGuard` struct, except instead of using a reference to unlock the -/// `Mutex` it uses an `Arc<ReentrantMutex>`. This has several advantages, most notably that it has an `'static` -/// lifetime. -#[cfg(feature = "arc_lock")] -#[must_use = "if unused the ReentrantMutex will immediately unlock"] -pub struct ArcReentrantMutexGuard<R: RawMutex, G: GetThreadId, T: ?Sized> { - remutex: Arc<ReentrantMutex<R, G, T>>, - marker: PhantomData<GuardNoSend>, -} - -#[cfg(feature = "arc_lock")] -impl<R: RawMutex, G: GetThreadId, T: ?Sized> ArcReentrantMutexGuard<R, G, T> { - /// Returns a reference to the `ReentrantMutex` this object is guarding, contained in its `Arc`. - pub fn remutex(s: &Self) -> &Arc<ReentrantMutex<R, G, T>> { - &s.remutex - } - - /// Temporarily unlocks the mutex to execute the given function. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the mutex. - #[inline] - pub fn unlocked<F, U>(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: A ReentrantMutexGuard always holds the lock. - unsafe { - s.remutex.raw.unlock(); - } - defer!(s.remutex.raw.lock()); - f() - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawMutexFair, G: GetThreadId, T: ?Sized> ArcReentrantMutexGuard<R, G, T> { - /// Unlocks the mutex using a fair unlock protocol. - /// - /// This is functionally identical to the `unlock_fair` method on [`ReentrantMutexGuard`]. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: A ReentrantMutexGuard always holds the lock - unsafe { - s.remutex.raw.unlock_fair(); - } - - // SAFETY: ensure that the Arc's refcount is decremented - let mut s = ManuallyDrop::new(s); - unsafe { ptr::drop_in_place(&mut s.remutex) }; - } - - /// Temporarily unlocks the mutex to execute the given function. - /// - /// This is functionally identical to the `unlocked_fair` method on [`ReentrantMutexGuard`]. - #[inline] - pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: A ReentrantMutexGuard always holds the lock - unsafe { - s.remutex.raw.unlock_fair(); - } - defer!(s.remutex.raw.lock()); - f() - } - - /// Temporarily yields the mutex to a waiting thread if there is one. - /// - /// This is functionally equivalent to the `bump` method on [`ReentrantMutexGuard`]. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: A ReentrantMutexGuard always holds the lock - unsafe { - s.remutex.raw.bump(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawMutex, G: GetThreadId, T: ?Sized> Deref for ArcReentrantMutexGuard<R, G, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.remutex.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawMutex, G: GetThreadId, T: ?Sized> Drop for ArcReentrantMutexGuard<R, G, T> { - #[inline] - fn drop(&mut self) { - // Safety: A ReentrantMutexGuard always holds the lock. - unsafe { - self.remutex.raw.unlock(); - } - } -} - /// An RAII mutex guard returned by `ReentrantMutexGuard::map`, which can point to a /// subfield of the protected data. /// diff --git a/src/rwlock.rs b/src/rwlock.rs index 9bfa1da..e97de98 100644 --- a/src/rwlock.rs +++ b/src/rwlock.rs @@ -11,13 +11,6 @@ use core::marker::PhantomData; use core::mem; use core::ops::{Deref, DerefMut}; -#[cfg(feature = "arc_lock")] -use alloc::sync::Arc; -#[cfg(feature = "arc_lock")] -use core::mem::ManuallyDrop; -#[cfg(feature = "arc_lock")] -use core::ptr; - #[cfg(feature = "owning_ref")] use owning_ref::StableAddress; @@ -84,18 +77,6 @@ pub unsafe trait RawRwLock { } !acquired_lock } - - /// Check if this `RwLock` is currently exclusively locked. - fn is_locked_exclusive(&self) -> bool { - let acquired_lock = self.try_lock_shared(); - if acquired_lock { - // Safety: A shared lock was successfully acquired above. - unsafe { - self.unlock_shared(); - } - } - !acquired_lock - } } /// Additional methods for RwLocks which support fair unlocking. @@ -514,12 +495,6 @@ impl<R: RawRwLock, T: ?Sized> RwLock<R, T> { self.raw.is_locked() } - /// Check if this `RwLock` is currently exclusively locked. - #[inline] - pub fn is_locked_exclusive(&self) -> bool { - self.raw.is_locked_exclusive() - } - /// Forcibly unlocks a read lock. /// /// This is useful when combined with `mem::forget` to hold a lock without @@ -582,84 +557,6 @@ impl<R: RawRwLock, T: ?Sized> RwLock<R, T> { pub fn data_ptr(&self) -> *mut T { self.data.get() } - - /// # Safety - /// - /// The lock must be held when calling this method. - #[cfg(feature = "arc_lock")] - #[inline] - unsafe fn read_guard_arc(self: &Arc<Self>) -> ArcRwLockReadGuard<R, T> { - ArcRwLockReadGuard { - rwlock: self.clone(), - marker: PhantomData, - } - } - - /// # Safety - /// - /// The lock must be held when calling this method. - #[cfg(feature = "arc_lock")] - #[inline] - unsafe fn write_guard_arc(self: &Arc<Self>) -> ArcRwLockWriteGuard<R, T> { - ArcRwLockWriteGuard { - rwlock: self.clone(), - marker: PhantomData, - } - } - - /// Locks this `RwLock` with read access, through an `Arc`. - /// - /// This method is similar to the `read` method; however, it requires the `RwLock` to be inside of an `Arc` - /// and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn read_arc(self: &Arc<Self>) -> ArcRwLockReadGuard<R, T> { - self.raw.lock_shared(); - // SAFETY: locking guarantee is upheld - unsafe { self.read_guard_arc() } - } - - /// Attempts to lock this `RwLock` with read access, through an `Arc`. - /// - /// This method is similar to the `try_read` method; however, it requires the `RwLock` to be inside of an - /// `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_read_arc(self: &Arc<Self>) -> Option<ArcRwLockReadGuard<R, T>> { - if self.raw.try_lock_shared() { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.read_guard_arc() }) - } else { - None - } - } - - /// Locks this `RwLock` with write access, through an `Arc`. - /// - /// This method is similar to the `write` method; however, it requires the `RwLock` to be inside of an `Arc` - /// and the resulting write guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn write_arc(self: &Arc<Self>) -> ArcRwLockWriteGuard<R, T> { - self.raw.lock_exclusive(); - // SAFETY: locking guarantee is upheld - unsafe { self.write_guard_arc() } - } - - /// Attempts to lock this `RwLock` with writ access, through an `Arc`. - /// - /// This method is similar to the `try_write` method; however, it requires the `RwLock` to be inside of an - /// `Arc` and the resulting write guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_write_arc(self: &Arc<Self>) -> Option<ArcRwLockWriteGuard<R, T>> { - if self.raw.try_lock_exclusive() { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.write_guard_arc() }) - } else { - None - } - } } impl<R: RawRwLockFair, T: ?Sized> RwLock<R, T> { @@ -760,78 +657,6 @@ impl<R: RawRwLockTimed, T: ?Sized> RwLock<R, T> { None } } - - /// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_read_for` method; however, it requires the `RwLock` to be inside of an - /// `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_read_arc_for( - self: &Arc<Self>, - timeout: R::Duration, - ) -> Option<ArcRwLockReadGuard<R, T>> { - if self.raw.try_lock_shared_for(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.read_guard_arc() }) - } else { - None - } - } - - /// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_read_until` method; however, it requires the `RwLock` to be inside of - /// an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_read_arc_until( - self: &Arc<Self>, - timeout: R::Instant, - ) -> Option<ArcRwLockReadGuard<R, T>> { - if self.raw.try_lock_shared_until(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.read_guard_arc() }) - } else { - None - } - } - - /// Attempts to acquire this `RwLock` with write access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_write_for` method; however, it requires the `RwLock` to be inside of - /// an `Arc` and the resulting write guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_write_arc_for( - self: &Arc<Self>, - timeout: R::Duration, - ) -> Option<ArcRwLockWriteGuard<R, T>> { - if self.raw.try_lock_exclusive_for(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.write_guard_arc() }) - } else { - None - } - } - - /// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_write_until` method; however, it requires the `RwLock` to be inside of - /// an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_write_arc_until( - self: &Arc<Self>, - timeout: R::Instant, - ) -> Option<ArcRwLockWriteGuard<R, T>> { - if self.raw.try_lock_exclusive_until(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.write_guard_arc() }) - } else { - None - } - } } impl<R: RawRwLockRecursive, T: ?Sized> RwLock<R, T> { @@ -876,33 +701,6 @@ impl<R: RawRwLockRecursive, T: ?Sized> RwLock<R, T> { None } } - - /// Locks this `RwLock` with shared read access, through an `Arc`. - /// - /// This method is similar to the `read_recursive` method; however, it requires the `RwLock` to be inside of - /// an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn read_arc_recursive(self: &Arc<Self>) -> ArcRwLockReadGuard<R, T> { - self.raw.lock_shared_recursive(); - // SAFETY: locking guarantee is upheld - unsafe { self.read_guard_arc() } - } - - /// Attempts to lock this `RwLock` with shared read access, through an `Arc`. - /// - /// This method is similar to the `try_read_recursive` method; however, it requires the `RwLock` to be inside - /// of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_read_recursive_arc(self: &Arc<Self>) -> Option<ArcRwLockReadGuard<R, T>> { - if self.raw.try_lock_shared_recursive() { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.read_guard_arc() }) - } else { - None - } - } } impl<R: RawRwLockRecursiveTimed, T: ?Sized> RwLock<R, T> { @@ -947,42 +745,6 @@ impl<R: RawRwLockRecursiveTimed, T: ?Sized> RwLock<R, T> { None } } - - /// Attempts to lock this `RwLock` with read access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_read_recursive_for` method; however, it requires the `RwLock` to be - /// inside of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_read_arc_recursive_for( - self: &Arc<Self>, - timeout: R::Duration, - ) -> Option<ArcRwLockReadGuard<R, T>> { - if self.raw.try_lock_shared_recursive_for(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.read_guard_arc() }) - } else { - None - } - } - - /// Attempts to lock this `RwLock` with read access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_read_recursive_until` method; however, it requires the `RwLock` to be - /// inside of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_read_arc_recursive_until( - self: &Arc<Self>, - timeout: R::Instant, - ) -> Option<ArcRwLockReadGuard<R, T>> { - if self.raw.try_lock_shared_recursive_until(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.read_guard_arc() }) - } else { - None - } - } } impl<R: RawRwLockUpgrade, T: ?Sized> RwLock<R, T> { @@ -1029,45 +791,6 @@ impl<R: RawRwLockUpgrade, T: ?Sized> RwLock<R, T> { None } } - - /// # Safety - /// - /// The lock must be held when calling this method. - #[cfg(feature = "arc_lock")] - #[inline] - unsafe fn upgradable_guard_arc(self: &Arc<Self>) -> ArcRwLockUpgradableReadGuard<R, T> { - ArcRwLockUpgradableReadGuard { - rwlock: self.clone(), - marker: PhantomData, - } - } - - /// Locks this `RwLock` with upgradable read access, through an `Arc`. - /// - /// This method is similar to the `upgradable_read` method; however, it requires the `RwLock` to be - /// inside of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn upgradable_read_arc(self: &Arc<Self>) -> ArcRwLockUpgradableReadGuard<R, T> { - self.raw.lock_upgradable(); - // SAFETY: locking guarantee is upheld - unsafe { self.upgradable_guard_arc() } - } - - /// Attempts to lock this `RwLock` with upgradable read access, through an `Arc`. - /// - /// This method is similar to the `try_upgradable_read` method; however, it requires the `RwLock` to be - /// inside of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_upgradable_read_arc(self: &Arc<Self>) -> Option<ArcRwLockUpgradableReadGuard<R, T>> { - if self.raw.try_lock_upgradable() { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.upgradable_guard_arc() }) - } else { - None - } - } } impl<R: RawRwLockUpgradeTimed, T: ?Sized> RwLock<R, T> { @@ -1108,42 +831,6 @@ impl<R: RawRwLockUpgradeTimed, T: ?Sized> RwLock<R, T> { None } } - - /// Attempts to lock this `RwLock` with upgradable access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_upgradable_read_for` method; however, it requires the `RwLock` to be - /// inside of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_upgradable_read_arc_for( - self: &Arc<Self>, - timeout: R::Duration, - ) -> Option<ArcRwLockUpgradableReadGuard<R, T>> { - if self.raw.try_lock_upgradable_for(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.upgradable_guard_arc() }) - } else { - None - } - } - - /// Attempts to lock this `RwLock` with upgradable access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_upgradable_read_until` method; however, it requires the `RwLock` to be - /// inside of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_upgradable_read_arc_until( - self: &Arc<Self>, - timeout: R::Instant, - ) -> Option<ArcRwLockUpgradableReadGuard<R, T>> { - if self.raw.try_lock_upgradable_until(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.upgradable_guard_arc() }) - } else { - None - } - } } impl<R: RawRwLock, T: ?Sized + Default> Default for RwLock<R, T> { @@ -1354,120 +1041,6 @@ impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display #[cfg(feature = "owning_ref")] unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockReadGuard<'a, R, T> {} -/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`. -/// -/// This is similar to the `RwLockReadGuard` struct, except instead of using a reference to unlock the `RwLock` -/// it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static` lifetime. -#[cfg(feature = "arc_lock")] -#[must_use = "if unused the RwLock will immediately unlock"] -pub struct ArcRwLockReadGuard<R: RawRwLock, T: ?Sized> { - rwlock: Arc<RwLock<R, T>>, - marker: PhantomData<R::GuardMarker>, -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLock, T: ?Sized> ArcRwLockReadGuard<R, T> { - /// Returns a reference to the rwlock, contained in its `Arc`. - pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> { - &s.rwlock - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is functionally identical to the `unlocked` method on [`RwLockReadGuard`]. - #[inline] - pub fn unlocked<F, U>(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.unlock_shared(); - } - defer!(s.rwlock.raw.lock_shared()); - f() - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLockFair, T: ?Sized> ArcRwLockReadGuard<R, T> { - /// Unlocks the `RwLock` using a fair unlock protocol. - /// - /// This is functionally identical to the `unlock_fair` method on [`RwLockReadGuard`]. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.unlock_shared_fair(); - } - - // SAFETY: ensure the Arc has its refcount decremented - let mut s = ManuallyDrop::new(s); - unsafe { ptr::drop_in_place(&mut s.rwlock) }; - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is functionally identical to the `unlocked_fair` method on [`RwLockReadGuard`]. - #[inline] - pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.unlock_shared_fair(); - } - defer!(s.rwlock.raw.lock_shared()); - f() - } - - /// Temporarily yields the `RwLock` to a waiting thread if there is one. - /// - /// This is functionally identical to the `bump` method on [`RwLockReadGuard`]. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.bump_shared(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLock, T: ?Sized> Deref for ArcRwLockReadGuard<R, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.rwlock.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLock, T: ?Sized> Drop for ArcRwLockReadGuard<R, T> { - #[inline] - fn drop(&mut self) { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - self.rwlock.raw.unlock_shared(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLock, T: fmt::Debug + ?Sized> fmt::Debug for ArcRwLockReadGuard<R, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display for ArcRwLockReadGuard<R, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - /// RAII structure used to release the exclusive write access of a lock when /// dropped. #[must_use = "if unused the RwLock will immediately unlock"] @@ -1689,173 +1262,6 @@ impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display #[cfg(feature = "owning_ref")] unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockWriteGuard<'a, R, T> {} -/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`. -/// This is similar to the `RwLockWriteGuard` struct, except instead of using a reference to unlock the `RwLock` -/// it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static` lifetime. -#[cfg(feature = "arc_lock")] -#[must_use = "if unused the RwLock will immediately unlock"] -pub struct ArcRwLockWriteGuard<R: RawRwLock, T: ?Sized> { - rwlock: Arc<RwLock<R, T>>, - marker: PhantomData<R::GuardMarker>, -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLock, T: ?Sized> ArcRwLockWriteGuard<R, T> { - /// Returns a reference to the rwlock, contained in its `Arc`. - pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> { - &s.rwlock - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is functionally equivalent to the `unlocked` method on [`RwLockWriteGuard`]. - #[inline] - pub fn unlocked<F, U>(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockWriteGuard always holds a shared lock. - unsafe { - s.rwlock.raw.unlock_exclusive(); - } - defer!(s.rwlock.raw.lock_exclusive()); - f() - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLockDowngrade, T: ?Sized> ArcRwLockWriteGuard<R, T> { - /// Atomically downgrades a write lock into a read lock without allowing any - /// writers to take exclusive access of the lock in the meantime. - /// - /// This is functionally equivalent to the `downgrade` method on [`RwLockWriteGuard`]. - pub fn downgrade(s: Self) -> ArcRwLockReadGuard<R, T> { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.downgrade(); - } - - // SAFETY: prevent the arc's refcount from changing using ManuallyDrop and ptr::read - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - ArcRwLockReadGuard { - rwlock, - marker: PhantomData, - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLockUpgradeDowngrade, T: ?Sized> ArcRwLockWriteGuard<R, T> { - /// Atomically downgrades a write lock into an upgradable read lock without allowing any - /// writers to take exclusive access of the lock in the meantime. - /// - /// This is functionally identical to the `downgrade_to_upgradable` method on [`RwLockWriteGuard`]. - pub fn downgrade_to_upgradable(s: Self) -> ArcRwLockUpgradableReadGuard<R, T> { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.downgrade_to_upgradable(); - } - - // SAFETY: same as above - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - ArcRwLockUpgradableReadGuard { - rwlock, - marker: PhantomData, - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLockFair, T: ?Sized> ArcRwLockWriteGuard<R, T> { - /// Unlocks the `RwLock` using a fair unlock protocol. - /// - /// This is functionally equivalent to the `unlock_fair` method on [`RwLockWriteGuard`]. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.unlock_exclusive_fair(); - } - - // SAFETY: prevent the Arc from leaking memory - let mut s = ManuallyDrop::new(s); - unsafe { ptr::drop_in_place(&mut s.rwlock) }; - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is functionally equivalent to the `unlocked_fair` method on [`RwLockWriteGuard`]. - #[inline] - pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.unlock_exclusive_fair(); - } - defer!(s.rwlock.raw.lock_exclusive()); - f() - } - - /// Temporarily yields the `RwLock` to a waiting thread if there is one. - /// - /// This method is functionally equivalent to the `bump` method on [`RwLockWriteGuard`]. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.bump_exclusive(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLock, T: ?Sized> Deref for ArcRwLockWriteGuard<R, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.rwlock.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLock, T: ?Sized> DerefMut for ArcRwLockWriteGuard<R, T> { - #[inline] - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.rwlock.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLock, T: ?Sized> Drop for ArcRwLockWriteGuard<R, T> { - #[inline] - fn drop(&mut self) { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - self.rwlock.raw.unlock_exclusive(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLock, T: fmt::Debug + ?Sized> fmt::Debug for ArcRwLockWriteGuard<R, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display for ArcRwLockWriteGuard<R, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - /// RAII structure used to release the upgradable read access of a lock when /// dropped. #[must_use = "if unused the RwLock will immediately unlock"] @@ -2089,240 +1495,6 @@ unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> StableAddress { } -/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`. -/// This is similar to the `RwLockUpgradableReadGuard` struct, except instead of using a reference to unlock the -/// `RwLock` it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static` -/// lifetime. -#[cfg(feature = "arc_lock")] -#[must_use = "if unused the RwLock will immediately unlock"] -pub struct ArcRwLockUpgradableReadGuard<R: RawRwLockUpgrade, T: ?Sized> { - rwlock: Arc<RwLock<R, T>>, - marker: PhantomData<R::GuardMarker>, -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLockUpgrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> { - /// Returns a reference to the rwlock, contained in its original `Arc`. - pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> { - &s.rwlock - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is functionally identical to the `unlocked` method on [`RwLockUpgradableReadGuard`]. - #[inline] - pub fn unlocked<F, U>(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.unlock_upgradable(); - } - defer!(s.rwlock.raw.lock_upgradable()); - f() - } - - /// Atomically upgrades an upgradable read lock lock into a exclusive write lock, - /// blocking the current thread until it can be acquired. - pub fn upgrade(s: Self) -> ArcRwLockWriteGuard<R, T> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.upgrade(); - } - - // SAFETY: avoid incrementing or decrementing the refcount using ManuallyDrop and reading the Arc out - // of the struct - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - ArcRwLockWriteGuard { - rwlock, - marker: PhantomData, - } - } - - /// Tries to atomically upgrade an upgradable read lock into a exclusive write lock. - /// - /// If the access could not be granted at this time, then the current guard is returned. - pub fn try_upgrade(s: Self) -> Result<ArcRwLockWriteGuard<R, T>, Self> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - if unsafe { s.rwlock.raw.try_upgrade() } { - // SAFETY: same as above - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - Ok(ArcRwLockWriteGuard { - rwlock, - marker: PhantomData, - }) - } else { - Err(s) - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLockUpgradeFair, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> { - /// Unlocks the `RwLock` using a fair unlock protocol. - /// - /// This is functionally identical to the `unlock_fair` method on [`RwLockUpgradableReadGuard`]. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.unlock_upgradable_fair(); - } - - // SAFETY: make sure we decrement the refcount properly - let mut s = ManuallyDrop::new(s); - unsafe { ptr::drop_in_place(&mut s.rwlock) }; - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is functionally equivalent to the `unlocked_fair` method on [`RwLockUpgradableReadGuard`]. - #[inline] - pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.unlock_upgradable_fair(); - } - defer!(s.rwlock.raw.lock_upgradable()); - f() - } - - /// Temporarily yields the `RwLock` to a waiting thread if there is one. - /// - /// This method is functionally equivalent to calling `bump` on [`RwLockUpgradableReadGuard`]. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.bump_upgradable(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLockUpgradeDowngrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> { - /// Atomically downgrades an upgradable read lock lock into a shared read lock - /// without allowing any writers to take exclusive access of the lock in the - /// meantime. - /// - /// Note that if there are any writers currently waiting to take the lock - /// then other readers may not be able to acquire the lock even if it was - /// downgraded. - pub fn downgrade(s: Self) -> ArcRwLockReadGuard<R, T> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.downgrade_upgradable(); - } - - // SAFETY: use ManuallyDrop and ptr::read to ensure the refcount is not changed - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - ArcRwLockReadGuard { - rwlock, - marker: PhantomData, - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLockUpgradeTimed, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> { - /// Tries to atomically upgrade an upgradable read lock into a exclusive - /// write lock, until a timeout is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// the current guard is returned. - pub fn try_upgrade_for( - s: Self, - timeout: R::Duration, - ) -> Result<ArcRwLockWriteGuard<R, T>, Self> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - if unsafe { s.rwlock.raw.try_upgrade_for(timeout) } { - // SAFETY: same as above - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - Ok(ArcRwLockWriteGuard { - rwlock, - marker: PhantomData, - }) - } else { - Err(s) - } - } - - /// Tries to atomically upgrade an upgradable read lock into a exclusive - /// write lock, until a timeout is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// the current guard is returned. - #[inline] - pub fn try_upgrade_until( - s: Self, - timeout: R::Instant, - ) -> Result<ArcRwLockWriteGuard<R, T>, Self> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - if unsafe { s.rwlock.raw.try_upgrade_until(timeout) } { - // SAFETY: same as above - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - Ok(ArcRwLockWriteGuard { - rwlock, - marker: PhantomData, - }) - } else { - Err(s) - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLockUpgrade, T: ?Sized> Deref for ArcRwLockUpgradableReadGuard<R, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.rwlock.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLockUpgrade, T: ?Sized> Drop for ArcRwLockUpgradableReadGuard<R, T> { - #[inline] - fn drop(&mut self) { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - self.rwlock.raw.unlock_upgradable(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLockUpgrade, T: fmt::Debug + ?Sized> fmt::Debug - for ArcRwLockUpgradableReadGuard<R, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[cfg(feature = "arc_lock")] -impl<R: RawRwLockUpgrade, T: fmt::Display + ?Sized> fmt::Display - for ArcRwLockUpgradableReadGuard<R, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - /// An RAII read lock guard returned by `RwLockReadGuard::map`, which can point to a /// subfield of the protected data. /// |