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