1 //! Thread local storage 2 3 #[cfg(all(test, not(target_os = "emscripten")))] 4 mod tests; 5 6 #[cfg(test)] 7 mod dynamic_tests; 8 9 use crate::std::cell::{Cell, RefCell}; 10 use crate::std::error::Error; 11 use crate::std::fmt; 12 13 /// A thread local storage key which owns its contents. 14 /// 15 /// This key uses the fastest possible implementation available to it for the 16 /// target platform. It is instantiated with the [`thread_local!`] macro and the 17 /// primary method is the [`with`] method. 18 /// 19 /// The [`with`] method yields a reference to the contained value which cannot 20 /// outlive the current thread or escape the given closure. 21 /// 22 /// [`thread_local!`]: crate::std::thread_local 23 /// 24 /// # Initialization and Destruction 25 /// 26 /// Initialization is dynamically performed on the first call to [`with`] 27 /// within a thread, and values that implement [`Drop`] get destructed when a 28 /// thread exits. Some caveats apply, which are explained below. 29 /// 30 /// A `LocalKey`'s initializer cannot recursively depend on itself, and using 31 /// a `LocalKey` in this way will cause the initializer to infinitely recurse 32 /// on the first call to `with`. 33 /// 34 /// # Examples 35 /// 36 /// ``` 37 /// use std::cell::RefCell; 38 /// use std::thread; 39 /// 40 /// thread_local!(static FOO: RefCell<u32> = RefCell::new(1)); 41 /// 42 /// FOO.with(|f| { 43 /// assert_eq!(*f.borrow(), 1); 44 /// *f.borrow_mut() = 2; 45 /// }); 46 /// 47 /// // each thread starts out with the initial value of 1 48 /// let t = thread::spawn(move|| { 49 /// FOO.with(|f| { 50 /// assert_eq!(*f.borrow(), 1); 51 /// *f.borrow_mut() = 3; 52 /// }); 53 /// }); 54 /// 55 /// // wait for the thread to complete and bail out on panic 56 /// t.join().unwrap(); 57 /// 58 /// // we retain our original value of 2 despite the child thread 59 /// FOO.with(|f| { 60 /// assert_eq!(*f.borrow(), 2); 61 /// }); 62 /// ``` 63 /// 64 /// # Platform-specific behavior 65 /// 66 /// Note that a "best effort" is made to ensure that destructors for types 67 /// stored in thread local storage are run, but not all platforms can guarantee 68 /// that destructors will be run for all types in thread local storage. For 69 /// example, there are a number of known caveats where destructors are not run: 70 /// 71 /// 1. On Unix systems when pthread-based TLS is being used, destructors will 72 /// not be run for TLS values on the main thread when it exits. Note that the 73 /// application will exit immediately after the main thread exits as well. 74 /// 2. On all platforms it's possible for TLS to re-initialize other TLS slots 75 /// during destruction. Some platforms ensure that this cannot happen 76 /// infinitely by preventing re-initialization of any slot that has been 77 /// destroyed, but not all platforms have this guard. Those platforms that do 78 /// not guard typically have a synthetic limit after which point no more 79 /// destructors are run. 80 /// 3. When the process exits on Windows systems, TLS destructors may only be 81 /// run on the thread that causes the process to exit. This is because the 82 /// other threads may be forcibly terminated. 83 /// 84 /// ## Synchronization in thread-local destructors 85 /// 86 /// On Windows, synchronization operations (such as [`JoinHandle::join`]) in 87 /// thread local destructors are prone to deadlocks and so should be avoided. 88 /// This is because the [loader lock] is held while a destructor is run. The 89 /// lock is acquired whenever a thread starts or exits or when a DLL is loaded 90 /// or unloaded. Therefore these events are blocked for as long as a thread 91 /// local destructor is running. 92 /// 93 /// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices 94 /// [`JoinHandle::join`]: crate::std::thread::JoinHandle::join 95 /// [`with`]: LocalKey::with 96 #[cfg_attr(not(test), rustc_diagnostic_item = "LocalKey")] 97 pub struct LocalKey<T: 'static> { 98 // This outer `LocalKey<T>` type is what's going to be stored in statics, 99 // but actual data inside will sometimes be tagged with #[thread_local]. 100 // It's not valid for a true static to reference a #[thread_local] static, 101 // so we get around that by exposing an accessor through a layer of function 102 // indirection (this thunk). 103 // 104 // Note that the thunk is itself unsafe because the returned lifetime of the 105 // slot where data lives, `'static`, is not actually valid. The lifetime 106 // here is actually slightly shorter than the currently running thread! 107 // 108 // Although this is an extra layer of indirection, it should in theory be 109 // trivially devirtualizable by LLVM because the value of `inner` never 110 // changes and the constant should be readonly within a crate. This mainly 111 // only runs into problems when TLS statics are exported across crates. 112 inner: unsafe fn(Option<&mut Option<T>>) -> Option<&'static T>, 113 } 114 115 impl<T: 'static> fmt::Debug for LocalKey<T> { 116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 117 f.debug_struct("LocalKey").finish_non_exhaustive() 118 } 119 } 120 121 /// Declare a new thread local storage key of type [`std::thread::LocalKey`]. 122 /// 123 /// # Syntax 124 /// 125 /// The macro wraps any number of static declarations and makes them thread local. 126 /// Publicity and attributes for each static are allowed. Example: 127 /// 128 /// ``` 129 /// use std::cell::RefCell; 130 /// thread_local! { 131 /// pub static FOO: RefCell<u32> = RefCell::new(1); 132 /// 133 /// static BAR: RefCell<f32> = RefCell::new(1.0); 134 /// } 135 /// 136 /// FOO.with(|foo| assert_eq!(*foo.borrow(), 1)); 137 /// BAR.with(|bar| assert_eq!(*bar.borrow(), 1.0)); 138 /// ``` 139 /// 140 /// This macro supports a special `const {}` syntax that can be used 141 /// when the initialization expression can be evaluated as a constant. 142 /// This can enable a more efficient thread local implementation that 143 /// can avoid lazy initialization. For types that do not 144 /// [need to be dropped][crate::std::mem::needs_drop], this can enable an 145 /// even more efficient implementation that does not need to 146 /// track any additional state. 147 /// 148 /// ``` 149 /// use std::cell::Cell; 150 /// thread_local! { 151 /// pub static FOO: Cell<u32> = const { Cell::new(1) }; 152 /// } 153 /// 154 /// FOO.with(|foo| assert_eq!(foo.get(), 1)); 155 /// ``` 156 /// 157 /// See [`LocalKey` documentation][`std::thread::LocalKey`] for more 158 /// information. 159 /// 160 /// [`std::thread::LocalKey`]: crate::std::thread::LocalKey 161 #[macro_export] 162 #[cfg_attr(not(test), rustc_diagnostic_item = "thread_local_macro")] 163 #[allow_internal_unstable(thread_local_internals)] 164 macro_rules! thread_local { 165 // empty (base case for the recursion) 166 () => {}; 167 168 ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => ( 169 $crate::std::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); 170 $crate::std::thread_local!($($rest)*); 171 ); 172 173 ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }) => ( 174 $crate::std::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); 175 ); 176 177 // process multiple declarations 178 ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( 179 $crate::std::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, $init); 180 //$crate::std::thread_local!($($rest)*); 181 ); 182 183 // handle a single declaration 184 ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => ( 185 $crate::std::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, $init); 186 ); 187 } 188 189 /// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with). 190 #[non_exhaustive] 191 #[derive(Clone, Copy, Eq, PartialEq)] 192 pub struct AccessError; 193 194 impl fmt::Debug for AccessError { 195 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 196 f.debug_struct("AccessError").finish() 197 } 198 } 199 200 impl fmt::Display for AccessError { 201 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 202 fmt::Display::fmt("already destroyed", f) 203 } 204 } 205 206 impl Error for AccessError {} 207 208 impl<T: 'static> LocalKey<T> { 209 #[doc(hidden)] 210 pub const unsafe fn new( 211 inner: unsafe fn(Option<&mut Option<T>>) -> Option<&'static T>, 212 ) -> LocalKey<T> { 213 LocalKey { inner } 214 } 215 216 /// Acquires a reference to the value in this TLS key. 217 /// 218 /// This will lazily initialize the value if this thread has not referenced 219 /// this key yet. 220 /// 221 /// # Panics 222 /// 223 /// This function will `panic!()` if the key currently has its 224 /// destructor running, and it **may** panic if the destructor has 225 /// previously been run for this thread. 226 pub fn with<F, R>(&'static self, f: F) -> R 227 where 228 F: FnOnce(&T) -> R, 229 { 230 self.try_with(f).expect( 231 "cannot access a Thread Local Storage value \ 232 during or after destruction", 233 ) 234 } 235 236 /// Acquires a reference to the value in this TLS key. 237 /// 238 /// This will lazily initialize the value if this thread has not referenced 239 /// this key yet. If the key has been destroyed (which may happen if this is called 240 /// in a destructor), this function will return an [`AccessError`]. 241 /// 242 /// # Panics 243 /// 244 /// This function will still `panic!()` if the key is uninitialized and the 245 /// key's initializer panics. 246 #[inline] 247 pub fn try_with<F, R>(&'static self, f: F) -> Result<R, AccessError> 248 where 249 F: FnOnce(&T) -> R, 250 { 251 unsafe { 252 let thread_local = (self.inner)(None).ok_or(AccessError)?; 253 Ok(f(thread_local)) 254 } 255 } 256 257 /// Acquires a reference to the value in this TLS key, initializing it with 258 /// `init` if it wasn't already initialized on this thread. 259 /// 260 /// If `init` was used to initialize the thread local variable, `None` is 261 /// passed as the first argument to `f`. If it was already initialized, 262 /// `Some(init)` is passed to `f`. 263 /// 264 /// # Panics 265 /// 266 /// This function will panic if the key currently has its destructor 267 /// running, and it **may** panic if the destructor has previously been run 268 /// for this thread. 269 fn initialize_with<F, R>(&'static self, init: T, f: F) -> R 270 where 271 F: FnOnce(Option<T>, &T) -> R, 272 { 273 unsafe { 274 let mut init = Some(init); 275 let reference = (self.inner)(Some(&mut init)).expect( 276 "cannot access a Thread Local Storage value \ 277 during or after destruction", 278 ); 279 f(init, reference) 280 } 281 } 282 } 283 284 impl<T: 'static> LocalKey<Cell<T>> { 285 /// Sets or initializes the contained value. 286 /// 287 /// Unlike the other methods, this will *not* run the lazy initializer of 288 /// the thread local. Instead, it will be directly initialized with the 289 /// given value if it wasn't initialized yet. 290 /// 291 /// # Panics 292 /// 293 /// Panics if the key currently has its destructor running, 294 /// and it **may** panic if the destructor has previously been run for this thread. 295 /// 296 /// # Examples 297 /// 298 /// ``` 299 /// use std::cell::Cell; 300 /// 301 /// thread_local! { 302 /// static X: Cell<i32> = panic!("!"); 303 /// } 304 /// 305 /// // Calling X.get() here would result in a panic. 306 /// 307 /// X.set(123); // But X.set() is fine, as it skips the initializer above. 308 /// 309 /// assert_eq!(X.get(), 123); 310 /// ``` 311 pub fn set(&'static self, value: T) { 312 self.initialize_with(Cell::new(value), |value, cell| { 313 if let Some(value) = value { 314 // The cell was already initialized, so `value` wasn't used to 315 // initialize it. So we overwrite the current value with the 316 // new one instead. 317 cell.set(value.into_inner()); 318 } 319 }); 320 } 321 322 /// Returns a copy of the contained value. 323 /// 324 /// This will lazily initialize the value if this thread has not referenced 325 /// this key yet. 326 /// 327 /// # Panics 328 /// 329 /// Panics if the key currently has its destructor running, 330 /// and it **may** panic if the destructor has previously been run for this thread. 331 /// 332 /// # Examples 333 /// 334 /// ``` 335 /// use std::cell::Cell; 336 /// 337 /// thread_local! { 338 /// static X: Cell<i32> = Cell::new(1); 339 /// } 340 /// 341 /// assert_eq!(X.get(), 1); 342 /// ``` 343 pub fn get(&'static self) -> T 344 where 345 T: Copy, 346 { 347 self.with(|cell| cell.get()) 348 } 349 350 /// Takes the contained value, leaving `Default::default()` in its place. 351 /// 352 /// This will lazily initialize the value if this thread has not referenced 353 /// this key yet. 354 /// 355 /// # Panics 356 /// 357 /// Panics if the key currently has its destructor running, 358 /// and it **may** panic if the destructor has previously been run for this thread. 359 /// 360 /// # Examples 361 /// 362 /// ``` 363 /// use std::cell::Cell; 364 /// 365 /// thread_local! { 366 /// static X: Cell<Option<i32>> = Cell::new(Some(1)); 367 /// } 368 /// 369 /// assert_eq!(X.take(), Some(1)); 370 /// assert_eq!(X.take(), None); 371 /// ``` 372 pub fn take(&'static self) -> T 373 where 374 T: Default, 375 { 376 self.with(|cell| cell.take()) 377 } 378 379 /// Replaces the contained value, returning the old value. 380 /// 381 /// This will lazily initialize the value if this thread has not referenced 382 /// this key yet. 383 /// 384 /// # Panics 385 /// 386 /// Panics if the key currently has its destructor running, 387 /// and it **may** panic if the destructor has previously been run for this thread. 388 /// 389 /// # Examples 390 /// 391 /// ``` 392 /// use std::cell::Cell; 393 /// 394 /// thread_local! { 395 /// static X: Cell<i32> = Cell::new(1); 396 /// } 397 /// 398 /// assert_eq!(X.replace(2), 1); 399 /// assert_eq!(X.replace(3), 2); 400 /// ``` 401 pub fn replace(&'static self, value: T) -> T { 402 self.with(|cell| cell.replace(value)) 403 } 404 } 405 406 impl<T: 'static> LocalKey<RefCell<T>> { 407 /// Acquires a reference to the contained value. 408 /// 409 /// This will lazily initialize the value if this thread has not referenced 410 /// this key yet. 411 /// 412 /// # Panics 413 /// 414 /// Panics if the value is currently mutably borrowed. 415 /// 416 /// Panics if the key currently has its destructor running, 417 /// and it **may** panic if the destructor has previously been run for this thread. 418 /// 419 /// # Example 420 /// 421 /// ``` 422 /// use std::cell::RefCell; 423 /// 424 /// thread_local! { 425 /// static X: RefCell<Vec<i32>> = RefCell::new(Vec::new()); 426 /// } 427 /// 428 /// X.with_borrow(|v| assert!(v.is_empty())); 429 /// ``` 430 pub fn with_borrow<F, R>(&'static self, f: F) -> R 431 where 432 F: FnOnce(&T) -> R, 433 { 434 self.with(|cell| f(&cell.borrow())) 435 } 436 437 /// Acquires a mutable reference to the contained value. 438 /// 439 /// This will lazily initialize the value if this thread has not referenced 440 /// this key yet. 441 /// 442 /// # Panics 443 /// 444 /// Panics if the value is currently borrowed. 445 /// 446 /// Panics if the key currently has its destructor running, 447 /// and it **may** panic if the destructor has previously been run for this thread. 448 /// 449 /// # Example 450 /// 451 /// ``` 452 /// use std::cell::RefCell; 453 /// 454 /// thread_local! { 455 /// static X: RefCell<Vec<i32>> = RefCell::new(Vec::new()); 456 /// } 457 /// 458 /// X.with_borrow_mut(|v| v.push(1)); 459 /// 460 /// X.with_borrow(|v| assert_eq!(*v, vec![1])); 461 /// ``` 462 pub fn with_borrow_mut<F, R>(&'static self, f: F) -> R 463 where 464 F: FnOnce(&mut T) -> R, 465 { 466 self.with(|cell| f(&mut cell.borrow_mut())) 467 } 468 469 /// Sets or initializes the contained value. 470 /// 471 /// Unlike the other methods, this will *not* run the lazy initializer of 472 /// the thread local. Instead, it will be directly initialized with the 473 /// given value if it wasn't initialized yet. 474 /// 475 /// # Panics 476 /// 477 /// Panics if the value is currently borrowed. 478 /// 479 /// Panics if the key currently has its destructor running, 480 /// and it **may** panic if the destructor has previously been run for this thread. 481 /// 482 /// # Examples 483 /// 484 /// ``` 485 /// use std::cell::RefCell; 486 /// 487 /// thread_local! { 488 /// static X: RefCell<Vec<i32>> = panic!("!"); 489 /// } 490 /// 491 /// // Calling X.with() here would result in a panic. 492 /// 493 /// X.set(vec![1, 2, 3]); // But X.set() is fine, as it skips the initializer above. 494 /// 495 /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3])); 496 /// ``` 497 pub fn set(&'static self, value: T) { 498 self.initialize_with(RefCell::new(value), |value, cell| { 499 if let Some(value) = value { 500 // The cell was already initialized, so `value` wasn't used to 501 // initialize it. So we overwrite the current value with the 502 // new one instead. 503 *cell.borrow_mut() = value.into_inner(); 504 } 505 }); 506 } 507 508 /// Takes the contained value, leaving `Default::default()` in its place. 509 /// 510 /// This will lazily initialize the value if this thread has not referenced 511 /// this key yet. 512 /// 513 /// # Panics 514 /// 515 /// Panics if the value is currently borrowed. 516 /// 517 /// Panics if the key currently has its destructor running, 518 /// and it **may** panic if the destructor has previously been run for this thread. 519 /// 520 /// # Examples 521 /// 522 /// ``` 523 /// use std::cell::RefCell; 524 /// 525 /// thread_local! { 526 /// static X: RefCell<Vec<i32>> = RefCell::new(Vec::new()); 527 /// } 528 /// 529 /// X.with_borrow_mut(|v| v.push(1)); 530 /// 531 /// let a = X.take(); 532 /// 533 /// assert_eq!(a, vec![1]); 534 /// 535 /// X.with_borrow(|v| assert!(v.is_empty())); 536 /// ``` 537 pub fn take(&'static self) -> T 538 where 539 T: Default, 540 { 541 self.with(|cell| cell.take()) 542 } 543 544 /// Replaces the contained value, returning the old value. 545 /// 546 /// # Panics 547 /// 548 /// Panics if the value is currently borrowed. 549 /// 550 /// Panics if the key currently has its destructor running, 551 /// and it **may** panic if the destructor has previously been run for this thread. 552 /// 553 /// # Examples 554 /// 555 /// ``` 556 /// use std::cell::RefCell; 557 /// 558 /// thread_local! { 559 /// static X: RefCell<Vec<i32>> = RefCell::new(Vec::new()); 560 /// } 561 /// 562 /// let prev = X.replace(vec![1, 2, 3]); 563 /// assert!(prev.is_empty()); 564 /// 565 /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3])); 566 /// ``` 567 pub fn replace(&'static self, value: T) -> T { 568 self.with(|cell| cell.replace(value)) 569 } 570 } 571