@@ -16,7 +16,8 @@ use crate::fmt;
1616///
1717/// This key uses the fastest possible implementation available to it for the
1818/// target platform. It is instantiated with the [`thread_local!`] macro and the
19- /// primary method is the [`with`] method.
19+ /// primary method is the [`with`] method, though there are helpers to make
20+ /// working with [`Cell`] types easier.
2021///
2122/// The [`with`] method yields a reference to the contained value which cannot
2223/// outlive the current thread or escape the given closure.
@@ -25,14 +26,30 @@ use crate::fmt;
2526///
2627/// # Initialization and Destruction
2728///
28- /// Initialization is dynamically performed on the first call to [`with`]
29- /// within a thread, and values that implement [`Drop`] get destructed when a
30- /// thread exits. Some caveats apply, which are explained below.
29+ /// Initialization is dynamically performed on the first call to a setter (e.g.
30+ /// [`with`]) within a thread, and values that implement [`Drop`] get
31+ /// destructed when a thread exits. Some caveats apply, which are explained below.
3132///
3233/// A `LocalKey`'s initializer cannot recursively depend on itself. Using a
3334/// `LocalKey` in this way may cause panics, aborts or infinite recursion on
3435/// the first call to `with`.
3536///
37+ /// # Single-thread Synchronization
38+ ///
39+ /// Though there is no potential race with other threads, it is still possible to
40+ /// obtain multiple references to the thread-local data in different places on
41+ /// the call stack. For this reason, only shared (`&T`) references may be obtained.
42+ ///
43+ /// To allow obtaining an exclusive mutable reference (`&mut T`), typically a
44+ /// [`Cell`] or [`RefCell`] is used (see the [`std::cell`] for more information
45+ /// on how exactly this works). To make this easier there are specialized
46+ /// implementations for [`LocalKey<Cell<T>>`] and [`LocalKey<RefCell<T>>`].
47+ ///
48+ /// [`std::cell`]: `crate::cell`
49+ /// [`LocalKey<Cell<T>>`]: struct.LocalKey.html#impl-LocalKey<Cell<T>>
50+ /// [`LocalKey<RefCell<T>>`]: struct.LocalKey.html#impl-LocalKey<RefCell<T>>
51+ ///
52+ ///
3653/// # Examples
3754///
3855/// ```
@@ -41,26 +58,20 @@ use crate::fmt;
4158///
4259/// thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
4360///
44- /// FOO.with(|f| {
45- /// assert_eq!(*f.borrow(), 1);
46- /// *f.borrow_mut() = 2;
47- /// });
61+ /// FOO.with_borrow(|v| assert_eq!(*v, 1));
62+ /// FOO.with_borrow_mut(|v| *v = 2);
4863///
4964/// // each thread starts out with the initial value of 1
5065/// let t = thread::spawn(move|| {
51- /// FOO.with(|f| {
52- /// assert_eq!(*f.borrow(), 1);
53- /// *f.borrow_mut() = 3;
54- /// });
66+ /// FOO.with_borrow(|v| assert_eq!(*v, 1));
67+ /// FOO.with_borrow_mut(|v| *v = 3);
5568/// });
5669///
5770/// // wait for the thread to complete and bail out on panic
5871/// t.join().unwrap();
5972///
6073/// // we retain our original value of 2 despite the child thread
61- /// FOO.with(|f| {
62- /// assert_eq!(*f.borrow(), 2);
63- /// });
74+ /// FOO.with_borrow(|v| assert_eq!(*v, 2));
6475/// ```
6576///
6677/// # Platform-specific behavior
@@ -137,10 +148,13 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
137148/// static BAR: RefCell<f32> = RefCell::new(1.0);
138149/// }
139150///
140- /// FOO.with(|foo | assert_eq!(*foo.borrow() , 1));
141- /// BAR.with(|bar | assert_eq!(*bar.borrow() , 1.0));
151+ /// FOO.with_borrow(|v | assert_eq!(*v , 1));
152+ /// BAR.with_borrow(|v | assert_eq!(*v , 1.0));
142153/// ```
143154///
155+ /// Note that only shared references (`&T`) to the inner data may be obtained, so a
156+ /// type such as [`Cell`] or [`RefCell`] is typically used to allow mutating access.
157+ ///
144158/// This macro supports a special `const {}` syntax that can be used
145159/// when the initialization expression can be evaluated as a constant.
146160/// This can enable a more efficient thread local implementation that
@@ -155,7 +169,7 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
155169/// pub static FOO: Cell<u32> = const { Cell::new(1) };
156170/// }
157171///
158- /// FOO.with(|foo| assert_eq!(foo .get(), 1) );
172+ /// assert_eq!(FOO .get(), 1);
159173/// ```
160174///
161175/// See [`LocalKey` documentation][`std::thread::LocalKey`] for more
0 commit comments