summaryrefslogtreecommitdiffstats
path: root/third_party/rust/try-lock
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/try-lock
parentInitial commit. (diff)
downloadfirefox-esr-upstream.tar.xz
firefox-esr-upstream.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/try-lock')
-rw-r--r--third_party/rust/try-lock/.cargo-checksum.json1
-rw-r--r--third_party/rust/try-lock/Cargo.toml31
-rw-r--r--third_party/rust/try-lock/LICENSE21
-rw-r--r--third_party/rust/try-lock/README.md44
-rw-r--r--third_party/rust/try-lock/src/lib.rs275
5 files changed, 372 insertions, 0 deletions
diff --git a/third_party/rust/try-lock/.cargo-checksum.json b/third_party/rust/try-lock/.cargo-checksum.json
new file mode 100644
index 0000000000..0afb2c606c
--- /dev/null
+++ b/third_party/rust/try-lock/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"fb6a5cac265146347b3fe5d8dbc01c6366e8411b11939e3befe23d14a7c13514","LICENSE":"69127cd697ac8e4da8d4a206ae067bbeb2aef41618c4be521509772110c4f202","README.md":"976bf116dd8794213bd242a61f819811a5c5a0fd4372acdbd21308863c05cfb6","src/lib.rs":"ececfc64a1b584fa42a5aa2d2d88f7c8d230ab96f70a038137411c7134763dc4"},"package":"3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"} \ No newline at end of file
diff --git a/third_party/rust/try-lock/Cargo.toml b/third_party/rust/try-lock/Cargo.toml
new file mode 100644
index 0000000000..dab6cacc44
--- /dev/null
+++ b/third_party/rust/try-lock/Cargo.toml
@@ -0,0 +1,31 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# 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.
+#
+# 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.
+
+[package]
+name = "try-lock"
+version = "0.2.4"
+authors = ["Sean McArthur <sean@seanmonstar.com>"]
+description = "A lightweight atomic lock."
+homepage = "https://github.com/seanmonstar/try-lock"
+documentation = "https://docs.rs/try-lock"
+readme = "README.md"
+keywords = [
+ "lock",
+ "atomic",
+]
+categories = [
+ "concurrency",
+ "no-std",
+]
+license = "MIT"
+repository = "https://github.com/seanmonstar/try-lock"
+
+[dependencies]
diff --git a/third_party/rust/try-lock/LICENSE b/third_party/rust/try-lock/LICENSE
new file mode 100644
index 0000000000..5cddb267af
--- /dev/null
+++ b/third_party/rust/try-lock/LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2018 Sean McArthur
+Copyright (c) 2016 Alex Crichton
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/third_party/rust/try-lock/README.md b/third_party/rust/try-lock/README.md
new file mode 100644
index 0000000000..abbb0eac47
--- /dev/null
+++ b/third_party/rust/try-lock/README.md
@@ -0,0 +1,44 @@
+# TryLock
+
+- [Crates.io](https://crates.io/crates/try-lock)
+- [Docs](https://docs.rs/try-lock)
+
+A light-weight lock guarded by an atomic boolean.
+
+Most efficient when contention is low, acquiring the lock is a single atomic swap, and releasing it just 1 more atomic swap.
+
+## Example
+
+```rust
+use std::sync::Arc;
+use try_lock::TryLock;
+
+// a thing we want to share
+struct Widget {
+ name: String,
+}
+
+// lock it up!
+let widget1 = Arc::new(TryLock::new(Widget {
+ name: "Spanner".into(),
+}));
+
+let widget2 = widget1.clone();
+
+
+// mutate the widget
+let mut locked = widget1.try_lock().expect("example isn't locked yet");
+locked.name.push_str(" Bundle");
+
+// hands off, buddy
+let not_locked = widget2.try_lock();
+assert!(not_locked.is_none(), "widget1 has the lock");
+
+// ok, you can have it
+drop(locked);
+
+let locked2 = widget2.try_lock().expect("widget1 lock is released");
+
+assert_eq!(locked2.name, "Spanner Bundle");
+```
+
diff --git a/third_party/rust/try-lock/src/lib.rs b/third_party/rust/try-lock/src/lib.rs
new file mode 100644
index 0000000000..80a240efe1
--- /dev/null
+++ b/third_party/rust/try-lock/src/lib.rs
@@ -0,0 +1,275 @@
+#![doc(html_root_url = "https://docs.rs/try-lock/0.2.3")]
+#![deny(missing_docs)]
+#![deny(missing_debug_implementations)]
+#![deny(warnings)]
+#![cfg_attr(not(test), no_std)]
+
+//! A light-weight lock guarded by an atomic boolean.
+//!
+//! Most efficient when contention is low, acquiring the lock is a single
+//! atomic swap, and releasing it just 1 more atomic swap.
+//!
+//! # Example
+//!
+//! ```
+//! use std::sync::Arc;
+//! use try_lock::TryLock;
+//!
+//! // a thing we want to share
+//! struct Widget {
+//! name: String,
+//! }
+//!
+//! // lock it up!
+//! let widget1 = Arc::new(TryLock::new(Widget {
+//! name: "Spanner".into(),
+//! }));
+//!
+//! let widget2 = widget1.clone();
+//!
+//!
+//! // mutate the widget
+//! let mut locked = widget1.try_lock().expect("example isn't locked yet");
+//! locked.name.push_str(" Bundle");
+//!
+//! // hands off, buddy
+//! let not_locked = widget2.try_lock();
+//! assert!(not_locked.is_none(), "widget1 has the lock");
+//!
+//! // ok, you can have it
+//! drop(locked);
+//!
+//! let locked2 = widget2.try_lock().expect("widget1 lock is released");
+//!
+//! assert_eq!(locked2.name, "Spanner Bundle");
+//! ```
+
+#[cfg(test)]
+extern crate core;
+
+use core::cell::UnsafeCell;
+use core::fmt;
+use core::ops::{Deref, DerefMut};
+use core::sync::atomic::{AtomicBool, Ordering};
+use core::marker::PhantomData;
+
+/// A light-weight lock guarded by an atomic boolean.
+///
+/// Most efficient when contention is low, acquiring the lock is a single
+/// atomic swap, and releasing it just 1 more atomic swap.
+///
+/// It is only possible to try to acquire the lock, it is not possible to
+/// wait for the lock to become ready, like with a `Mutex`.
+#[derive(Default)]
+pub struct TryLock<T> {
+ is_locked: AtomicBool,
+ value: UnsafeCell<T>,
+}
+
+impl<T> TryLock<T> {
+ /// Create a `TryLock` around the value.
+ #[inline]
+ pub fn new(val: T) -> TryLock<T> {
+ TryLock {
+ is_locked: AtomicBool::new(false),
+ value: UnsafeCell::new(val),
+ }
+ }
+
+ /// Try to acquire the lock of this value.
+ ///
+ /// If the lock is already acquired by someone else, this returns
+ /// `None`. You can try to acquire again whenever you want, perhaps
+ /// by spinning a few times, or by using some other means of
+ /// notification.
+ ///
+ /// # Note
+ ///
+ /// The default memory ordering is to use `Acquire` to lock, and `Release`
+ /// to unlock. If different ordering is required, use
+ /// [`try_lock_explicit`](TryLock::try_lock_explicit) or
+ /// [`try_lock_explicit_unchecked`](TryLock::try_lock_explicit_unchecked).
+ #[inline]
+ pub fn try_lock(&self) -> Option<Locked<T>> {
+ unsafe {
+ self.try_lock_explicit_unchecked(Ordering::Acquire, Ordering::Release)
+ }
+ }
+
+ /// Try to acquire the lock of this value using the lock and unlock orderings.
+ ///
+ /// If the lock is already acquired by someone else, this returns
+ /// `None`. You can try to acquire again whenever you want, perhaps
+ /// by spinning a few times, or by using some other means of
+ /// notification.
+ #[inline]
+ #[deprecated(
+ since = "0.2.3",
+ note = "This method is actually unsafe because it unsafely allows \
+ the use of weaker memory ordering. Please use try_lock_explicit instead"
+ )]
+ pub fn try_lock_order(&self, lock_order: Ordering, unlock_order: Ordering) -> Option<Locked<T>> {
+ unsafe {
+ self.try_lock_explicit_unchecked(lock_order, unlock_order)
+ }
+ }
+
+ /// Try to acquire the lock of this value using the specified lock and
+ /// unlock orderings.
+ ///
+ /// If the lock is already acquired by someone else, this returns
+ /// `None`. You can try to acquire again whenever you want, perhaps
+ /// by spinning a few times, or by using some other means of
+ /// notification.
+ ///
+ /// # Panic
+ ///
+ /// This method panics if `lock_order` is not any of `Acquire`, `AcqRel`,
+ /// and `SeqCst`, or `unlock_order` is not any of `Release` and `SeqCst`.
+ #[inline]
+ pub fn try_lock_explicit(&self, lock_order: Ordering, unlock_order: Ordering) -> Option<Locked<T>> {
+ match lock_order {
+ Ordering::Acquire |
+ Ordering::AcqRel |
+ Ordering::SeqCst => {}
+ _ => panic!("lock ordering must be `Acquire`, `AcqRel`, or `SeqCst`"),
+ }
+
+ match unlock_order {
+ Ordering::Release |
+ Ordering::SeqCst => {}
+ _ => panic!("unlock ordering must be `Release` or `SeqCst`"),
+ }
+
+ unsafe {
+ self.try_lock_explicit_unchecked(lock_order, unlock_order)
+ }
+ }
+
+ /// Try to acquire the lock of this value using the specified lock and
+ /// unlock orderings without checking that the specified orderings are
+ /// strong enough to be safe.
+ ///
+ /// If the lock is already acquired by someone else, this returns
+ /// `None`. You can try to acquire again whenever you want, perhaps
+ /// by spinning a few times, or by using some other means of
+ /// notification.
+ ///
+ /// # Safety
+ ///
+ /// Unlike [`try_lock_explicit`], this method is unsafe because it does not
+ /// check that the given memory orderings are strong enough to prevent data
+ /// race.
+ ///
+ /// [`try_lock_explicit`]: Self::try_lock_explicit
+ #[inline]
+ pub unsafe fn try_lock_explicit_unchecked(&self, lock_order: Ordering, unlock_order: Ordering) -> Option<Locked<T>> {
+ if !self.is_locked.swap(true, lock_order) {
+ Some(Locked {
+ lock: self,
+ order: unlock_order,
+ _p: PhantomData,
+ })
+ } else {
+ None
+ }
+ }
+
+ /// Take the value back out of the lock when this is the sole owner.
+ #[inline]
+ pub fn into_inner(self) -> T {
+ debug_assert!(!self.is_locked.load(Ordering::Relaxed), "TryLock was mem::forgotten");
+ // Since the compiler can statically determine this is the only owner,
+ // it's safe to take the value out. In fact, in newer versions of Rust,
+ // `UnsafeCell::into_inner` has been marked safe.
+ //
+ // To support older version (1.21), the unsafe block is still here.
+ #[allow(unused_unsafe)]
+ unsafe {
+ self.value.into_inner()
+ }
+ }
+}
+
+unsafe impl<T: Send> Send for TryLock<T> {}
+unsafe impl<T: Send> Sync for TryLock<T> {}
+
+impl<T: fmt::Debug> fmt::Debug for TryLock<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+
+ // Used if the TryLock cannot acquire the lock.
+ struct LockedPlaceholder;
+
+ impl fmt::Debug for LockedPlaceholder {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("<locked>")
+ }
+ }
+
+ let mut builder = f.debug_struct("TryLock");
+ if let Some(locked) = self.try_lock() {
+ builder.field("value", &*locked);
+ } else {
+ builder.field("value", &LockedPlaceholder);
+ }
+ builder.finish()
+ }
+}
+
+/// A locked value acquired from a `TryLock`.
+///
+/// The type represents an exclusive view at the underlying value. The lock is
+/// released when this type is dropped.
+///
+/// This type derefs to the underlying value.
+#[must_use = "TryLock will immediately unlock if not used"]
+pub struct Locked<'a, T: 'a> {
+ lock: &'a TryLock<T>,
+ order: Ordering,
+ /// Suppresses Send and Sync autotraits for `struct Locked`.
+ _p: PhantomData<*mut T>,
+}
+
+impl<'a, T> Deref for Locked<'a, T> {
+ type Target = T;
+ #[inline]
+ fn deref(&self) -> &T {
+ unsafe { &*self.lock.value.get() }
+ }
+}
+
+impl<'a, T> DerefMut for Locked<'a, T> {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut T {
+ unsafe { &mut *self.lock.value.get() }
+ }
+}
+
+impl<'a, T> Drop for Locked<'a, T> {
+ #[inline]
+ fn drop(&mut self) {
+ self.lock.is_locked.store(false, self.order);
+ }
+}
+
+impl<'a, T: fmt::Debug> fmt::Debug for Locked<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Debug::fmt(&**self, f)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::TryLock;
+
+ #[test]
+ fn fmt_debug() {
+ let lock = TryLock::new(5);
+ assert_eq!(format!("{:?}", lock), "TryLock { value: 5 }");
+
+ let locked = lock.try_lock().unwrap();
+ assert_eq!(format!("{:?}", locked), "5");
+
+ assert_eq!(format!("{:?}", lock), "TryLock { value: <locked> }");
+ }
+}