Skip to content

Commit 248d293

Browse files
committed
Add shuttle-parking_lot
1 parent d00bba1 commit 248d293

File tree

12 files changed

+261
-38
lines changed

12 files changed

+261
-38
lines changed

Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
[workspace]
22
members = [
33
"shuttle",
4-
"wrappers/shuttle_rand_0.8",
5-
"wrappers/shuttle_sync",
4+
"wrappers/rand_0.8",
5+
"wrappers/sync",
6+
"wrappers/parking_lot",
67
]
78

8-
resolver = "2"
9+
resolver = "2"

wrappers/parking_lot/Cargo.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[package]
2+
name = "shuttle-parking_lot"
3+
version = "0.12.5"
4+
edition = "2024"
5+
6+
[features]
7+
shuttle = [ "dep:shuttle-parking_lot-impl" ]
8+
9+
arc_lock = [ "parking_lot/arc_lock", "shuttle-parking_lot-impl?/arc_lock" ]
10+
deadlock_detection = [ "parking_lot/deadlock_detection", "shuttle-parking_lot-impl?/deadlock_detection" ]
11+
hardware-lock-elision = [ "parking_lot/hardware-lock-elision", "shuttle-parking_lot-impl?/hardware-lock-elision" ]
12+
nightly = [ "parking_lot/nightly", "shuttle-parking_lot-impl?/nightly" ]
13+
owning_ref = [ "parking_lot/owning_ref", "shuttle-parking_lot-impl?/owning_ref" ]
14+
send_guard = [ "parking_lot/send_guard", "shuttle-parking_lot-impl?/send_guard" ]
15+
serde = [ "parking_lot/serde", "shuttle-parking_lot-impl?/serde" ]
16+
17+
[dependencies]
18+
cfg-if = "1.0"
19+
parking_lot = "0.12"
20+
shuttle-parking_lot-impl = { path = "./parking_lot_impl", version = "0.1.0", optional = true }
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "shuttle-parking_lot-impl"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[features]
7+
arc_lock = []
8+
deadlock_detection = []
9+
hardware-lock-elision = []
10+
nightly = []
11+
owning_ref = []
12+
send_guard = []
13+
serde = []
14+
15+
[dependencies]
16+
shuttle = { path = "../../../shuttle", version = "*"}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
//! This crate contains Shuttle's internal implementations of the `parking_lot` crate.
2+
//! Do not depend on this crate directly. Use the `shuttle-parking_lot` crate, which conditionally
3+
//! exposes these implementations with the `shuttle` feature or the original crate without it.
4+
//!
5+
//! [`Shuttle`]: <https://crates.io/crates/shuttle>
6+
//!
7+
//! [`parking_lot`]: <https://crates.io/crates/parking_lot>
8+
9+
use shuttle::sync;
10+
11+
// TODO: All the `expect`s below are wrong — it is possible to poison a Shuttle mutex.
12+
// `clear_poison` should be added and used to avoid the `expect`.
13+
// TODO: Shuttle should be split up into a "core" crate which offers a more versatile
14+
// Mutex which is parametric on poisoning (and this crate would initialize it as non-poisonable)
15+
16+
#[derive(Default, Debug)]
17+
pub struct Mutex<T: ?Sized> {
18+
inner: sync::Mutex<T>,
19+
}
20+
21+
pub use sync::{MutexGuard, RwLockReadGuard, RwLockWriteGuard};
22+
23+
impl<T> Mutex<T> {
24+
/// Creates a new mutex in an unlocked state ready for use.
25+
pub fn new(value: T) -> Self {
26+
Self {
27+
inner: sync::Mutex::new(value),
28+
}
29+
}
30+
31+
/// Consumes this mutex, returning the underlying data.
32+
#[inline]
33+
pub fn into_inner(self) -> T {
34+
self.inner
35+
.into_inner()
36+
.expect("This shouldn't happen as there is no way to poision a Shuttle Mutex.")
37+
}
38+
}
39+
40+
impl<T: ?Sized> Mutex<T> {
41+
/// Acquires a mutex, blocking the current thread until it is able to do so.
42+
///
43+
/// This function will block the local thread until it is available to acquire
44+
/// the mutex. Upon returning, the thread is the only thread with the mutex
45+
/// held. An RAII guard is returned to allow scoped unlock of the lock. When
46+
/// the guard goes out of scope, the mutex will be unlocked.
47+
///
48+
/// Attempts to lock a mutex in the thread which already holds the lock will
49+
/// result in a deadlock.
50+
#[inline]
51+
pub fn lock(&self) -> sync::MutexGuard<'_, T> {
52+
self.inner
53+
.lock()
54+
.expect("This shouldn't happen as there is no way to poision a Shuttle Mutex.")
55+
}
56+
57+
/// Attempts to acquire this lock.
58+
///
59+
/// If the lock could not be acquired at this time, then `None` is returned.
60+
/// Otherwise, an RAII guard is returned. The lock will be unlocked when the
61+
/// guard is dropped.
62+
#[inline]
63+
pub fn try_lock(&self) -> Option<sync::MutexGuard<'_, T>> {
64+
self.inner.try_lock().ok()
65+
}
66+
}
67+
68+
/// A reader-writer lock
69+
#[derive(Debug, Default)]
70+
pub struct RwLock<T: ?Sized> {
71+
inner: sync::RwLock<T>,
72+
}
73+
74+
impl<T> RwLock<T> {
75+
/// Creates a new instance of an `RwLock<T>` which is unlocked.
76+
pub fn new(value: T) -> Self {
77+
Self {
78+
inner: sync::RwLock::new(value),
79+
}
80+
}
81+
82+
/// Consumes this `RwLock`, returning the underlying data.
83+
#[inline]
84+
pub fn into_inner(self) -> T {
85+
self.inner
86+
.into_inner()
87+
.expect("This shouldn't happen as there is no way to poision a Shuttle RwLock.")
88+
}
89+
}
90+
91+
impl<T: ?Sized> RwLock<T> {
92+
/// Locks this `RwLock` with shared read access, blocking the current thread
93+
/// until it can be acquired.
94+
///
95+
/// The calling thread will be blocked until there are no more writers which
96+
/// hold the lock. There may be other readers currently inside the lock when
97+
/// this method returns.
98+
///
99+
/// Note that attempts to recursively acquire a read lock on a `RwLock` when
100+
/// the current thread already holds one may result in a deadlock.
101+
///
102+
/// Returns an RAII guard which will release this thread's shared access
103+
/// once it is dropped.
104+
#[inline]
105+
pub fn read(&self) -> RwLockReadGuard<'_, T> {
106+
self.inner
107+
.read()
108+
.expect("This shouldn't happen as there is no way to poision a Shuttle RwLock.")
109+
}
110+
111+
/// Attempts to acquire this `RwLock` with shared read access.
112+
///
113+
/// If the access could not be granted at this time, then `None` is returned.
114+
/// Otherwise, an RAII guard is returned which will release the shared access
115+
/// when it is dropped.
116+
///
117+
/// This function does not block.
118+
#[inline]
119+
pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T>> {
120+
self.inner.try_read().ok()
121+
}
122+
123+
/// Locks this `RwLock` with exclusive write access, blocking the current
124+
/// thread until it can be acquired.
125+
///
126+
/// This function will not return while other writers or other readers
127+
/// currently have access to the lock.
128+
///
129+
/// Returns an RAII guard which will drop the write access of this `RwLock`
130+
/// when dropped.
131+
#[inline]
132+
pub fn write(&self) -> RwLockWriteGuard<'_, T> {
133+
self.inner
134+
.write()
135+
.expect("This shouldn't happen as there is no way to poision a Shuttle RwLock.")
136+
}
137+
138+
/// Attempts to lock this `RwLock` with exclusive write access.
139+
///
140+
/// If the lock could not be acquired at this time, then `None` is returned.
141+
/// Otherwise, an RAII guard is returned which will release the lock when
142+
/// it is dropped.
143+
///
144+
/// This function does not block.
145+
#[inline]
146+
pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, T>> {
147+
self.inner.try_write().ok()
148+
}
149+
}

