Skip to content

Commit

Permalink
rollup merge of rust-lang#23557: aturon/rfc-909
Browse files Browse the repository at this point in the history
This commit implements [RFC 909](rust-lang/rfcs#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 rust-lang#23547
  • Loading branch information
alexcrichton committed Mar 23, 2015
2 parents b97e1cc + 6bd3ab0 commit 2153c58
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 91 deletions.
23 changes: 8 additions & 15 deletions src/libstd/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,30 +252,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;
Expand Down Expand Up @@ -308,7 +301,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!

Expand Down
4 changes: 2 additions & 2 deletions src/libstd/sys/common/thread_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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");
}
Expand Down
99 changes: 36 additions & 63 deletions src/libstd/thread_local/mod.rs → src/libstd/thread/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -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
Expand All @@ -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;

Expand All @@ -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;

Expand All @@ -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 }
};
);
}
Expand Down Expand Up @@ -183,36 +156,36 @@ 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 },
}
};

#[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)),
},
}
Expand All @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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,
}
}
}
Expand All @@ -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")))]
Expand Down Expand Up @@ -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<()>);
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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 {
Expand All @@ -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));
}
Expand All @@ -679,7 +652,7 @@ mod tests {

impl Drop for S1 {
fn drop(&mut self) {
assert!(K1.state() == State::Destroyed);
assert!(K1.state() == LocalKeyState::Destroyed);
}
}

Expand All @@ -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())));
}
}
Expand Down
Loading

0 comments on commit 2153c58

Please sign in to comment.