Skip to content

Commit 53abc69

Browse files
committed
fix: proper bounds and comments for lockguard.
1 parent 50ffab9 commit 53abc69

File tree

4 files changed

+20
-8
lines changed

4 files changed

+20
-8
lines changed

src/lock/api.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use core::ops::{Deref, DerefMut};
1212
pub unsafe trait RawLock: Default + Send + Sync {
1313
/// Raw lock's token type.
1414
///
15-
/// We don't enforce Send + Sync, as some locks may not satisfy it. Necessary bounds will be
16-
/// auto-derived.
15+
/// We don't enforce Send/Sync, as some locks may not satisfy it. We restrict them at
16+
/// Send/Sync impl for [LockGuard].
1717
type Token;
1818

1919
/// Acquires the raw lock.
@@ -87,13 +87,22 @@ impl<L: RawTryLock, T> Lock<L, T> {
8787
}
8888

8989
/// A guard that holds the lock and dereferences the inner value.
90-
// `Send` and `Sync` are automatically derived.
9190
#[derive(Debug)]
9291
pub struct LockGuard<'s, L: RawLock, T> {
9392
lock: &'s Lock<L, T>,
9493
token: ManuallyDrop<L::Token>,
9594
}
9695

96+
// Not auto derived as the auto-derived impls are incorrect. Remember, auto-derived impls are only
97+
// correct if there are no unsafe code used in the struct's methods.
98+
99+
// SAFETY: Ownership of `LockGuard` implies ownership of `L::Token` and `T`. Thus, they must both be
100+
// `Send`.
101+
unsafe impl<L: RawLock, T: Send> Send for LockGuard<'_, L, T> where L::Token: Send {}
102+
103+
// SAFETY: Reference to `LockGuard` implies reference to `T`. Thus, `T` must be `Sync`.
104+
unsafe impl<L: RawLock, T: Sync> Sync for LockGuard<'_, L, T> {}
105+
97106
impl<L: RawLock, T> Drop for LockGuard<'_, L, T> {
98107
fn drop(&mut self) {
99108
// SAFETY: `self.token` is not used anymore in this function, and as we are `drop`ing
@@ -110,14 +119,17 @@ impl<L: RawLock, T> Deref for LockGuard<'_, L, T> {
110119
type Target = T;
111120

112121
fn deref(&self) -> &Self::Target {
113-
// SAFETY: Having a `LockGuard` means the underlying lock is acquired.
122+
// SAFETY: Having a `LockGuard` means the underlying lock is acquired, so the underlying
123+
// data is valid. Hence we can create a shared reference to it.
114124
unsafe { &*self.lock.data.get() }
115125
}
116126
}
117127

118128
impl<L: RawLock, T> DerefMut for LockGuard<'_, L, T> {
119129
fn deref_mut(&mut self) -> &mut Self::Target {
120-
// SAFETY: Having a `LockGuard` means the underlying lock is held.
130+
// SAFETY: Having a `LockGuard` means the underlying lock is acquired, so the underlying
131+
// data is valid. Having a mutable refererence to it implies that we are the only one with
132+
// access to the underlying data. Hence we can create a mutable reference to it.
121133
unsafe { &mut *self.lock.data.get() }
122134
}
123135
}

src/lock/clhlock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ struct Node {
1212
#[derive(Debug, Clone)]
1313
pub struct Token(*const CachePadded<Node>);
1414

15+
// SAFETY: It doesn't matter if a thread used a token made by another thread.
1516
unsafe impl Send for Token {}
16-
unsafe impl Sync for Token {}
1717

1818
/// CLH lock.
1919
#[derive(Debug)]

src/lock/mcslock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ struct Node {
1414
#[derive(Debug, Clone)]
1515
pub struct Token(*mut CachePadded<Node>);
1616

17+
// SAFETY: It doesn't matter if a thread used a token made by another thread.
1718
unsafe impl Send for Token {}
18-
unsafe impl Sync for Token {}
1919

2020
/// An MCS lock.
2121
#[derive(Debug)]

src/lock/mcsparkinglock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ struct Node {
1616
#[derive(Debug, Clone)]
1717
pub struct Token(*mut CachePadded<Node>);
1818

19+
// SAFETY: It doesn't matter if a thread used a token made by another thread.
1920
unsafe impl Send for Token {}
20-
unsafe impl Sync for Token {}
2121

2222
/// An MCS parking lock.
2323
#[derive(Debug)]

0 commit comments

Comments
 (0)