Skip to content

Commit

Permalink
Add new const_new function to lock_api
Browse files Browse the repository at this point in the history
This new constructor allows creating mutexes, reentrant mutexes and
RwLocks in a constant context on stable Rust by manually passing in the
underlying raw mutex / rwlock.
  • Loading branch information
CryZe committed Feb 18, 2020
1 parent fa294cd commit a9961d4
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 4 deletions.
14 changes: 13 additions & 1 deletion lock_api/src/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub unsafe trait RawMutexTimed: RawMutex {
/// it is protecting. The data can only be accessed through the RAII guards
/// returned from `lock` and `try_lock`, which guarantees that the data is only
/// ever accessed when the mutex is locked.
pub struct Mutex<R: RawMutex, T: ?Sized> {
pub struct Mutex<R, T: ?Sized> {
raw: R,
data: UnsafeCell<T>,
}
Expand Down Expand Up @@ -131,6 +131,18 @@ impl<R: RawMutex, T> Mutex<R, T> {
}
}

impl<R, T> Mutex<R, T> {
/// Creates a new mutex based on a pre-existing raw mutex. This allows
/// creating a mutex in a constant context on stable Rust.
#[inline]
pub const fn const_new(raw_mutex: R, val: T) -> Mutex<R, T> {
Mutex {
raw: raw_mutex,
data: UnsafeCell::new(val),
}
}
}

impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
/// # Safety
///
Expand Down
26 changes: 24 additions & 2 deletions lock_api/src/remutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub unsafe trait GetThreadId {
fn nonzero_thread_id(&self) -> NonZeroUsize;
}

struct RawReentrantMutex<R: RawMutex, G: GetThreadId> {
struct RawReentrantMutex<R, G> {
owner: AtomicUsize,
lock_count: Cell<usize>,
mutex: R,
Expand Down Expand Up @@ -145,7 +145,7 @@ impl<R: RawMutexTimed, G: GetThreadId> RawReentrantMutex<R, G> {
///
/// See [`Mutex`](struct.Mutex.html) for more details about the underlying mutex
/// primitive.
pub struct ReentrantMutex<R: RawMutex, G: GetThreadId, T: ?Sized> {
pub struct ReentrantMutex<R, G, T: ?Sized> {
raw: RawReentrantMutex<R, G>,
data: UnsafeCell<T>,
}
Expand Down Expand Up @@ -197,6 +197,28 @@ impl<R: RawMutex, G: GetThreadId, T> ReentrantMutex<R, G, T> {
}
}

impl<R, G, T> ReentrantMutex<R, G, T> {
/// Creates a new reentrant mutex based on a pre-existing raw reentrant
/// mutex and a helper to get the thread ID. This allows creating a
/// reentrant mutex in a constant context on stable Rust.
#[inline]
pub const fn const_new(
raw_reentrant_mutex: R,
get_thread_id: G,
val: T,
) -> ReentrantMutex<R, G, T> {
ReentrantMutex {
data: UnsafeCell::new(val),
raw: RawReentrantMutex {
owner: AtomicUsize::new(0),
lock_count: Cell::new(0),
mutex: raw_reentrant_mutex,
get_thread_id,
},
}
}
}

impl<R: RawMutex, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> {
/// # Safety
///
Expand Down
15 changes: 14 additions & 1 deletion lock_api/src/rwlock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ pub unsafe trait RawRwLockUpgradeTimed: RawRwLockUpgrade + RawRwLockTimed {
/// allow concurrent access through readers. The RAII guards returned from the
/// locking methods implement `Deref` (and `DerefMut` for the `write` methods)
/// to allow access to the contained of the lock.
pub struct RwLock<R: RawRwLock, T: ?Sized> {
pub struct RwLock<R, T: ?Sized> {
raw: R,
data: UnsafeCell<T>,
}
Expand Down Expand Up @@ -297,6 +297,19 @@ impl<R: RawRwLock, T> RwLock<R, T> {
}
}

impl<R, T> RwLock<R, T> {
/// Creates a new new instance of an `RwLock<T>` based on a pre-existing
/// `RawRwLock<T>`. This allows creating a `RwLock<T>` in a constant context
/// on stable Rust.
#[inline]
pub const fn const_new(raw_rwlock: R, val: T) -> RwLock<R, T> {
RwLock {
data: UnsafeCell::new(val),
raw: raw_rwlock,
}
}
}

impl<R: RawRwLock, T: ?Sized> RwLock<R, T> {
/// # Safety
///
Expand Down

0 comments on commit a9961d4

Please sign in to comment.