wrappers/parking_lot/src/lib.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//! This crate provides a Shuttle-compatible implementation and wrapper for [`parking_lot`] in order to make it
2+
//! more ergonomic to run a codebase under Shuttle.
3+
//!
4+
//! [`parking_lot`]: <https://crates.io/crates/parking_lot>
5+
//!
6+
//! To use this crate, add something akin to the following to your Cargo.toml:
7+
//!
8+
//! ```ignore
9+
//! [features]
10+
//! shuttle = [
11+
//! "parking_lot/shuttle",
12+
//! ]
13+
//!
14+
//! [dependencies]
15+
//! parking_lot = { package = "shuttle-parking_lot", version = "0.12" }
16+
//! ```
17+
//!
18+
//! The rest of the codebase then remains unchanged, and running with Shuttle-compatible `parking_lot` can be done via the "shuttle" feature flag.
19+
//!
20+
//! By default the version of `parking_lot` exported is the latest `0.12` version (the same as if you had written `parking_lot = "0.12"` in your Cargo.toml).
21+
//! If you need to constrain the version of `parking_lot` that you depend on (eg. to pin the version), then this can be done by adding an entry like:
22+
//!
23+
//! ```ignore
24+
//! [dependencies]
25+
//! parking_lot-version-import-dont-use = { package = "parking_lot", version = "=0.12.5" }
26+
//! ```
27+
28+
cfg_if::cfg_if! {
29+
if #[cfg(feature = "shuttle")] {
30+
pub use shuttle_parking_lot_impl::*;
31+
} else {
32+
pub use parking_lot::*;
33+
}
34+
}

