Skip to content

Commit 641b99d

Browse files
bors[bot]CryZe
andauthored
Merge #217
217: Implement Support for creating the locking primitives in a const context on stable Rust r=Amanieu a=CryZe This adds a new constructor `const_new` to lock_api's mutexes, reentrant mutexes and RwLocks that allows creating them in a constant context on stable Rust by manually passing in the underlying raw mutex / rwlock. Additionally, various helper functions are being added to parking_lot that allow creating mutexes, reentrant mutexes, fair mutexes and RwLocks in constant contexts on stable Rust. Co-authored-by: Christopher Serr <[email protected]>
2 parents fa294cd + b62d1f5 commit 641b99d

File tree

8 files changed

+91
-10
lines changed

8 files changed

+91
-10
lines changed

lock_api/src/mutex.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ pub unsafe trait RawMutexTimed: RawMutex {
9595
/// it is protecting. The data can only be accessed through the RAII guards
9696
/// returned from `lock` and `try_lock`, which guarantees that the data is only
9797
/// ever accessed when the mutex is locked.
98-
pub struct Mutex<R: RawMutex, T: ?Sized> {
98+
pub struct Mutex<R, T: ?Sized> {
9999
raw: R,
100100
data: UnsafeCell<T>,
101101
}
@@ -131,6 +131,19 @@ impl<R: RawMutex, T> Mutex<R, T> {
131131
}
132132
}
133133

134+
impl<R, T> Mutex<R, T> {
135+
/// Creates a new mutex based on a pre-existing raw mutex.
136+
///
137+
/// This allows creating a mutex in a constant context on stable Rust.
138+
#[inline]
139+
pub const fn const_new(raw_mutex: R, val: T) -> Mutex<R, T> {
140+
Mutex {
141+
raw: raw_mutex,
142+
data: UnsafeCell::new(val),
143+
}
144+
}
145+
}
146+
134147
impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
135148
/// # Safety
136149
///

lock_api/src/remutex.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub unsafe trait GetThreadId {
4747
fn nonzero_thread_id(&self) -> NonZeroUsize;
4848
}
4949

50-
struct RawReentrantMutex<R: RawMutex, G: GetThreadId> {
50+
struct RawReentrantMutex<R, G> {
5151
owner: AtomicUsize,
5252
lock_count: Cell<usize>,
5353
mutex: R,
@@ -145,7 +145,7 @@ impl<R: RawMutexTimed, G: GetThreadId> RawReentrantMutex<R, G> {
145145
///
146146
/// See [`Mutex`](struct.Mutex.html) for more details about the underlying mutex
147147
/// primitive.
148-
pub struct ReentrantMutex<R: RawMutex, G: GetThreadId, T: ?Sized> {
148+
pub struct ReentrantMutex<R, G, T: ?Sized> {
149149
raw: RawReentrantMutex<R, G>,
150150
data: UnsafeCell<T>,
151151
}
@@ -197,6 +197,26 @@ impl<R: RawMutex, G: GetThreadId, T> ReentrantMutex<R, G, T> {
197197
}
198198
}
199199

200+
impl<R, G, T> ReentrantMutex<R, G, T> {
201+
/// Creates a new reentrant mutex based on a pre-existing raw mutex and a
202+
/// helper to get the thread ID.
203+
///
204+
/// This allows creating a reentrant mutex in a constant context on stable
205+
/// Rust.
206+
#[inline]
207+
pub const fn const_new(raw_mutex: R, get_thread_id: G, val: T) -> ReentrantMutex<R, G, T> {
208+
ReentrantMutex {
209+
data: UnsafeCell::new(val),
210+
raw: RawReentrantMutex {
211+
owner: AtomicUsize::new(0),
212+
lock_count: Cell::new(0),
213+
mutex: raw_mutex,
214+
get_thread_id,
215+
},
216+
}
217+
}
218+
}
219+
200220
impl<R: RawMutex, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> {
201221
/// # Safety
202222
///

lock_api/src/rwlock.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ pub unsafe trait RawRwLockUpgradeTimed: RawRwLockUpgrade + RawRwLockTimed {
231231
/// allow concurrent access through readers. The RAII guards returned from the
232232
/// locking methods implement `Deref` (and `DerefMut` for the `write` methods)
233233
/// to allow access to the contained of the lock.
234-
pub struct RwLock<R: RawRwLock, T: ?Sized> {
234+
pub struct RwLock<R, T: ?Sized> {
235235
raw: R,
236236
data: UnsafeCell<T>,
237237
}
@@ -297,6 +297,21 @@ impl<R: RawRwLock, T> RwLock<R, T> {
297297
}
298298
}
299299

300+
impl<R, T> RwLock<R, T> {
301+
/// Creates a new new instance of an `RwLock<T>` based on a pre-existing
302+
/// `RawRwLock<T>`.
303+
///
304+
/// This allows creating a `RwLock<T>` in a constant context on stable
305+
/// Rust.
306+
#[inline]
307+
pub const fn const_new(raw_rwlock: R, val: T) -> RwLock<R, T> {
308+
RwLock {
309+
data: UnsafeCell::new(val),
310+
raw: raw_rwlock,
311+
}
312+
}
313+
}
314+
300315
impl<R: RawRwLock, T: ?Sized> RwLock<R, T> {
301316
/// # Safety
302317
///

src/fair_mutex.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ use lock_api;
8080
/// ```
8181
pub type FairMutex<T> = lock_api::Mutex<RawFairMutex, T>;
8282

83+
/// Creates a new fair mutex in an unlocked state ready for use.
84+
///
85+
/// This allows creating a fair mutex in a constant context on stable Rust.
86+
pub const fn const_fair_mutex<T>(val: T) -> FairMutex<T> {
87+
FairMutex::const_new(<RawFairMutex as lock_api::RawMutex>::INIT, val)
88+
}
89+
8390
/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
8491
/// dropped (falls out of scope), the lock will be unlocked.
8592
///

src/lib.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ mod elision;
1818
mod fair_mutex;
1919
mod mutex;
2020
mod once;
21-
mod raw_mutex;
2221
mod raw_fair_mutex;
22+
mod raw_mutex;
2323
mod raw_rwlock;
2424
mod remutex;
2525
mod rwlock;
@@ -31,17 +31,18 @@ pub mod deadlock;
3131
mod deadlock;
3232

3333
pub use self::condvar::{Condvar, WaitTimeoutResult};
34-
pub use self::mutex::{MappedMutexGuard, Mutex, MutexGuard};
35-
pub use self::fair_mutex::{MappedFairMutexGuard, FairMutex, FairMutexGuard};
34+
pub use self::fair_mutex::{const_fair_mutex, FairMutex, FairMutexGuard, MappedFairMutexGuard};
35+
pub use self::mutex::{const_mutex, MappedMutexGuard, Mutex, MutexGuard};
3636
pub use self::once::{Once, OnceState};
37-
pub use self::raw_mutex::RawMutex;
3837
pub use self::raw_fair_mutex::RawFairMutex;
38+
pub use self::raw_mutex::RawMutex;
3939
pub use self::raw_rwlock::RawRwLock;
4040
pub use self::remutex::{
41-
MappedReentrantMutexGuard, RawThreadId, ReentrantMutex, ReentrantMutexGuard,
41+
const_reentrant_mutex, MappedReentrantMutexGuard, RawThreadId, ReentrantMutex,
42+
ReentrantMutexGuard,
4243
};
4344
pub use self::rwlock::{
44-
MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard,
45+
const_rwlock, MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard,
4546
RwLockUpgradableReadGuard, RwLockWriteGuard,
4647
};
4748
pub use ::lock_api;

src/mutex.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ use lock_api;
8686
/// ```
8787
pub type Mutex<T> = lock_api::Mutex<RawMutex, T>;
8888

89+
/// Creates a new mutex in an unlocked state ready for use.
90+
///
91+
/// This allows creating a mutex in a constant context on stable Rust.
92+
pub const fn const_mutex<T>(val: T) -> Mutex<T> {
93+
Mutex::const_new(<RawMutex as lock_api::RawMutex>::INIT, val)
94+
}
95+
8996
/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
9097
/// dropped (falls out of scope), the lock will be unlocked.
9198
///

src/remutex.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ unsafe impl GetThreadId for RawThreadId {
4040
/// primitive.
4141
pub type ReentrantMutex<T> = lock_api::ReentrantMutex<RawMutex, RawThreadId, T>;
4242

43+
/// Creates a new reentrant mutex in an unlocked state ready for use.
44+
///
45+
/// This allows creating a reentrant mutex in a constant context on stable Rust.
46+
pub const fn const_reentrant_mutex<T>(val: T) -> ReentrantMutex<T> {
47+
ReentrantMutex::const_new(
48+
<RawMutex as lock_api::RawMutex>::INIT,
49+
<RawThreadId as lock_api::GetThreadId>::INIT,
50+
val,
51+
)
52+
}
53+
4354
/// An RAII implementation of a "scoped lock" of a reentrant mutex. When this structure
4455
/// is dropped (falls out of scope), the lock will be unlocked.
4556
///

src/rwlock.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ use lock_api;
8888
/// ```
8989
pub type RwLock<T> = lock_api::RwLock<RawRwLock, T>;
9090

91+
/// Creates a new instance of an `RwLock<T>` which is unlocked.
92+
///
93+
/// This allows creating a `RwLock<T>` in a constant context on stable Rust.
94+
pub const fn const_rwlock<T>(val: T) -> RwLock<T> {
95+
RwLock::const_new(<RawRwLock as lock_api::RawRwLock>::INIT, val)
96+
}
97+
9198
/// RAII structure used to release the shared read access of a lock when
9299
/// dropped.
93100
pub type RwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, RawRwLock, T>;

0 commit comments

Comments
 (0)