Skip to content

Commit 7c8c2f0

Browse files
authored
Rollup merge of #123651 - tgross35:thread-local-updates, r=Mark-Simulacrum
Thread local updates for idiomatic examples Update thread local examples to make more idiomatic use of `Cell` for `Copy` types, `RefCell` for non-`Copy` types. Also shrink the size of `unsafe` blocks, add `SAFETY` comments, and fix `clippy::redundant_closure_for_method_calls`.
2 parents f3c6608 + 313085f commit 7c8c2f0

File tree

1 file changed

+32
-28
lines changed

1 file changed

+32
-28
lines changed

library/std/src/thread/local.rs

+32-28
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,25 @@ use crate::fmt;
5353
/// # Examples
5454
///
5555
/// ```
56-
/// use std::cell::RefCell;
56+
/// use std::cell::Cell;
5757
/// use std::thread;
5858
///
59-
/// thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
59+
/// thread_local!(static FOO: Cell<u32> = Cell::new(1));
6060
///
61-
/// FOO.with_borrow(|v| assert_eq!(*v, 1));
62-
/// FOO.with_borrow_mut(|v| *v = 2);
61+
/// assert_eq!(FOO.get(), 1);
62+
/// FOO.set(2);
6363
///
6464
/// // each thread starts out with the initial value of 1
6565
/// let t = thread::spawn(move|| {
66-
/// FOO.with_borrow(|v| assert_eq!(*v, 1));
67-
/// FOO.with_borrow_mut(|v| *v = 3);
66+
/// assert_eq!(FOO.get(), 1);
67+
/// FOO.set(3);
6868
/// });
6969
///
7070
/// // wait for the thread to complete and bail out on panic
7171
/// t.join().unwrap();
7272
///
7373
/// // we retain our original value of 2 despite the child thread
74-
/// FOO.with_borrow(|v| assert_eq!(*v, 2));
74+
/// assert_eq!(FOO.get(), 2);
7575
/// ```
7676
///
7777
/// # Platform-specific behavior
@@ -141,15 +141,16 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
141141
/// Publicity and attributes for each static are allowed. Example:
142142
///
143143
/// ```
144-
/// use std::cell::RefCell;
144+
/// use std::cell::{Cell, RefCell};
145+
///
145146
/// thread_local! {
146-
/// pub static FOO: RefCell<u32> = RefCell::new(1);
147+
/// pub static FOO: Cell<u32> = Cell::new(1);
147148
///
148-
/// static BAR: RefCell<f32> = RefCell::new(1.0);
149+
/// static BAR: RefCell<Vec<f32>> = RefCell::new(vec![1.0, 2.0]);
149150
/// }
150151
///
151-
/// FOO.with_borrow(|v| assert_eq!(*v, 1));
152-
/// BAR.with_borrow(|v| assert_eq!(*v, 1.0));
152+
/// assert_eq!(FOO.get(), 1);
153+
/// BAR.with_borrow(|v| assert_eq!(v[1], 2.0));
153154
/// ```
154155
///
155156
/// Note that only shared references (`&T`) to the inner data may be obtained, so a
@@ -164,12 +165,13 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
164165
/// track any additional state.
165166
///
166167
/// ```
167-
/// use std::cell::Cell;
168+
/// use std::cell::RefCell;
169+
///
168170
/// thread_local! {
169-
/// pub static FOO: Cell<u32> = const { Cell::new(1) };
171+
/// pub static FOO: RefCell<Vec<u32>> = const { RefCell::new(Vec::new()) };
170172
/// }
171173
///
172-
/// assert_eq!(FOO.get(), 1);
174+
/// FOO.with_borrow(|v| assert_eq!(v.len(), 0));
173175
/// ```
174176
///
175177
/// See [`LocalKey` documentation][`std::thread::LocalKey`] for more
@@ -279,10 +281,9 @@ impl<T: 'static> LocalKey<T> {
279281
where
280282
F: FnOnce(&T) -> R,
281283
{
282-
unsafe {
283-
let thread_local = (self.inner)(None).ok_or(AccessError)?;
284-
Ok(f(thread_local))
285-
}
284+
// SAFETY: `inner` is safe to call within the lifetime of the thread
285+
let thread_local = unsafe { (self.inner)(None).ok_or(AccessError)? };
286+
Ok(f(thread_local))
286287
}
287288

288289
/// Acquires a reference to the value in this TLS key, initializing it with
@@ -301,14 +302,17 @@ impl<T: 'static> LocalKey<T> {
301302
where
302303
F: FnOnce(Option<T>, &T) -> R,
303304
{
304-
unsafe {
305-
let mut init = Some(init);
306-
let reference = (self.inner)(Some(&mut init)).expect(
305+
let mut init = Some(init);
306+
307+
// SAFETY: `inner` is safe to call within the lifetime of the thread
308+
let reference = unsafe {
309+
(self.inner)(Some(&mut init)).expect(
307310
"cannot access a Thread Local Storage value \
308311
during or after destruction",
309-
);
310-
f(init, reference)
311-
}
312+
)
313+
};
314+
315+
f(init, reference)
312316
}
313317
}
314318

@@ -377,7 +381,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
377381
where
378382
T: Copy,
379383
{
380-
self.with(|cell| cell.get())
384+
self.with(Cell::get)
381385
}
382386

383387
/// Takes the contained value, leaving `Default::default()` in its place.
@@ -407,7 +411,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
407411
where
408412
T: Default,
409413
{
410-
self.with(|cell| cell.take())
414+
self.with(Cell::take)
411415
}
412416

413417
/// Replaces the contained value, returning the old value.
@@ -578,7 +582,7 @@ impl<T: 'static> LocalKey<RefCell<T>> {
578582
where
579583
T: Default,
580584
{
581-
self.with(|cell| cell.take())
585+
self.with(RefCell::take)
582586
}
583587

584588
/// Replaces the contained value, returning the old value.

0 commit comments

Comments
 (0)