Skip to content

Commit e367ff4

Browse files
chore: improve thread local macro docs (#21)
Change thread_local_node! examples so they correctly demonstrate their usage as declaration blocks as oppose to function calls.
1 parent 92dfb48 commit e367ff4

10 files changed

Lines changed: 56 additions & 53 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ use std::thread;
112112
use mcslock::raw::spins::Mutex;
113113

114114
// Requires `thread_local` feature.
115-
mcslock::thread_local_node!(static NODE);
115+
mcslock::thread_local_node! { static NODE }
116116

117117
fn main() {
118118
let mutex = Arc::new(Mutex::new(0));

examples/thread_local.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use mcslock::raw::spins::Mutex;
66

77
// Requires that the `thread_local` feature is enabled.
88
mcslock::thread_local_node! {
9-
// * Allows multiple static definitions, must be separated with semicolons.
9+
// * Allows multiple static declarations, must be separated with semicolons.
1010
// * Visibility is optional (private by default).
1111
// * Requires `static` keyword and a UPPER_SNAKE_CASE name.
1212
pub static NODE;

src/barging/mutex.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -497,9 +497,9 @@ impl<T: ?Sized, Rs: Relax, Rq: Relax> LockThen for MutexStackNode<T, Rs, Rq> {
497497
#[cfg(test)]
498498
impl<T: ?Sized, Rs: Relax, Rq: Relax> TryLockThen for MutexStackNode<T, Rs, Rq> {}
499499

500-
#[cfg(all(feature = "lock_api", not(loom)))]
501500
// SAFETY: This `Mutex` implementation guarantees linearization of access and
502501
// modification to the protected data in a concurrent, multithreaded context.
502+
#[cfg(all(feature = "lock_api", not(loom)))]
503503
unsafe impl<Rs: Relax, Rq: Relax> lock_api::RawMutex for Mutex<(), Rs, Rq> {
504504
type GuardMarker = lock_api::GuardSend;
505505

@@ -595,10 +595,10 @@ impl<T: ?Sized, Rs, Rq> core::ops::DerefMut for MutexGuard<'_, T, Rs, Rq> {
595595
}
596596
}
597597

598-
#[cfg(all(loom, test))]
599-
#[cfg(not(tarpaulin_include))]
600598
// SAFETY: A guard instance hold the lock locked, with exclusive access to the
601599
// underlying data.
600+
#[cfg(all(loom, test))]
601+
#[cfg(not(tarpaulin_include))]
602602
unsafe impl<T: ?Sized, Rs, Rq> Guard for MutexGuard<'_, T, Rs, Rq> {
603603
type Target = T;
604604

src/barging/thread_local.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ impl<T: ?Sized, Rs: Relax, Rq: Relax> Mutex<T, Rs, Rq> {
1212
/// in the thread local storage of the locking threads. That is, the number
1313
/// of queue nodes is proportional at 1:1 to the number of locking threads.
1414
pub(super) fn lock_with_local_queue_node(&self) -> MutexGuard<'_, T, Rs, Rq> {
15-
crate::thread_local_node!(static NODE);
15+
crate::thread_local_node! { static NODE }
1616
// SAFETY: The thread local node: `NODE` is not borrowed to any other
1717
// locking operation for all duration of the `inner` borrow of it.
1818
unsafe { self.inner.lock_with_local_unchecked(&NODE.inner) }.into()

src/inner/barging/mod.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub struct Mutex<T: ?Sized, L, Ws, Wq> {
2020
// SAFETY: A `Mutex` is safe to be sent across thread boundaries as long as
2121
// the inlined protected data `T` is also safe to be sent to other threads.
2222
unsafe impl<T: ?Sized + Send, L: Send, Ws, Wq> Send for Mutex<T, L, Ws, Wq> {}
23+
2324
// SAFETY: A `Mutex` is safe to be shared across thread boundaries since it
2425
// guarantees linearization of access and modification to the protected data,
2526
// but only if the protected data `T` is safe to be sent to other threads.
@@ -53,7 +54,10 @@ impl<T: ?Sized, L: Lock, Ws: Wait, Wq: Wait> Mutex<T, L, Ws, Wq> {
5354
/// each call, storing it at the current stack frame.
5455
#[cfg(any(test, not(feature = "thread_local")))]
5556
pub fn lock_with_stack_queue_node(&self) -> MutexGuard<'_, T, L, Ws, Wq> {
56-
self.lock(|f| self.queue.lock_with_then(&mut raw::MutexNode::new(), |()| f(self)))
57+
self.lock(|f| {
58+
let mut node = raw::MutexNode::new();
59+
self.queue.lock_with_then(&mut node, |()| f(self));
60+
})
5761
}
5862

5963
/// Generic lock implementation over call site provided queueing logic.
@@ -139,6 +143,7 @@ pub struct MutexGuard<'a, T: ?Sized, L: Lock, Ws, Wq> {
139143
// Note that `std::sync::MutexGuard` is `!Send` because it must be compatible
140144
// with `Pthreads` implementation on Linux, but we do not have this constraint.
141145
unsafe impl<T: ?Sized + Send, L: Lock + Send, Ws, Wq> Send for MutexGuard<'_, T, L, Ws, Wq> {}
146+
142147
// SAFETY: A `MutexGuard` is safe to be shared across thread boundaries since
143148
// it owns exclusive access over the protected data during its lifetime, and so
144149
// the can safely share references to the data, but only if the protected data
@@ -199,10 +204,10 @@ impl<T: ?Sized, L: Lock, Ws, Wq> Drop for MutexGuard<'_, T, L, Ws, Wq> {
199204
}
200205
}
201206

202-
#[cfg(all(loom, test))]
203-
#[cfg(not(tarpaulin_include))]
204207
// SAFETY: A guard instance hold the lock locked, with exclusive access to the
205208
// underlying data.
209+
#[cfg(all(loom, test))]
210+
#[cfg(not(tarpaulin_include))]
206211
unsafe impl<T: ?Sized, L: Lock, Ws, Wq> crate::loom::Guard for MutexGuard<'_, T, L, Ws, Wq> {
207212
type Target = T;
208213

src/inner/raw/mod.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub struct MutexNodeInit<L> {
2727

2828
impl<L> MutexNodeInit<L> {
2929
/// Returns a raw mutable pointer of this node.
30-
#[allow(clippy::ref_as_ptr)] // 1.91.0
30+
#[allow(clippy::ref_as_ptr)] // `from_ref`: 1.76.0
3131
const fn as_ptr(&self) -> *mut Self {
3232
(self as *const Self).cast_mut()
3333
}
@@ -88,7 +88,7 @@ impl<L> MutexNode<L> {
8888
impl<L: Lock> MutexNode<L> {
8989
/// Initializes this node's inner state, returning a shared reference
9090
/// pointing to it.
91-
#[allow(clippy::missing_const_for_fn)] // 1.91.0
91+
#[allow(clippy::missing_const_for_fn)] // &mut self in const: 1.83.0
9292
fn initialize(&mut self) -> &MutexNodeInit<L> {
9393
self.inner.write(MutexNodeInit::locked())
9494
}
@@ -113,6 +113,7 @@ pub struct Mutex<T: ?Sized, L, W> {
113113
// SAFETY: A `Mutex` is safe to be sent across thread boundaries as long as
114114
// the inlined protected data `T` is also safe to be sent to other threads.
115115
unsafe impl<T: ?Sized + Send, L, W> Send for Mutex<T, L, W> {}
116+
116117
// SAFETY: A `Mutex` is safe to be shared across thread boundaries since it
117118
// guarantees linearization of access and modification to the protected data,
118119
// but only if the protected data `T` is safe to be sent to other threads.
@@ -267,11 +268,6 @@ struct MutexGuard<'a, T: ?Sized, L: Lock, W: Wait> {
267268
head: &'a MutexNodeInit<L>,
268269
}
269270

270-
// SAFETY: A `MutexGuard` is safe to be sent across thread boundaries as long as
271-
// the referenced protected data `T` is also safe to be sent to other threads.
272-
// Note that `std::sync::MutexGuard` is `!Send` because it must be compatible
273-
// with `Pthreads` implementation on Linux, but we do not have this constraint.
274-
unsafe impl<T: ?Sized + Send, L: Lock + Send, W: Wait> Send for MutexGuard<'_, T, L, W> {}
275271
// SAFETY: A `MutexGuard` is safe to be shared across thread boundaries since
276272
// it owns exclusive access over the protected data during its lifetime, and so
277273
// the can safely share references to the data, but only if the protected data

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
//! use mcslock::raw::spins::Mutex;
8181
//!
8282
//! // Requires `thread_local` feature.
83-
//! mcslock::thread_local_node!(static NODE);
83+
//! mcslock::thread_local_node! { static NODE }
8484
//!
8585
//! let mutex = Arc::new(Mutex::new(0));
8686
//! let c_mutex = Arc::clone(&mutex);

src/loom.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ pub mod models {
9292
use loom::sync::Arc;
9393
use loom::{model, thread};
9494

95-
use crate::test::{lock_get, lock_inc, try_lock_inc, Int};
96-
use crate::test::{LockThen, TryLockThen};
95+
use crate::test::{lock_get, lock_inc, try_lock_inc};
96+
use crate::test::{Int, LockThen, TryLockThen};
9797

9898
/// Get a copy of the shared integer, converting it to usize.
9999
///

src/raw/thread_local.rs

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ type Key = &'static LocalMutexNode;
2323
/// See: [`try_lock_with_local_then`], [`lock_with_local_then`],
2424
/// [`try_lock_with_local_then_unchecked`] or [`lock_with_local_then_unchecked`].
2525
///
26-
/// The thread local node definition generated by this macro avoids lazy
26+
/// The thread local node declaration generated by this macro avoids lazy
2727
/// initialization and does not need to be dropped, which enables a more
2828
/// efficient underlying implementation. See [`std::thread_local!`] macro.
2929
///
3030
/// # Sintax
3131
///
32-
/// * Allows multiple static definitions, must be separated with semicolons.
32+
/// * Allows multiple static declarations, must be separated with semicolons.
3333
/// * Visibility is optional (private by default).
3434
/// * Requires `static` keyword and a **UPPER_SNAKE_CASE** name.
3535
///
@@ -38,15 +38,13 @@ type Key = &'static LocalMutexNode;
3838
/// ```
3939
/// use mcslock::raw::spins::Mutex;
4040
///
41-
/// // Multiple difenitions.
41+
/// // Multiple declarations allowed.
4242
/// mcslock::thread_local_node! {
4343
/// pub static NODE;
44-
/// static OTHER_NODE1;
44+
/// static OTHER_NODE;
45+
/// // ...
4546
/// }
4647
///
47-
/// // Single definition.
48-
/// mcslock::thread_local_node!(pub static OTHER_NODE2);
49-
///
5048
/// let mutex = Mutex::new(0);
5149
/// // Keys are provided to APIs by reference.
5250
/// mutex.lock_with_local_then(&NODE, |data| *data = 10);
@@ -63,14 +61,14 @@ type Key = &'static LocalMutexNode;
6361
macro_rules! thread_local_node {
6462
// Empty (base for recursion).
6563
() => {};
66-
// Process multiply definitions (recursive).
64+
// Process multiple declarations (recursive).
6765
($vis:vis static $node:ident; $($rest:tt)*) => {
68-
$crate::__thread_local_node_inner!($vis $node, raw);
69-
$crate::thread_local_node!($($rest)*);
66+
$crate::__thread_local_node_inner! { $vis $node, raw }
67+
$crate::thread_local_node! { $($rest)* }
7068
};
7169
// Process single declaration.
7270
($vis:vis static $node:ident) => {
73-
$crate::__thread_local_node_inner!($vis $node, raw);
71+
$crate::__thread_local_node_inner! { $vis $node, raw }
7472
};
7573
}
7674

@@ -158,7 +156,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
158156
///
159157
/// use mcslock::raw::spins::Mutex;
160158
///
161-
/// mcslock::thread_local_node!(static NODE);
159+
/// mcslock::thread_local_node! { static NODE }
162160
///
163161
/// let mutex = Arc::new(Mutex::new(0));
164162
/// let c_mutex = Arc::clone(&mutex);
@@ -182,7 +180,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
182180
/// ```compile_fail,E0515
183181
/// use mcslock::raw::spins::Mutex;
184182
///
185-
/// mcslock::thread_local_node!(static NODE);
183+
/// mcslock::thread_local_node! { static NODE }
186184
///
187185
/// let mutex = Mutex::new(1);
188186
/// let borrow = mutex.try_lock_with_local_then(&NODE, |data| &*data.unwrap());
@@ -194,7 +192,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
194192
#[doc = concat!("```should_panic(expected = ", already_borrowed_error!(), ")")]
195193
/// use mcslock::raw::spins::Mutex;
196194
///
197-
/// mcslock::thread_local_node!(static NODE);
195+
/// mcslock::thread_local_node! { static NODE }
198196
///
199197
/// let mutex = Mutex::new(0);
200198
///
@@ -205,7 +203,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
205203
/// let mutex = Mutex::new(());
206204
/// mutex.try_lock_with_local_then(&NODE, |_data| ());
207205
/// });
208-
/// ```
206+
#[doc = "```"]
209207
#[inline]
210208
#[track_caller]
211209
pub fn try_lock_with_local_then<F, Ret>(&self, node: Key, f: F) -> Ret
@@ -250,7 +248,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
250248
///
251249
/// use mcslock::raw::spins::Mutex;
252250
///
253-
/// mcslock::thread_local_node!(static NODE);
251+
/// mcslock::thread_local_node! { static NODE }
254252
///
255253
/// let mutex = Arc::new(Mutex::new(0));
256254
/// let c_mutex = Arc::clone(&mutex);
@@ -274,11 +272,11 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
274272
/// ```compile_fail,E0515
275273
/// use mcslock::raw::spins::Mutex;
276274
///
277-
/// mcslock::thread_local_node!(static NODE);
275+
/// mcslock::thread_local_node! { static NODE }
278276
///
279277
/// let mutex = Mutex::new(1);
280278
/// let data = unsafe {
281-
/// mutex.try_lock_with_local_then_unchecked(&NODE, |g| &*g.unwrap())
279+
/// mutex.try_lock_with_local_then_unchecked(&NODE, |d| &*d.unwrap())
282280
/// };
283281
/// ```
284282
///
@@ -288,7 +286,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
288286
/// ```no_run
289287
/// use mcslock::raw::spins::Mutex;
290288
///
291-
/// mcslock::thread_local_node!(static NODE);
289+
/// mcslock::thread_local_node! { static NODE }
292290
///
293291
/// let mutex = Mutex::new(0);
294292
///
@@ -339,7 +337,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
339337
///
340338
/// use mcslock::raw::spins::Mutex;
341339
///
342-
/// mcslock::thread_local_node!(static NODE);
340+
/// mcslock::thread_local_node! { static NODE }
343341
///
344342
/// let mutex = Arc::new(Mutex::new(0));
345343
/// let c_mutex = Arc::clone(&mutex);
@@ -357,7 +355,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
357355
/// ```compile_fail,E0515
358356
/// use mcslock::raw::spins::Mutex;
359357
///
360-
/// mcslock::thread_local_node!(static NODE);
358+
/// mcslock::thread_local_node! { static NODE }
361359
///
362360
/// let mutex = Mutex::new(1);
363361
/// let borrow = mutex.lock_with_local_then(&NODE, |data| &*data);
@@ -369,7 +367,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
369367
#[doc = concat!("```should_panic(expected = ", already_borrowed_error!(), ")")]
370368
/// use mcslock::raw::spins::Mutex;
371369
///
372-
/// mcslock::thread_local_node!(static NODE);
370+
/// mcslock::thread_local_node! { static NODE }
373371
///
374372
/// let mutex = Mutex::new(0);
375373
///
@@ -380,7 +378,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
380378
/// let mutex = Mutex::new(());
381379
/// mutex.lock_with_local_then(&NODE, |_data| ());
382380
/// });
383-
/// ```
381+
#[doc = "```"]
384382
#[inline]
385383
#[track_caller]
386384
pub fn lock_with_local_then<F, Ret>(&self, node: Key, f: F) -> Ret
@@ -424,7 +422,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
424422
///
425423
/// use mcslock::raw::spins::Mutex;
426424
///
427-
/// mcslock::thread_local_node!(static NODE);
425+
/// mcslock::thread_local_node! { static NODE }
428426
///
429427
/// let mutex = Arc::new(Mutex::new(0));
430428
/// let c_mutex = Arc::clone(&mutex);
@@ -442,7 +440,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
442440
/// ```compile_fail,E0515
443441
/// use mcslock::raw::spins::Mutex;
444442
///
445-
/// mcslock::thread_local_node!(static NODE);
443+
/// mcslock::thread_local_node! { static NODE }
446444
///
447445
/// let mutex = Mutex::new(1);
448446
/// let data = unsafe {
@@ -456,7 +454,7 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
456454
/// ```no_run
457455
/// use mcslock::raw::spins::Mutex;
458456
///
459-
/// mcslock::thread_local_node!(static NODE);
457+
/// mcslock::thread_local_node!{ static NODE }
460458
///
461459
/// let mutex = Mutex::new(0);
462460
///
@@ -482,7 +480,8 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
482480
///
483481
/// ```compile_fail
484482
/// use mcslock::raw::spins::Mutex;
485-
/// mcslock::thread_local_node!(static NODE);
483+
///
484+
/// mcslock::thread_local_node! { static NODE }
486485
///
487486
/// let mutex = Mutex::new(1);
488487
/// let borrow = mutex.lock_with_local_then(&NODE, |data| data);
@@ -491,7 +490,8 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
491490
/// ```compile_fail,E0521
492491
/// use std::thread;
493492
/// use mcslock::raw::spins::Mutex;
494-
/// mcslock::thread_local_node!(static NODE);
493+
///
494+
/// mcslock::thread_local_node! { static NODE }
495495
///
496496
/// let mutex = Mutex::new(1);
497497
/// mutex.lock_with_local_then(&NODE, |data| {
@@ -506,9 +506,11 @@ impl<T: ?Sized, R: Relax> Mutex<T, R> {
506506
}
507507

508508
// A thread local node definition used for testing.
509+
//
510+
// NOTE: Be mindfull of usage since it is a module global name.
509511
#[cfg(test)]
510512
#[cfg(not(tarpaulin_include))]
511-
thread_local_node!(static TEST_NODE);
513+
thread_local_node! { static TEST_NODE }
512514

513515
/// A Mutex wrapper type that calls `lock_with_local_then` and
514516
/// `try_lock_with_local_then` when implementing testing traits.
@@ -598,8 +600,8 @@ impl<T: ?Sized, R: Relax> LockWithThen for MutexUnchecked<T, R> {
598600
where
599601
F: FnOnce(&mut Self::Target) -> Ret,
600602
{
601-
// SAFETY: caller must guarantee that this thread local node is not
602-
// already mutably borrowed for some other lock acquisition.
603+
// SAFETY: The thread local node is not borrowed to any other
604+
// locking operation for all duration of this call.
603605
unsafe { self.0.lock_with_local_then_unchecked(&TEST_NODE, f) }
604606
}
605607
}
@@ -610,8 +612,8 @@ impl<T: ?Sized, R: Relax> TryLockWithThen for MutexUnchecked<T, R> {
610612
where
611613
F: FnOnce(Option<&mut Self::Target>) -> Ret,
612614
{
613-
// SAFETY: caller must guarantee that this thread local node is not
614-
// already mutably borrowed for some other lock acquisition.
615+
// SAFETY: The thread local node is not borrowed to any other
616+
// locking operation for all duration of this call.
615617
unsafe { self.0.try_lock_with_local_then_unchecked(&TEST_NODE, f) }
616618
}
617619

src/thread_local.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ macro_rules! __thread_local_node_inner {
2121

2222
/// Non-recursive, Loom based inner definition of `thread_local_node!`.
2323
///
24-
/// This node definition uses Loom primitives and it can't be evaluated at
24+
/// This node declaration uses Loom primitives and it can't be evaluated at
2525
/// compile-time since Loom does not support that feature. Loom's `thread_local!`
2626
/// macro defines a `static` value as oppose to std's `const` value.
2727
#[cfg(all(loom, test))]

0 commit comments

Comments
 (0)