about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAaron Turon <aturon@mozilla.com>2015-03-20 00:46:13 -0700
committerAaron Turon <aturon@mozilla.com>2015-03-23 11:28:54 -0700
commit6bd3ab0d8140053475a901ad4e2e80e98955bcb0 (patch)
treeb8d6a880328d2fd590634319a047cabe66630632
parentb0aad7dd4fad8d7e2e2f877a511a637258949597 (diff)
downloadrust-6bd3ab0d8140053475a901ad4e2e80e98955bcb0.tar.gz
rust-6bd3ab0d8140053475a901ad4e2e80e98955bcb0.zip
Implement RFC 909: move thread_local into thread
This commit implements [RFC
909](https://github.com/rust-lang/rfcs/pull/909):

The `std::thread_local` module is now deprecated, and its contents are
available directly in `std::thread` as `LocalKey`, `LocalKeyState`, and
`ScopedKey`.

The macros remain exactly as they were, which means little if any code
should break. Nevertheless, this is technically a:

[breaking-change]

Closes #23547
-rw-r--r--src/libstd/lib.rs23
-rw-r--r--src/libstd/sys/common/thread_info.rs4
-rw-r--r--src/libstd/thread/local.rs (renamed from src/libstd/thread_local/mod.rs)99
-rw-r--r--src/libstd/thread/mod.rs (renamed from src/libstd/thread.rs)66
-rw-r--r--src/libstd/thread/scoped.rs (renamed from src/libstd/thread_local/scoped.rs)26
5 files changed, 127 insertions, 91 deletions
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index b055796ba54..970074f7930 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -249,30 +249,23 @@ pub mod num;
 /* Runtime and platform support */
 
 #[macro_use]
-pub mod thread_local;
+pub mod thread;
 
+pub mod collections;
 pub mod dynamic_lib;
+pub mod env;
 pub mod ffi;
-pub mod old_io;
-pub mod io;
 pub mod fs;
+pub mod io;
 pub mod net;
+pub mod old_io;
+pub mod old_path;
 pub mod os;
-pub mod env;
 pub mod path;
-pub mod old_path;
 pub mod process;
 pub mod rand;
-pub mod time;
-
-/* Common data structures */
-
-pub mod collections;
-
-/* Threads and communication */
-
-pub mod thread;
 pub mod sync;
+pub mod time;
 
 #[macro_use]
 #[path = "sys/common/mod.rs"] mod sys_common;
@@ -305,7 +298,7 @@ mod std {
     pub use rt; // used for panic!()
     pub use vec; // used for vec![]
     pub use cell; // used for tls!
-    pub use thread_local; // used for thread_local!
+    pub use thread; // used for thread_local!
     pub use marker;  // used for tls!
     pub use ops; // used for bitflags!
 
diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs
index e4985e703ba..90526b8f4f3 100644
--- a/src/libstd/sys/common/thread_info.rs
+++ b/src/libstd/sys/common/thread_info.rs
@@ -15,7 +15,7 @@ use core::prelude::*;
 use cell::RefCell;
 use string::String;
 use thread::Thread;
-use thread_local::State;
+use thread::LocalKeyState;
 
 struct ThreadInfo {
     stack_guard: uint,
@@ -26,7 +26,7 @@ thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(N
 
 impl ThreadInfo {
     fn with<R, F>(f: F) -> R where F: FnOnce(&mut ThreadInfo) -> R {
-        if THREAD_INFO.state() == State::Destroyed {
+        if THREAD_INFO.state() == LocalKeyState::Destroyed {
             panic!("Use of std::thread::current() is not possible after \
                     the thread's local data has been destroyed");
         }
diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread/local.rs
index 08780292c88..43142d2e5bc 100644
--- a/src/libstd/thread_local/mod.rs
+++ b/src/libstd/thread/local.rs
@@ -9,40 +9,13 @@
 // except according to those terms.
 
 //! Thread local storage
-//!
-//! This module provides an implementation of thread local storage for Rust
-//! programs. Thread local storage is a method of storing data into a global
-//! variable which each thread in the program will have its own copy of.
-//! Threads do not share this data, so accesses do not need to be synchronized.
-//!
-//! At a high level, this module provides two variants of storage:
-//!
-//! * Owning thread local storage. This is a type of thread local key which
-//!   owns the value that it contains, and will destroy the value when the
-//!   thread exits. This variant is created with the `thread_local!` macro and
-//!   can contain any value which is `'static` (no borrowed pointers.
-//!
-//! * Scoped thread local storage. This type of key is used to store a reference
-//!   to a value into local storage temporarily for the scope of a function
-//!   call. There are no restrictions on what types of values can be placed
-//!   into this key.
-//!
-//! Both forms of thread local storage provide an accessor function, `with`,
-//! which will yield a shared reference to the value to the specified
-//! closure. Thread local keys only allow shared access to values as there is no
-//! way to guarantee uniqueness if a mutable borrow was allowed. Most values
-//! will want to make use of some form of **interior mutability** through the
-//! `Cell` or `RefCell` types.
-
-#![stable(feature = "rust1", since = "1.0.0")]
+
+#![unstable(feature = "thread_local_internals")]
 
 use prelude::v1::*;
 
 use cell::UnsafeCell;
 
-#[macro_use]
-pub mod scoped;
-
 // Sure wish we had macro hygiene, no?
 #[doc(hidden)]
 #[unstable(feature = "thread_local_internals")]
@@ -95,7 +68,7 @@ pub mod __impl {
 /// });
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Key<T> {
+pub struct LocalKey<T> {
     // The key itself may be tagged with #[thread_local], and this `Key` is
     // stored as a `static`, and it's not valid for a static to reference the
     // address of another thread_local static. For this reason we kinda wonkily
@@ -114,15 +87,15 @@ pub struct Key<T> {
     pub init: fn() -> T,
 }
 
-/// Declare a new thread local storage key of type `std::thread_local::Key`.
+/// Declare a new thread local storage key of type `std::thread::LocalKey`.
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable]
 macro_rules! thread_local {
     (static $name:ident: $t:ty = $init:expr) => (
-        static $name: ::std::thread_local::Key<$t> = {
+        static $name: ::std::thread::LocalKey<$t> = {
             use std::cell::UnsafeCell as __UnsafeCell;
-            use std::thread_local::__impl::KeyInner as __KeyInner;
+            use std::thread::__local::__impl::KeyInner as __KeyInner;
             use std::option::Option as __Option;
             use std::option::Option::None as __None;
 
@@ -133,13 +106,13 @@ macro_rules! thread_local {
             fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> {
                 &__KEY
             }
-            ::std::thread_local::Key { inner: __getit, init: __init }
+            ::std::thread::LocalKey { inner: __getit, init: __init }
         };
     );
     (pub static $name:ident: $t:ty = $init:expr) => (
-        pub static $name: ::std::thread_local::Key<$t> = {
+        pub static $name: ::std::thread::LocalKey<$t> = {
             use std::cell::UnsafeCell as __UnsafeCell;
-            use std::thread_local::__impl::KeyInner as __KeyInner;
+            use std::thread::__local::__impl::KeyInner as __KeyInner;
             use std::option::Option as __Option;
             use std::option::Option::None as __None;
 
@@ -150,7 +123,7 @@ macro_rules! thread_local {
             fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> {
                 &__KEY
             }
-            ::std::thread_local::Key { inner: __getit, init: __init }
+            ::std::thread::LocalKey { inner: __getit, init: __init }
         };
     );
 }
@@ -183,20 +156,20 @@ macro_rules! __thread_local_inner {
         #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
                        not(target_arch = "aarch64")),
                    thread_local)]
-        static $name: ::std::thread_local::__impl::KeyInner<$t> =
+        static $name: ::std::thread::__local::__impl::KeyInner<$t> =
             __thread_local_inner!($init, $t);
     );
     (pub static $name:ident: $t:ty = $init:expr) => (
         #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
                        not(target_arch = "aarch64")),
                    thread_local)]
-        pub static $name: ::std::thread_local::__impl::KeyInner<$t> =
+        pub static $name: ::std::thread::__local::__impl::KeyInner<$t> =
             __thread_local_inner!($init, $t);
     );
     ($init:expr, $t:ty) => ({
         #[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))]
-        const _INIT: ::std::thread_local::__impl::KeyInner<$t> = {
-            ::std::thread_local::__impl::KeyInner {
+        const _INIT: ::std::thread::__local::__impl::KeyInner<$t> = {
+            ::std::thread::__local::__impl::KeyInner {
                 inner: ::std::cell::UnsafeCell { value: $init },
                 dtor_registered: ::std::cell::UnsafeCell { value: false },
                 dtor_running: ::std::cell::UnsafeCell { value: false },
@@ -204,15 +177,15 @@ macro_rules! __thread_local_inner {
         };
 
         #[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))]
-        const _INIT: ::std::thread_local::__impl::KeyInner<$t> = {
+        const _INIT: ::std::thread::__local::__impl::KeyInner<$t> = {
             unsafe extern fn __destroy(ptr: *mut u8) {
-                ::std::thread_local::__impl::destroy_value::<$t>(ptr);
+                ::std::thread::__local::__impl::destroy_value::<$t>(ptr);
             }
 
-            ::std::thread_local::__impl::KeyInner {
+            ::std::thread::__local::__impl::KeyInner {
                 inner: ::std::cell::UnsafeCell { value: $init },
-                os: ::std::thread_local::__impl::OsStaticKey {
-                    inner: ::std::thread_local::__impl::OS_INIT_INNER,
+                os: ::std::thread::__local::__impl::OsStaticKey {
+                    inner: ::std::thread::__local::__impl::OS_INIT_INNER,
                     dtor: ::std::option::Option::Some(__destroy as unsafe extern fn(*mut u8)),
                 },
             }
@@ -226,7 +199,7 @@ macro_rules! __thread_local_inner {
 #[unstable(feature = "std_misc",
            reason = "state querying was recently added")]
 #[derive(Eq, PartialEq, Copy)]
-pub enum State {
+pub enum LocalKeyState {
     /// All keys are in this state whenever a thread starts. Keys will
     /// transition to the `Valid` state once the first call to `with` happens
     /// and the initialization expression succeeds.
@@ -253,7 +226,7 @@ pub enum State {
     Destroyed,
 }
 
-impl<T: 'static> Key<T> {
+impl<T: 'static> LocalKey<T> {
     /// Acquire a reference to the value in this TLS key.
     ///
     /// This will lazily initialize the value if this thread has not referenced
@@ -309,16 +282,16 @@ impl<T: 'static> Key<T> {
     /// any call to `with`.
     #[unstable(feature = "std_misc",
                reason = "state querying was recently added")]
-    pub fn state(&'static self) -> State {
+    pub fn state(&'static self) -> LocalKeyState {
         unsafe {
             match (self.inner)().get() {
                 Some(cell) => {
                     match *cell.get() {
-                        Some(..) => State::Valid,
-                        None => State::Uninitialized,
+                        Some(..) => LocalKeyState::Valid,
+                        None => LocalKeyState::Uninitialized,
                     }
                 }
-                None => State::Destroyed,
+                None => LocalKeyState::Destroyed,
             }
         }
     }
@@ -327,7 +300,7 @@ impl<T: 'static> Key<T> {
     #[unstable(feature = "std_misc")]
     #[deprecated(since = "1.0.0",
                  reason = "function renamed to state() and returns more info")]
-    pub fn destroyed(&'static self) -> bool { self.state() == State::Destroyed }
+    pub fn destroyed(&'static self) -> bool { self.state() == LocalKeyState::Destroyed }
 }
 
 #[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))]
@@ -553,7 +526,7 @@ mod tests {
 
     use sync::mpsc::{channel, Sender};
     use cell::UnsafeCell;
-    use super::State;
+    use super::LocalKeyState;
     use thread;
 
     struct Foo(Sender<()>);
@@ -592,21 +565,21 @@ mod tests {
         struct Foo;
         impl Drop for Foo {
             fn drop(&mut self) {
-                assert!(FOO.state() == State::Destroyed);
+                assert!(FOO.state() == LocalKeyState::Destroyed);
             }
         }
         fn foo() -> Foo {
-            assert!(FOO.state() == State::Uninitialized);
+            assert!(FOO.state() == LocalKeyState::Uninitialized);
             Foo
         }
         thread_local!(static FOO: Foo = foo());
 
         thread::spawn(|| {
-            assert!(FOO.state() == State::Uninitialized);
+            assert!(FOO.state() == LocalKeyState::Uninitialized);
             FOO.with(|_| {
-                assert!(FOO.state() == State::Valid);
+                assert!(FOO.state() == LocalKeyState::Valid);
             });
-            assert!(FOO.state() == State::Valid);
+            assert!(FOO.state() == LocalKeyState::Valid);
         }).join().ok().unwrap();
     }
 
@@ -642,7 +615,7 @@ mod tests {
             fn drop(&mut self) {
                 unsafe {
                     HITS += 1;
-                    if K2.state() == State::Destroyed {
+                    if K2.state() == LocalKeyState::Destroyed {
                         assert_eq!(HITS, 3);
                     } else {
                         if HITS == 1 {
@@ -658,7 +631,7 @@ mod tests {
             fn drop(&mut self) {
                 unsafe {
                     HITS += 1;
-                    assert!(K1.state() != State::Destroyed);
+                    assert!(K1.state() != LocalKeyState::Destroyed);
                     assert_eq!(HITS, 2);
                     K1.with(|s| *s.get() = Some(S1));
                 }
@@ -679,7 +652,7 @@ mod tests {
 
         impl Drop for S1 {
             fn drop(&mut self) {
-                assert!(K1.state() == State::Destroyed);
+                assert!(K1.state() == LocalKeyState::Destroyed);
             }
         }
 
@@ -702,7 +675,7 @@ mod tests {
             fn drop(&mut self) {
                 let S1(ref tx) = *self;
                 unsafe {
-                    if K2.state() != State::Destroyed {
+                    if K2.state() != LocalKeyState::Destroyed {
                         K2.with(|s| *s.get() = Some(Foo(tx.clone())));
                     }
                 }
diff --git a/src/libstd/thread.rs b/src/libstd/thread/mod.rs
index ab74442cac9..57baeb1fb74 100644
--- a/src/libstd/thread.rs
+++ b/src/libstd/thread/mod.rs
@@ -138,9 +138,43 @@
 //!   synchronization primitives; the threads already provide basic blocking/signaling.
 //!
 //! * It can be implemented very efficiently on many platforms.
+//!
+//! ## Thread-local storage
+//!
+//! This module also provides an implementation of thread local storage for Rust
+//! programs. Thread local storage is a method of storing data into a global
+//! variable which each thread in the program will have its own copy of.
+//! Threads do not share this data, so accesses do not need to be synchronized.
+//!
+//! At a high level, this module provides two variants of storage:
+//!
+//! * Owned thread-local storage. This is a type of thread local key which
+//!   owns the value that it contains, and will destroy the value when the
+//!   thread exits. This variant is created with the `thread_local!` macro and
+//!   can contain any value which is `'static` (no borrowed pointers).
+//!
+//! * Scoped thread-local storage. This type of key is used to store a reference
+//!   to a value into local storage temporarily for the scope of a function
+//!   call. There are no restrictions on what types of values can be placed
+//!   into this key.
+//!
+//! Both forms of thread local storage provide an accessor function, `with`,
+//! which will yield a shared reference to the value to the specified
+//! closure. Thread-local keys only allow shared access to values as there is no
+//! way to guarantee uniqueness if a mutable borrow was allowed. Most values
+//! will want to make use of some form of **interior mutability** through the
+//! `Cell` or `RefCell` types.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::__local::{LocalKey, LocalKeyState};
+
+#[unstable(feature = "scoped_tls",
+            reason = "scoped TLS has yet to have wide enough use to fully consider \
+                      stabilizing its interface")]
+pub use self::__scoped::ScopedKey;
+
 use prelude::v1::*;
 
 use any::Any;
@@ -157,6 +191,22 @@ use time::Duration;
 
 #[allow(deprecated)] use old_io::Writer;
 
+////////////////////////////////////////////////////////////////////////////////
+// Thread-local storage
+////////////////////////////////////////////////////////////////////////////////
+
+#[macro_use]
+#[doc(hidden)]
+#[path = "local.rs"] pub mod __local;
+
+#[macro_use]
+#[doc(hidden)]
+#[path = "scoped.rs"] pub mod __scoped;
+
+////////////////////////////////////////////////////////////////////////////////
+// Builder
+////////////////////////////////////////////////////////////////////////////////
+
 /// Thread configuration. Provides detailed control over the properties
 /// and behavior of new threads.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -322,6 +372,10 @@ impl Builder {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Free functions
+////////////////////////////////////////////////////////////////////////////////
+
 /// Spawn a new thread, returning a `JoinHandle` for it.
 ///
 /// The join handle will implicitly *detach* the child thread upon being
@@ -433,6 +487,10 @@ pub fn park_timeout(duration: Duration) {
     *guard = false;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Thread
+////////////////////////////////////////////////////////////////////////////////
+
 /// The internal representation of a `Thread` handle
 struct Inner {
     name: Option<String>,
@@ -557,6 +615,10 @@ impl thread_info::NewThread for Thread {
     fn new(name: Option<String>) -> Thread { Thread::new(name) }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// JoinHandle and JoinGuard
+////////////////////////////////////////////////////////////////////////////////
+
 /// Indicates the manner in which a thread exited.
 ///
 /// A thread that completes without panicking is considered to exit successfully.
@@ -689,6 +751,10 @@ impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Tests
+////////////////////////////////////////////////////////////////////////////////
+
 #[cfg(test)]
 mod test {
     use prelude::v1::*;
diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread/scoped.rs
index 86e6c059a70..2a8be2ad82c 100644
--- a/src/libstd/thread_local/scoped.rs
+++ b/src/libstd/thread/scoped.rs
@@ -38,9 +38,7 @@
 //! });
 //! ```
 
-#![unstable(feature = "std_misc",
-            reason = "scoped TLS has yet to have wide enough use to fully consider \
-                      stabilizing its interface")]
+#![unstable(feature = "thread_local_internals")]
 
 use prelude::v1::*;
 
@@ -58,7 +56,10 @@ pub mod __impl {
 /// type `T` scoped to a particular lifetime. Keys provides two methods, `set`
 /// and `with`, both of which currently use closures to control the scope of
 /// their contents.
-pub struct Key<T> { #[doc(hidden)] pub inner: __impl::KeyInner<T> }
+#[unstable(feature = "scoped_tls",
+           reason = "scoped TLS has yet to have wide enough use to fully consider \
+                     stabilizing its interface")]
+pub struct ScopedKey<T> { #[doc(hidden)] pub inner: __impl::KeyInner<T> }
 
 /// Declare a new scoped thread local storage key.
 ///
@@ -86,7 +87,7 @@ macro_rules! __scoped_thread_local_inner {
                            target_os = "openbsd",
                            target_arch = "aarch64")),
                    thread_local)]
-        static $name: ::std::thread_local::scoped::Key<$t> =
+        static $name: ::std::thread::ScopedKey<$t> =
             __scoped_thread_local_inner!($t);
     );
     (pub static $name:ident: $t:ty) => (
@@ -96,11 +97,11 @@ macro_rules! __scoped_thread_local_inner {
                            target_os = "openbsd",
                            target_arch = "aarch64")),
                    thread_local)]
-        pub static $name: ::std::thread_local::scoped::Key<$t> =
+        pub static $name: ::std::thread::ScopedKey<$t> =
             __scoped_thread_local_inner!($t);
     );
     ($t:ty) => ({
-        use std::thread_local::scoped::Key as __Key;
+        use std::thread::ScopedKey as __Key;
 
         #[cfg(not(any(windows,
                       target_os = "android",
@@ -108,7 +109,7 @@ macro_rules! __scoped_thread_local_inner {
                       target_os = "openbsd",
                       target_arch = "aarch64")))]
         const _INIT: __Key<$t> = __Key {
-            inner: ::std::thread_local::scoped::__impl::KeyInner {
+            inner: ::std::thread::__scoped::__impl::KeyInner {
                 inner: ::std::cell::UnsafeCell { value: 0 as *mut _ },
             }
         };
@@ -119,8 +120,8 @@ macro_rules! __scoped_thread_local_inner {
                   target_os = "openbsd",
                   target_arch = "aarch64"))]
         const _INIT: __Key<$t> = __Key {
-            inner: ::std::thread_local::scoped::__impl::KeyInner {
-                inner: ::std::thread_local::scoped::__impl::OS_INIT,
+            inner: ::std::thread::__scoped::__impl::KeyInner {
+                inner: ::std::thread::__scoped::__impl::OS_INIT,
                 marker: ::std::marker::PhantomData::<::std::cell::Cell<$t>>,
             }
         };
@@ -129,7 +130,10 @@ macro_rules! __scoped_thread_local_inner {
     })
 }
 
-impl<T> Key<T> {
+#[unstable(feature = "scoped_tls",
+           reason = "scoped TLS has yet to have wide enough use to fully consider \
+                     stabilizing its interface")]
+impl<T> ScopedKey<T> {
     /// Insert a value into this scoped thread local storage slot for a
     /// duration of a closure.
     ///