wrappers/rand_0.8/Cargo.toml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[package]
2+
name = "shuttle-rand"
3+
version = "0.8.5"
4+
edition = "2024"
5+
6+
[features]
7+
shuttle = [ "dep:shuttle-rand-impl" ]
8+
9+
alloc = ["rand/alloc", "shuttle-rand-impl/alloc"]
10+
getrandom = [ "rand/getrandom", "shuttle-rand-impl/getrandom" ]
11+
min_const_gen = [ "rand/min_const_gen", "shuttle-rand-impl/min_const_gen" ]
12+
nightly = [ "rand/nightly", "shuttle-rand-impl/nightly" ]
13+
serde1 = [ "rand/serde1", "shuttle-rand-impl/serde1" ]
14+
simd_support = [ "rand/simd_support", "shuttle-rand-impl/simd_support" ]
15+
small_rng = [ "rand/small_rng", "shuttle-rand-impl/small_rng" ]
16+
std = [ "rand/std", "shuttle-rand-impl/std" ]
17+
std_rng = [ "rand/std_rng", "shuttle-rand-impl/std_rng" ]
18+
19+
[dependencies]
20+
cfg-if = "1.0"
21+
rand = "0.8"
22+
shuttle-rand-impl = { path = "./shuttle_rand_impl", version = "0.1.0", optional = true }

wrappers/shuttle_rand_0.8/shuttle_rand_inner/Cargo.toml renamed to wrappers/rand_0.8/shuttle_rand_impl/Cargo.toml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
[package]
2-
name = "shuttle-rand-inner"
2+
name = "shuttle-rand-impl"
33
version = "0.1.0"
44
edition = "2024"
55

66
[features]
77
alloc = []
8-
default = []
98
getrandom = []
109
min_const_gen = []
1110
nightly = []
@@ -18,5 +17,3 @@ std_rng = []
1817
[dependencies]
1918
shuttle = { path = "../../../shuttle", version = "*"}
2019
rand-orig = { package = "rand", version = "0.8" }
21-
22-

wrappers/shuttle_rand_0.8/shuttle_rand_inner/src/lib.rs renamed to wrappers/rand_0.8/shuttle_rand_impl/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
//! This is the "inner" crate implementing [`rand` version 0.8] support for [`Shuttle`].
2-
//! This crate should not be depended on directly, the intended way to use this crate is via
3-
//! the `shuttle-rand` crate and feature flag `shuttle`.
1+
//! This crate contains Shuttle's internal implementations of the `rand` crate.
2+
//! Do not depend on this crate directly. Use the `shuttle-rand` crate, which conditionally
3+
//! exposes these implementations with the `shuttle` feature or the original crate without it.
44
//!
55
//! [`Shuttle`]: <https://crates.io/crates/shuttle>
66
//!
Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,19 @@
1616
//! ```
1717
//!
1818
//! The rest of the codebase then remains unchanged, and running with Shuttle-compatible `rand` can be done via the "shuttle" feature flag.
19+
//!
20+
//! By default the version of `rand` exported is the latest `0.8` version (the same as if you had written `rand = "0.8"` in your Cargo.toml).
21+
//! If you need to constrain the version of `rand` that you depend on (eg. to pin the version), then this can be done by adding an entry like:
22+
//!
23+
//! ```ignore
24+
//! [dependencies]
25+
//! rand-version-import-dont-use = { package = "rand", version = "=0.8.5" }
26+
//! ```
1927
2028
cfg_if::cfg_if! {
2129
if #[cfg(feature = "shuttle")] {
22-
pub use shuttle_rand_inner::*;
30+
pub use shuttle_rand_impl::*;
2331
} else {
24-
pub use rand_orig::*;
32+
pub use rand::*;
2533
}
2634
}

wrappers/shuttle_rand_0.8/Cargo.toml

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)