aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Vander Stoep <jeffv@google.com>2022-12-13 09:36:41 +0100
committerJeff Vander Stoep <jeffv@google.com>2022-12-13 09:37:04 +0100
commit824a531036c53205c3b22b4ceac4c88cd021f589 (patch)
treeded5029caae060037b38c7173961f0d713685cf5
parent33fba32707404170f2ffb4a54ac261d460d91fb6 (diff)
downloadparking_lot-824a531036c53205c3b22b4ceac4c88cd021f589.tar.gz
Upgrade parking_lot to 0.12.1
This project was upgraded with external_updater. Usage: tools/external_updater/updater.sh update rust/crates/parking_lot For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md Test: TreeHugger Change-Id: I89fe53441ba6f3bab0686c192f5e80ec3b640709
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--.github/workflows/rust.yml5
-rw-r--r--Android.bp2
-rw-r--r--CHANGELOG.md21
-rw-r--r--Cargo.toml19
-rw-r--r--Cargo.toml.orig4
-rw-r--r--METADATA12
-rw-r--r--README.md24
-rw-r--r--src/condvar.rs266
-rw-r--r--src/fair_mutex.rs2
-rw-r--r--src/mutex.rs2
-rw-r--r--src/once.rs12
-rw-r--r--src/raw_rwlock.rs4
-rw-r--r--src/rwlock.rs2
14 files changed, 322 insertions, 55 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 38c6551..ca34d9d 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
{
"git": {
- "sha1": "a75875b0bf904287a9749e8eabea919b5e9dd8a9"
+ "sha1": "336a9b31ff385728d00eb7ef173e4d054584b787"
},
"path_in_vcs": ""
} \ No newline at end of file
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 4d33593..e5c2395 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -8,6 +8,7 @@ on:
pull_request:
env:
+ CARGO_INCREMENTAL: 0
RUST_TEST_THREADS: 1
jobs:
@@ -18,7 +19,7 @@ jobs:
os: [ubuntu, macos, windows]
channel: [1.49.0, stable, beta, nightly]
feature: [arc_lock, serde, deadlock_detection]
- exclude:
+ exclude:
- feature: deadlock_detection
channel: '1.49.0'
include:
@@ -41,7 +42,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- target:
+ target:
- wasm32-unknown-unknown
- x86_64-fortanix-unknown-sgx
#- x86_64-unknown-redox
diff --git a/Android.bp b/Android.bp
index 37f9ad1..2c6d8bf 100644
--- a/Android.bp
+++ b/Android.bp
@@ -42,7 +42,7 @@ rust_library {
host_supported: true,
crate_name: "parking_lot",
cargo_env_compat: true,
- cargo_pkg_version: "0.12.0",
+ cargo_pkg_version: "0.12.1",
srcs: ["src/lib.rs"],
edition: "2018",
features: ["default"],
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d1951e9..8421b84 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,24 @@
+## parking_lot 0.12.1 (2022-05-31)
+
+- Fixed incorrect memory ordering in `RwLock`. (#344)
+- Added `Condvar::wait_while` convenience methods (#343)
+
+## parking_lot_core 0.9.3 (2022-04-30)
+
+- Bump windows-sys dependency to 0.36. (#339)
+
+## parking_lot_core 0.9.2, lock_api 0.4.7 (2022-03-25)
+
+- Enable const new() on lock types on stable. (#325)
+- Added `MutexGuard::leak` function. (#333)
+- Bump windows-sys dependency to 0.34. (#331)
+- Bump petgraph dependency to 0.6. (#326)
+- Don't use pthread attributes on the espidf platform. (#319)
+
+## parking_lot_core 0.9.1 (2022-02-06)
+
+- Bump windows-sys dependency to 0.32. (#316)
+
## parking_lot 0.12.0, parking_lot_core 0.9.0, lock_api 0.4.6 (2022-01-28)
- The MSRV is bumped to 1.49.0.
diff --git a/Cargo.toml b/Cargo.toml
index 6f58afa..e474f48 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,19 +12,27 @@
[package]
edition = "2018"
name = "parking_lot"
-version = "0.12.0"
+version = "0.12.1"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
description = "More compact and efficient implementations of the standard synchronization primitives."
readme = "README.md"
-keywords = ["mutex", "condvar", "rwlock", "once", "thread"]
+keywords = [
+ "mutex",
+ "condvar",
+ "rwlock",
+ "once",
+ "thread",
+]
categories = ["concurrency"]
-license = "Apache-2.0/MIT"
+license = "MIT OR Apache-2.0"
repository = "https://github.com/Amanieu/parking_lot"
+
[dependencies.lock_api]
version = "0.4.6"
[dependencies.parking_lot_core]
version = "0.9.0"
+
[dev-dependencies.bincode]
version = "1.3.3"
@@ -36,7 +44,10 @@ arc_lock = ["lock_api/arc_lock"]
deadlock_detection = ["parking_lot_core/deadlock_detection"]
default = []
hardware-lock-elision = []
-nightly = ["parking_lot_core/nightly", "lock_api/nightly"]
+nightly = [
+ "parking_lot_core/nightly",
+ "lock_api/nightly",
+]
owning_ref = ["lock_api/owning_ref"]
send_guard = []
serde = ["lock_api/serde"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index bb501be..90b653d 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,9 +1,9 @@
[package]
name = "parking_lot"
-version = "0.12.0"
+version = "0.12.1"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
description = "More compact and efficient implementations of the standard synchronization primitives."
-license = "Apache-2.0/MIT"
+license = "MIT OR Apache-2.0"
repository = "https://github.com/Amanieu/parking_lot"
readme = "README.md"
keywords = ["mutex", "condvar", "rwlock", "once", "thread"]
diff --git a/METADATA b/METADATA
index 10f98ed..0cb5945 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/parking_lot
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
name: "parking_lot"
description: "More compact and efficient implementations of the standard synchronization primitives."
third_party {
@@ -7,13 +11,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/parking_lot/parking_lot-0.12.0.crate"
+ value: "https://static.crates.io/crates/parking_lot/parking_lot-0.12.1.crate"
}
- version: "0.12.0"
+ version: "0.12.1"
license_type: NOTICE
last_upgrade_date {
year: 2022
- month: 3
- day: 1
+ month: 12
+ day: 13
}
}
diff --git a/README.md b/README.md
index 5bda8d8..70fdca7 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
parking_lot
============
-![Rust](https://github.com/Amanieu/parking_lot/workflows/Rust/badge.svg)
+[![Rust](https://github.com/Amanieu/parking_lot/workflows/Rust/badge.svg)](https://github.com/Amanieu/parking_lot/actions)
[![Crates.io](https://img.shields.io/crates/v/parking_lot.svg)](https://crates.io/crates/parking_lot)
[Documentation (synchronization primitives)](https://docs.rs/parking_lot/)
@@ -83,7 +83,7 @@ functionality is offloaded to the *parking lot*. The idea behind this is
based on the Webkit [`WTF::ParkingLot`](https://webkit.org/blog/6161/locking-in-webkit/)
class, which essentially consists of a hash table mapping of lock addresses
to queues of parked (sleeping) threads. The Webkit parking lot was itself
-inspired by Linux [futexes](http://man7.org/linux/man-pages/man2/futex.2.html),
+inspired by Linux [futexes](https://man7.org/linux/man-pages/man2/futex.2.html),
but it is more powerful since it allows invoking callbacks while holding a queue
lock.
@@ -91,11 +91,13 @@ lock.
There are a few restrictions when using this library on stable Rust:
-- You will have to use the `const_*` functions (e.g. `const_mutex(val)`) to
- statically initialize the locking primitives. Using e.g. `Mutex::new(val)`
- does not work on stable Rust yet.
-- The `wasm32-unknown-unknown` target is only supported on nightly and requires
- `-C target-feature=+atomics` in `RUSTFLAGS`.
+- The `wasm32-unknown-unknown` target is only fully supported on nightly with
+ `-C target-feature=+atomics` in `RUSTFLAGS` and `-Z build-std` passed to cargo.
+ parking_lot will work mostly fine on stable, the only difference is it will
+ panic instead of block forever if you hit a deadlock.
+ Just make sure not to enable `-C target-feature=+atomics` on stable as that
+ will allow wasm to run with multiple threads which will completely break
+ parking_lot's concurrency guarantees.
To enable nightly-only functionality, you need to enable the `nightly` feature
in Cargo (see below).
@@ -106,14 +108,14 @@ Add this to your `Cargo.toml`:
```toml
[dependencies]
-parking_lot = "0.11"
+parking_lot = "0.12"
```
To enable nightly-only features, add this to your `Cargo.toml` instead:
```toml
[dependencies]
-parking_lot = { version = "0.11", features = ["nightly"] }
+parking_lot = { version = "0.12", features = ["nightly"] }
```
The experimental deadlock detector can be enabled with the
@@ -142,8 +144,8 @@ considered a breaking change and will require a major version bump.
Licensed under either of
- * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+ * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
at your option.
diff --git a/src/condvar.rs b/src/condvar.rs
index 9eaf300..15daa69 100644
--- a/src/condvar.rs
+++ b/src/condvar.rs
@@ -14,6 +14,7 @@ use core::{
};
use lock_api::RawMutex as RawMutex_;
use parking_lot_core::{self, ParkResult, RequeueOp, UnparkResult, DEFAULT_PARK_TOKEN};
+use std::ops::DerefMut;
use std::time::{Duration, Instant};
/// A type indicating whether a timed wait on a condition variable returned
@@ -53,7 +54,7 @@ impl WaitTimeoutResult {
/// woken up.
/// - Only requires 1 word of space, whereas the standard library boxes the
/// `Condvar` due to platform limitations.
-/// - Can be statically constructed (requires the `const_fn` nightly feature).
+/// - Can be statically constructed.
/// - Does not require any drop glue when dropped.
/// - Inline fast path for the uncontended case.
///
@@ -136,10 +137,9 @@ impl Condvar {
#[cold]
fn notify_one_slow(&self, mutex: *mut RawMutex) -> bool {
- unsafe {
- // Unpark one thread and requeue the rest onto the mutex
- let from = self as *const _ as usize;
- let to = mutex as usize;
+ // Unpark one thread and requeue the rest onto the mutex
+ let from = self as *const _ as usize;
+ let to = mutex as usize;
let validate = || {
// Make sure that our atomic state still points to the same
// mutex. If not then it means that all threads on the current
@@ -156,7 +156,7 @@ impl Condvar {
// locking the queue. There is the possibility of a race if the
// mutex gets locked after we check, but that doesn't matter in
// this case.
- if (*mutex).mark_parked_if_locked() {
+ if unsafe { (*mutex).mark_parked_if_locked() } {
RequeueOp::RequeueOne
} else {
RequeueOp::UnparkOne
@@ -169,10 +169,9 @@ impl Condvar {
}
TOKEN_NORMAL
};
- let res = parking_lot_core::unpark_requeue(from, to, validate, callback);
+ let res = unsafe { parking_lot_core::unpark_requeue(from, to, validate, callback) };
res.unparked_threads + res.requeued_threads != 0
- }
}
/// Wakes up all blocked threads on this condvar.
@@ -197,7 +196,6 @@ impl Condvar {
#[cold]
fn notify_all_slow(&self, mutex: *mut RawMutex) -> usize {
- unsafe {
// Unpark one thread and requeue the rest onto the mutex
let from = self as *const _ as usize;
let to = mutex as usize;
@@ -221,7 +219,7 @@ impl Condvar {
// locking the queue. There is the possibility of a race if the
// mutex gets locked after we check, but that doesn't matter in
// this case.
- if (*mutex).mark_parked_if_locked() {
+ if unsafe { (*mutex).mark_parked_if_locked() } {
RequeueOp::RequeueAll
} else {
RequeueOp::UnparkOneRequeueRest
@@ -231,14 +229,13 @@ impl Condvar {
// If we requeued threads to the mutex, mark it as having
// parked threads. The RequeueAll case is already handled above.
if op == RequeueOp::UnparkOneRequeueRest && result.requeued_threads != 0 {
- (*mutex).mark_parked();
+ unsafe { (*mutex).mark_parked() };
}
TOKEN_NORMAL
};
- let res = parking_lot_core::unpark_requeue(from, to, validate, callback);
+ let res = unsafe { parking_lot_core::unpark_requeue(from, to, validate, callback) };
res.unparked_threads + res.requeued_threads
- }
}
/// Blocks the current thread until this condition variable receives a
@@ -297,7 +294,6 @@ impl Condvar {
// This is a non-generic function to reduce the monomorphization cost of
// using `wait_until`.
fn wait_until_internal(&self, mutex: &RawMutex, timeout: Option<Instant>) -> WaitTimeoutResult {
- unsafe {
let result;
let mut bad_mutex = false;
let mut requeued = false;
@@ -319,7 +315,7 @@ impl Condvar {
};
let before_sleep = || {
// Unlock the mutex before sleeping...
- mutex.unlock();
+ unsafe { mutex.unlock() };
};
let timed_out = |k, was_last_thread| {
// If we were requeued to a mutex, then we did not time out.
@@ -334,14 +330,14 @@ impl Condvar {
self.state.store(ptr::null_mut(), Ordering::Relaxed);
}
};
- result = parking_lot_core::park(
+ result = unsafe { parking_lot_core::park(
addr,
validate,
before_sleep,
timed_out,
DEFAULT_PARK_TOKEN,
timeout,
- );
+ ) };
}
// Panic if we tried to use multiple mutexes with a Condvar. Note
@@ -353,13 +349,12 @@ impl Condvar {
// ... and re-lock it once we are done sleeping
if result == ParkResult::Unparked(TOKEN_HANDOFF) {
- deadlock::acquire_resource(mutex as *const _ as usize);
+ unsafe { deadlock::acquire_resource(mutex as *const _ as usize) };
} else {
mutex.lock();
}
WaitTimeoutResult(!(result.is_unparked() || requeued))
- }
}
/// Waits on this condition variable for a notification, timing out after a
@@ -389,6 +384,127 @@ impl Condvar {
let deadline = util::to_deadline(timeout);
self.wait_until_internal(unsafe { MutexGuard::mutex(mutex_guard).raw() }, deadline)
}
+
+ #[inline]
+ fn wait_while_until_internal<T, F>(
+ &self,
+ mutex_guard: &mut MutexGuard<'_, T>,
+ mut condition: F,
+ timeout: Option<Instant>,
+ ) -> WaitTimeoutResult
+ where
+ T: ?Sized,
+ F: FnMut(&mut T) -> bool,
+ {
+ let mut result = WaitTimeoutResult(false);
+
+ while !result.timed_out() && condition(mutex_guard.deref_mut()) {
+ result =
+ self.wait_until_internal(unsafe { MutexGuard::mutex(mutex_guard).raw() }, timeout);
+ }
+
+ result
+ }
+ /// Blocks the current thread until this condition variable receives a
+ /// notification. If the provided condition evaluates to `false`, then the
+ /// thread is no longer blocked and the operation is completed. If the
+ /// condition evaluates to `true`, then the thread is blocked again and
+ /// waits for another notification before repeating this process.
+ ///
+ /// This function will atomically unlock the mutex specified (represented by
+ /// `mutex_guard`) and block the current thread. This means that any calls
+ /// to `notify_*()` which happen logically after the mutex is unlocked are
+ /// candidates to wake this thread up. When this function call returns, the
+ /// lock specified will have been re-acquired.
+ ///
+ /// # Panics
+ ///
+ /// This function will panic if another thread is waiting on the `Condvar`
+ /// with a different `Mutex` object.
+ #[inline]
+ pub fn wait_while<T, F>(&self, mutex_guard: &mut MutexGuard<'_, T>, condition: F)
+ where
+ T: ?Sized,
+ F: FnMut(&mut T) -> bool,
+ {
+ self.wait_while_until_internal(mutex_guard, condition, None);
+ }
+
+ /// Waits on this condition variable for a notification, timing out after
+ /// the specified time instant. If the provided condition evaluates to
+ /// `false`, then the thread is no longer blocked and the operation is
+ /// completed. If the condition evaluates to `true`, then the thread is
+ /// blocked again and waits for another notification before repeating
+ /// this process.
+ ///
+ /// The semantics of this function are equivalent to `wait()` except that
+ /// the thread will be blocked roughly until `timeout` is reached. This
+ /// method should not be used for precise timing due to anomalies such as
+ /// preemption or platform differences that may not cause the maximum
+ /// amount of time waited to be precisely `timeout`.
+ ///
+ /// Note that the best effort is made to ensure that the time waited is
+ /// measured with a monotonic clock, and not affected by the changes made to
+ /// the system time.
+ ///
+ /// The returned `WaitTimeoutResult` value indicates if the timeout is
+ /// known to have elapsed.
+ ///
+ /// Like `wait`, the lock specified will be re-acquired when this function
+ /// returns, regardless of whether the timeout elapsed or not.
+ ///
+ /// # Panics
+ ///
+ /// This function will panic if another thread is waiting on the `Condvar`
+ /// with a different `Mutex` object.
+ #[inline]
+ pub fn wait_while_until<T, F>(
+ &self,
+ mutex_guard: &mut MutexGuard<'_, T>,
+ condition: F,
+ timeout: Instant,
+ ) -> WaitTimeoutResult
+ where
+ T: ?Sized,
+ F: FnMut(&mut T) -> bool,
+ {
+ self.wait_while_until_internal(mutex_guard, condition, Some(timeout))
+ }
+
+ /// Waits on this condition variable for a notification, timing out after a
+ /// specified duration. If the provided condition evaluates to `false`,
+ /// then the thread is no longer blocked and the operation is completed.
+ /// If the condition evaluates to `true`, then the thread is blocked again
+ /// and waits for another notification before repeating this process.
+ ///
+ /// The semantics of this function are equivalent to `wait()` except that
+ /// the thread will be blocked for roughly no longer than `timeout`. This
+ /// method should not be used for precise timing due to anomalies such as
+ /// preemption or platform differences that may not cause the maximum
+ /// amount of time waited to be precisely `timeout`.
+ ///
+ /// Note that the best effort is made to ensure that the time waited is
+ /// measured with a monotonic clock, and not affected by the changes made to
+ /// the system time.
+ ///
+ /// The returned `WaitTimeoutResult` value indicates if the timeout is
+ /// known to have elapsed.
+ ///
+ /// Like `wait`, the lock specified will be re-acquired when this function
+ /// returns, regardless of whether the timeout elapsed or not.
+ #[inline]
+ pub fn wait_while_for<T: ?Sized, F>(
+ &self,
+ mutex_guard: &mut MutexGuard<'_, T>,
+ condition: F,
+ timeout: Duration,
+ ) -> WaitTimeoutResult
+ where
+ F: FnMut(&mut T) -> bool,
+ {
+ let deadline = util::to_deadline(timeout);
+ self.wait_while_until_internal(mutex_guard, condition, deadline)
+ }
}
impl Default for Condvar {
@@ -410,6 +526,8 @@ mod tests {
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::thread;
+ use std::thread::sleep;
+ use std::thread::JoinHandle;
use std::time::Duration;
use std::time::Instant;
@@ -578,6 +696,116 @@ mod tests {
drop(g);
}
+ fn spawn_wait_while_notifier(
+ mutex: Arc<Mutex<u32>>,
+ cv: Arc<Condvar>,
+ num_iters: u32,
+ timeout: Option<Instant>,
+ ) -> JoinHandle<()> {
+ thread::spawn(move || {
+ for epoch in 1..=num_iters {
+ // spin to wait for main test thread to block
+ // before notifying it to wake back up and check
+ // its condition.
+ let mut sleep_backoff = Duration::from_millis(1);
+ let _mutex_guard = loop {
+ let mutex_guard = mutex.lock();
+
+ if let Some(timeout) = timeout {
+ if Instant::now() >= timeout {
+ return;
+ }
+ }
+
+ if *mutex_guard == epoch {
+ break mutex_guard;
+ }
+
+ drop(mutex_guard);
+
+ // give main test thread a good chance to
+ // acquire the lock before this thread does.
+ sleep(sleep_backoff);
+ sleep_backoff *= 2;
+ };
+
+ cv.notify_one();
+ }
+ })
+ }
+
+ #[test]
+ fn wait_while_until_internal_does_not_wait_if_initially_false() {
+ let mutex = Arc::new(Mutex::new(0));
+ let cv = Arc::new(Condvar::new());
+
+ let condition = |counter: &mut u32| {
+ *counter += 1;
+ false
+ };
+
+ let mut mutex_guard = mutex.lock();
+ let timeout_result = cv
+ .wait_while_until_internal(&mut mutex_guard, condition, None);
+
+ assert!(!timeout_result.timed_out());
+ assert!(*mutex_guard == 1);
+ }
+
+ #[test]
+ fn wait_while_until_internal_times_out_before_false() {
+ let mutex = Arc::new(Mutex::new(0));
+ let cv = Arc::new(Condvar::new());
+
+ let num_iters = 3;
+ let condition = |counter: &mut u32| {
+ *counter += 1;
+ true
+ };
+
+ let mut mutex_guard = mutex.lock();
+ let timeout = Some(Instant::now() + Duration::from_millis(500));
+ let handle = spawn_wait_while_notifier(mutex.clone(), cv.clone(), num_iters, timeout);
+
+ let timeout_result =
+ cv.wait_while_until_internal(&mut mutex_guard, condition, timeout);
+
+ assert!(timeout_result.timed_out());
+ assert!(*mutex_guard == num_iters + 1);
+
+ // prevent deadlock with notifier
+ drop(mutex_guard);
+ handle.join().unwrap();
+ }
+
+ #[test]
+ fn wait_while_until_internal() {
+ let mutex = Arc::new(Mutex::new(0));
+ let cv = Arc::new(Condvar::new());
+
+ let num_iters = 4;
+
+ let condition = |counter: &mut u32| {
+ *counter += 1;
+ *counter <= num_iters
+ };
+
+ let mut mutex_guard = mutex.lock();
+ let handle = spawn_wait_while_notifier(mutex.clone(), cv.clone(), num_iters, None);
+
+ let timeout_result =
+ cv.wait_while_until_internal(&mut mutex_guard, condition, None);
+
+ assert!(!timeout_result.timed_out());
+ assert!(*mutex_guard == num_iters + 1);
+
+ let timeout_result = cv.wait_while_until_internal(&mut mutex_guard, condition, None);
+ handle.join().unwrap();
+
+ assert!(!timeout_result.timed_out());
+ assert!(*mutex_guard == num_iters + 2);
+ }
+
#[test]
#[should_panic]
fn two_mutexes() {
diff --git a/src/fair_mutex.rs b/src/fair_mutex.rs
index 3e4c163..d7d7a77 100644
--- a/src/fair_mutex.rs
+++ b/src/fair_mutex.rs
@@ -35,7 +35,7 @@ use lock_api;
/// - No poisoning, the lock is released normally on panic.
/// - Only requires 1 byte of space, whereas the standard library boxes the
/// `FairMutex` due to platform limitations.
-/// - Can be statically constructed (requires the `const_fn` nightly feature).
+/// - Can be statically constructed.
/// - Does not require any drop glue when dropped.
/// - Inline fast path for the uncontended case.
/// - Efficient handling of micro-contention using adaptive spinning.
diff --git a/src/mutex.rs b/src/mutex.rs
index 71bc351..f3f8aa9 100644
--- a/src/mutex.rs
+++ b/src/mutex.rs
@@ -42,7 +42,7 @@ use lock_api;
/// - No poisoning, the lock is released normally on panic.
/// - Only requires 1 byte of space, whereas the standard library boxes the
/// `Mutex` due to platform limitations.
-/// - Can be statically constructed (requires the `const_fn` nightly feature).
+/// - Can be statically constructed.
/// - Does not require any drop glue when dropped.
/// - Inline fast path for the uncontended case.
/// - Efficient handling of micro-contention using adaptive spinning.
diff --git a/src/once.rs b/src/once.rs
index f458c9c..6b91ac4 100644
--- a/src/once.rs
+++ b/src/once.rs
@@ -258,11 +258,11 @@ impl Once {
// Park our thread until we are woken up by the thread that owns the
// lock.
+ let addr = self as *const _ as usize;
+ let validate = || self.0.load(Ordering::Relaxed) == LOCKED_BIT | PARKED_BIT;
+ let before_sleep = || {};
+ let timed_out = |_, _| unreachable!();
unsafe {
- let addr = self as *const _ as usize;
- let validate = || self.0.load(Ordering::Relaxed) == LOCKED_BIT | PARKED_BIT;
- let before_sleep = || {};
- let timed_out = |_, _| unreachable!();
parking_lot_core::park(
addr,
validate,
@@ -285,8 +285,8 @@ impl Once {
let once = self.0;
let state = once.0.swap(POISON_BIT, Ordering::Release);
if state & PARKED_BIT != 0 {
+ let addr = once as *const _ as usize;
unsafe {
- let addr = once as *const _ as usize;
parking_lot_core::unpark_all(addr, DEFAULT_UNPARK_TOKEN);
}
}
@@ -307,8 +307,8 @@ impl Once {
// Now unlock the state, set the done bit and unpark all threads
let state = self.0.swap(DONE_BIT, Ordering::Release);
if state & PARKED_BIT != 0 {
+ let addr = self as *const _ as usize;
unsafe {
- let addr = self as *const _ as usize;
parking_lot_core::unpark_all(addr, DEFAULT_UNPARK_TOKEN);
}
}
diff --git a/src/raw_rwlock.rs b/src/raw_rwlock.rs
index 21d338b..6d1fef9 100644
--- a/src/raw_rwlock.rs
+++ b/src/raw_rwlock.rs
@@ -988,8 +988,8 @@ impl RawRwLock {
if let Err(x) = self.state.compare_exchange_weak(
state,
state | WRITER_PARKED_BIT,
- Ordering::Relaxed,
- Ordering::Relaxed,
+ Ordering::Acquire,
+ Ordering::Acquire,
) {
state = x;
continue;
diff --git a/src/rwlock.rs b/src/rwlock.rs
index 512114c..4167a85 100644
--- a/src/rwlock.rs
+++ b/src/rwlock.rs
@@ -55,7 +55,7 @@ use lock_api;
/// - No poisoning, the lock is released normally on panic.
/// - Only requires 1 word of space, whereas the standard library boxes the
/// `RwLock` due to platform limitations.
-/// - Can be statically constructed (requires the `const_fn` nightly feature).
+/// - Can be statically constructed.
/// - Does not require any drop glue when dropped.
/// - Inline fast path for the uncontended case.
/// - Efficient handling of micro-contention using adaptive spinning.