diff options
| -rw-r--r-- | src/libextra/rl.rs | 2 | ||||
| -rw-r--r-- | src/librustc/back/link.rs | 8 | ||||
| -rw-r--r-- | src/librustc/middle/trans/base.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/trans/context.rs | 2 | ||||
| -rw-r--r-- | src/librusti/program.rs | 10 | ||||
| -rw-r--r-- | src/libstd/local_data.rs | 80 | ||||
| -rw-r--r-- | src/libstd/os.rs | 2 | ||||
| -rw-r--r-- | src/libstd/rand.rs | 2 | ||||
| -rw-r--r-- | src/libstd/rt/task.rs | 4 | ||||
| -rw-r--r-- | src/libstd/std.rs | 1 | ||||
| -rw-r--r-- | src/libstd/task/local_data_priv.rs | 3 | ||||
| -rw-r--r-- | src/libstd/task/spawn.rs | 19 | ||||
| -rw-r--r-- | src/libsyntax/ast_util.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 3 | ||||
| -rw-r--r-- | src/test/compile-fail/core-tls-store-pointer.rs | 3 |
16 files changed, 81 insertions, 70 deletions
diff --git a/src/libextra/rl.rs b/src/libextra/rl.rs index b7b74694475..59801c945b6 100644 --- a/src/libextra/rl.rs +++ b/src/libextra/rl.rs @@ -69,7 +69,7 @@ pub unsafe fn read(prompt: &str) -> Option<~str> { pub type CompletionCb = @fn(~str, @fn(~str)); #[cfg(not(stage0))] -static complete_key: local_data::Key<@CompletionCb> = &[]; +static complete_key: local_data::Key<@CompletionCb> = &local_data::Key; #[cfg(stage0)] fn complete_key(_: @CompletionCb) {} diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 593a1ed535d..aeed2d842c1 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -105,6 +105,7 @@ pub mod jit { use metadata::cstore; use std::cast; + #[cfg(not(stage0))] use std::local_data; use std::unstable::intrinsics; @@ -202,18 +203,19 @@ pub mod jit { // The stage1 compiler won't work, but that doesn't really matter. TLS // changed only very recently to allow storage of owned values. - fn engine_key(_: ~Engine) {} + #[cfg(not(stage0))] + static engine_key: local_data::Key<~Engine> = &local_data::Key; #[cfg(not(stage0))] fn set_engine(engine: ~Engine) { - unsafe { local_data::set(engine_key, engine) } + local_data::set(engine_key, engine) } #[cfg(stage0)] fn set_engine(_: ~Engine) {} #[cfg(not(stage0))] pub fn consume_engine() -> Option<~Engine> { - unsafe { local_data::pop(engine_key) } + local_data::pop(engine_key) } #[cfg(stage0)] pub fn consume_engine() -> Option<~Engine> { None } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index bfa325a21ee..7182f7ff8b7 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -88,7 +88,7 @@ use syntax::abi::{X86, X86_64, Arm, Mips}; pub use middle::trans::context::task_llcx; #[cfg(not(stage0))] -static task_local_insn_key: local_data::Key<@~[&'static str]> = &[]; +static task_local_insn_key: local_data::Key<@~[&'static str]> = &local_data::Key; #[cfg(stage0)] fn task_local_insn_key(_: @~[&'static str]) {} diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index a2f0fd480e1..ffebb87d5cf 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -239,7 +239,7 @@ impl Drop for CrateContext { #[cfg(stage0)] fn task_local_llcx_key(_v: @ContextRef) {} #[cfg(not(stage0))] -static task_local_llcx_key: local_data::Key<@ContextRef> = &[]; +static task_local_llcx_key: local_data::Key<@ContextRef> = &local_data::Key; pub fn task_llcx() -> ContextRef { let opt = local_data::get(task_local_llcx_key, |k| k.map(|&k| *k)); diff --git a/src/librusti/program.rs b/src/librusti/program.rs index d1d5b47ff57..9031a001eca 100644 --- a/src/librusti/program.rs +++ b/src/librusti/program.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cast; use std::hashmap::HashMap; use std::local_data; -use std::vec; use syntax::ast; use syntax::parse::token; @@ -57,7 +57,7 @@ struct LocalVariable { } type LocalCache = @mut HashMap<~str, @~[u8]>; -static tls_key: local_data::Key<LocalCache> = &[]; +static tls_key: local_data::Key<LocalCache> = &local_data::Key; impl Program { pub fn new() -> Program { @@ -130,16 +130,14 @@ impl Program { fn main() { "); - let key: *LocalCache = vec::raw::to_ptr(tls_key); + let key: uint= unsafe { cast::transmute(tls_key) }; // First, get a handle to the tls map which stores all the local // variables. This works by totally legitimately using the 'code' // pointer of the 'tls_key' function as a uint, and then casting it back // up to a function code.push_str(fmt!(" let __tls_map: @mut ::std::hashmap::HashMap<~str, @~[u8]> = unsafe { - let key = ::std::vec::raw::SliceRepr{ data: %? as *u8, - len: 0 }; - let key = ::std::cast::transmute(key); + let key = ::std::cast::transmute(%u); ::std::local_data::get(key, |k| k.map(|&x| *x)).unwrap() };\n", key as uint)); diff --git a/src/libstd/local_data.rs b/src/libstd/local_data.rs index 640bcc757b3..be170cce07e 100644 --- a/src/libstd/local_data.rs +++ b/src/libstd/local_data.rs @@ -13,18 +13,19 @@ Task local data management Allows storing arbitrary types inside task-local-storage (TLS), to be accessed -anywhere within a task, keyed by a global slice of the appropriate type. -Useful for dynamic variables, singletons, and interfacing with foreign code -with bad callback interfaces. +anywhere within a task, keyed by a global pointer parameterized over the type of +the TLS slot. Useful for dynamic variables, singletons, and interfacing with +foreign code with bad callback interfaces. -To use, declare a static slice of the type you wish to store. The initialization -should be `&[]`. This is then the key to what you wish to store. +To use, declare a static variable of the type you wish to store. The +initialization should be `&local_data::Key`. This is then the key to what you +wish to store. ~~~{.rust} use std::local_data; -static key_int: local_data::Key<int> = &[]; -static key_vector: local_data::Key<~[int]> = &[]; +static key_int: local_data::Key<int> = &local_data::Key; +static key_vector: local_data::Key<~[int]> = &local_data::Key; local_data::set(key_int, 3); local_data::get(key_int, |opt| assert_eq!(opt, Some(&3))); @@ -45,24 +46,23 @@ use task::local_data_priv::{local_get, local_pop, local_set, Handle}; #[cfg(test)] use task; /** - * Indexes a task-local data slot. The function's code pointer is used for - * comparison. Recommended use is to write an empty function for each desired - * task-local data slot (and use class destructors, not code inside the - * function, if specific teardown is needed). DO NOT use multiple - * instantiations of a single polymorphic function to index data of different - * types; arbitrary type coercion is possible this way. + * Indexes a task-local data slot. This pointer is used for comparison to + * differentiate keys from one another. The actual type `T` is not used anywhere + * as a member of this type, except that it is parameterized with it to define + * the type of each key's value. * - * One other exception is that this global state can be used in a destructor - * context to create a circular @-box reference, which will crash during task - * failure (see issue #3039). - * - * These two cases aside, the interface is safe. + * The value of each Key is of the singleton enum KeyValue. These also have the + * same name as `Key` and their purpose is to take up space in the programs data + * sections to ensure that each value of the `Key` type points to a unique + * location. */ #[cfg(not(stage0))] -pub type Key<T> = &'static [T]; +pub type Key<T> = &'static KeyValue<T>; #[cfg(stage0)] pub type Key<'self,T> = &'self fn:Copy(v: T); +pub enum KeyValue<T> { Key } + /** * Remove a task-local data value from the table, returning the * reference that was originally created to insert it. @@ -136,7 +136,7 @@ pub fn modify<T: 'static>(key: Key<T>, f: &fn(Option<T>) -> Option<T>) { #[test] fn test_tls_multitask() { - static my_key: Key<@~str> = &[]; + static my_key: Key<@~str> = &Key; set(my_key, @~"parent data"); do task::spawn { // TLS shouldn't carry over. @@ -154,7 +154,7 @@ fn test_tls_multitask() { #[test] fn test_tls_overwrite() { - static my_key: Key<@~str> = &[]; + static my_key: Key<@~str> = &Key; set(my_key, @~"first data"); set(my_key, @~"next data"); // Shouldn't leak. assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"next data"); @@ -162,7 +162,7 @@ fn test_tls_overwrite() { #[test] fn test_tls_pop() { - static my_key: Key<@~str> = &[]; + static my_key: Key<@~str> = &Key; set(my_key, @~"weasel"); assert!(*(pop(my_key).get()) == ~"weasel"); // Pop must remove the data from the map. @@ -171,7 +171,7 @@ fn test_tls_pop() { #[test] fn test_tls_modify() { - static my_key: Key<@~str> = &[]; + static my_key: Key<@~str> = &Key; modify(my_key, |data| { match data { Some(@ref val) => fail!("unwelcome value: %s", *val), @@ -196,7 +196,7 @@ fn test_tls_crust_automorestack_memorial_bug() { // to get recorded as something within a rust stack segment. Then a // subsequent upcall (esp. for logging, think vsnprintf) would run on // a stack smaller than 1 MB. - static my_key: Key<@~str> = &[]; + static my_key: Key<@~str> = &Key; do task::spawn { set(my_key, @~"hax"); } @@ -204,9 +204,9 @@ fn test_tls_crust_automorestack_memorial_bug() { #[test] fn test_tls_multiple_types() { - static str_key: Key<@~str> = &[]; - static box_key: Key<@@()> = &[]; - static int_key: Key<@int> = &[]; + static str_key: Key<@~str> = &Key; + static box_key: Key<@@()> = &Key; + static int_key: Key<@int> = &Key; do task::spawn { set(str_key, @~"string data"); set(box_key, @@()); @@ -216,9 +216,9 @@ fn test_tls_multiple_types() { #[test] fn test_tls_overwrite_multiple_types() { - static str_key: Key<@~str> = &[]; - static box_key: Key<@@()> = &[]; - static int_key: Key<@int> = &[]; + static str_key: Key<@~str> = &Key; + static box_key: Key<@@()> = &Key; + static int_key: Key<@int> = &Key; do task::spawn { set(str_key, @~"string data"); set(int_key, @42); @@ -233,9 +233,9 @@ fn test_tls_overwrite_multiple_types() { #[should_fail] #[ignore(cfg(windows))] fn test_tls_cleanup_on_failure() { - static str_key: Key<@~str> = &[]; - static box_key: Key<@@()> = &[]; - static int_key: Key<@int> = &[]; + static str_key: Key<@~str> = &Key; + static box_key: Key<@@()> = &Key; + static int_key: Key<@int> = &Key; set(str_key, @~"parent data"); set(box_key, @@()); do task::spawn { @@ -252,7 +252,7 @@ fn test_tls_cleanup_on_failure() { #[test] fn test_static_pointer() { - static key: Key<@&'static int> = &[]; + static key: Key<@&'static int> = &Key; static VALUE: int = 0; let v: @&'static int = @&VALUE; set(key, v); @@ -260,17 +260,17 @@ fn test_static_pointer() { #[test] fn test_owned() { - static key: Key<~int> = &[]; + static key: Key<~int> = &Key; set(key, ~1); } #[test] fn test_same_key_type() { - static key1: Key<int> = &[]; - static key2: Key<int> = &[]; - static key3: Key<int> = &[]; - static key4: Key<int> = &[]; - static key5: Key<int> = &[]; + static key1: Key<int> = &Key; + static key2: Key<int> = &Key; + static key3: Key<int> = &Key; + static key4: Key<int> = &Key; + static key5: Key<int> = &Key; set(key1, 1); set(key2, 2); set(key3, 3); diff --git a/src/libstd/os.rs b/src/libstd/os.rs index cbd1e4e7663..58175db1241 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -1242,7 +1242,7 @@ struct OverriddenArgs { #[cfg(stage0)] fn overridden_arg_key(_v: @OverriddenArgs) {} #[cfg(not(stage0))] -static overridden_arg_key: local_data::Key<@OverriddenArgs> = &[]; +static overridden_arg_key: local_data::Key<@OverriddenArgs> = &local_data::Key; /// Returns the arguments which this program was started with (normally passed /// via the command line). diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs index 8551012d6d7..6f89e7ffb07 100644 --- a/src/libstd/rand.rs +++ b/src/libstd/rand.rs @@ -854,7 +854,7 @@ pub fn seed() -> ~[u8] { #[cfg(stage0)] fn tls_rng_state(_v: @@mut IsaacRng) {} #[cfg(not(stage0))] -static tls_rng_state: local_data::Key<@@mut IsaacRng> = &[]; +static tls_rng_state: local_data::Key<@@mut IsaacRng> = &local_data::Key; /** * Gives back a lazily initialized task-local random number generator, diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index 0fd8c5c03d3..17d0d59660f 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -348,10 +348,10 @@ mod test { fn tls() { use local_data; do run_in_newsched_task() { - static key: local_data::Key<@~str> = &[]; + static key: local_data::Key<@~str> = &local_data::Key; local_data::set(key, @~"data"); assert!(*local_data::get(key, |k| k.map(|&k| *k)).get() == ~"data"); - static key2: local_data::Key<@~str> = &[]; + static key2: local_data::Key<@~str> = &local_data::Key; local_data::set(key2, @~"data"); assert!(*local_data::get(key2, |k| k.map(|&k| *k)).get() == ~"data"); } diff --git a/src/libstd/std.rs b/src/libstd/std.rs index 8f86216d240..03b895b3860 100644 --- a/src/libstd/std.rs +++ b/src/libstd/std.rs @@ -222,6 +222,7 @@ mod std { pub use condition; pub use option; pub use kinds; + pub use local_data; pub use sys; pub use pipes; pub use unstable; diff --git a/src/libstd/task/local_data_priv.rs b/src/libstd/task/local_data_priv.rs index 1a2141e996a..d46e5707f14 100644 --- a/src/libstd/task/local_data_priv.rs +++ b/src/libstd/task/local_data_priv.rs @@ -17,7 +17,6 @@ use prelude::*; use ptr; use task::rt; use util; -use vec; use super::rt::rust_task; use rt::task::{Task, LocalStorage}; @@ -143,7 +142,7 @@ unsafe fn get_local_map(handle: Handle) -> &mut TaskLocalMap { } fn key_to_key_value<T: 'static>(key: local_data::Key<T>) -> *libc::c_void { - return vec::raw::to_ptr(key) as *libc::c_void; + unsafe { cast::transmute(key) } } pub unsafe fn local_pop<T: 'static>(handle: Handle, diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs index 27cb1c2c100..206d19e175f 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -80,6 +80,7 @@ use cell::Cell; use container::MutableMap; use comm::{Chan, GenericChan}; use hashmap::HashSet; +use local_data; use task::local_data_priv::{local_get, local_set, OldHandle}; use task::rt::rust_task; use task::rt; @@ -465,10 +466,14 @@ fn kill_taskgroup(state: TaskGroupInner, me: *rust_task, is_main: bool) { // FIXME (#2912): Work around core-vs-coretest function duplication. Can't use // a proper closure because the #[test]s won't understand. Have to fake it. -macro_rules! taskgroup_key ( - // Use a "code pointer" value that will never be a real code pointer. - () => (cast::transmute((-2 as uint, 0u))) -) +#[cfg(not(stage0))] +fn taskgroup_key() -> local_data::Key<@@mut TCB> { + unsafe { cast::transmute(-2) } +} +#[cfg(stage0)] +fn taskgroup_key() -> local_data::Key<@@mut TCB> { + unsafe { cast::transmute((-2, 0)) } +} fn gen_child_taskgroup(linked: bool, supervised: bool) -> (TaskGroupArc, AncestorList, bool) { @@ -478,7 +483,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool) * Step 1. Get spawner's taskgroup info. *##################################################################*/ let spawner_group: @@mut TCB = - do local_get(OldHandle(spawner), taskgroup_key!()) |group| { + do local_get(OldHandle(spawner), taskgroup_key()) |group| { match group { None => { // Main task, doing first spawn ever. Lazily initialise @@ -495,7 +500,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool) AncestorList(None), true, None); - local_set(OldHandle(spawner), taskgroup_key!(), group); + local_set(OldHandle(spawner), taskgroup_key(), group); group } Some(&group) => group @@ -688,7 +693,7 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) { is_main, notifier); unsafe { - local_set(OldHandle(child), taskgroup_key!(), group); + local_set(OldHandle(child), taskgroup_key(), group); } // Run the child's body. diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 0b876bf1f81..a1d209d19ac 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -695,7 +695,7 @@ pub fn new_sctable_internal() -> SCTable { // fetch the SCTable from TLS, create one if it doesn't yet exist. pub fn get_sctable() -> @mut SCTable { #[cfg(not(stage0))] - static sctable_key: local_data::Key<@@mut SCTable> = &[]; + static sctable_key: local_data::Key<@@mut SCTable> = &local_data::Key; #[cfg(stage0)] fn sctable_key(_: @@mut SCTable) {} match local_data::get(sctable_key, |k| k.map(|&k| *k)) { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 4fbc3862848..b45cde6a8e3 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -580,7 +580,9 @@ pub fn core_macros() -> @str { pub mod $c { #[allow(non_uppercase_statics)]; - static key: &'static [@::std::condition::Handler<$in, $out>] = &[]; + static key: ::std::local_data::Key< + @::std::condition::Handler<$in, $out>> = + &::std::local_data::Key; pub static cond : ::std::condition::Condition<$in,$out> = @@ -596,7 +598,9 @@ pub fn core_macros() -> @str { // FIXME (#6009): remove mod's `pub` below once variant above lands. pub mod $c { #[allow(non_uppercase_statics)]; - static key: &'static [@::std::condition::Handler<$in, $out>] = &[]; + static key: ::std::local_data::Key< + @::std::condition::Handler<$in, $out>> = + &::std::local_data::Key; pub static cond : ::std::condition::Condition<$in,$out> = diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 8737e571399..01860c3ae99 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -485,7 +485,8 @@ fn mk_fresh_ident_interner() -> @ident_interner { // fresh one. pub fn get_ident_interner() -> @ident_interner { #[cfg(not(stage0))] - static key: local_data::Key<@@::parse::token::ident_interner> = &[]; + static key: local_data::Key<@@::parse::token::ident_interner> = + &local_data::Key; #[cfg(stage0)] fn key(_: @@::parse::token::ident_interner) {} match local_data::get(key, |k| k.map(|&k| *k)) { diff --git a/src/test/compile-fail/core-tls-store-pointer.rs b/src/test/compile-fail/core-tls-store-pointer.rs index f5b7f34b365..576b1c452a5 100644 --- a/src/test/compile-fail/core-tls-store-pointer.rs +++ b/src/test/compile-fail/core-tls-store-pointer.rs @@ -12,6 +12,7 @@ use std::local_data; -static key: local_data::Key<@&int> = &[]; //~ ERROR only 'static is allowed +static key: local_data::Key<@&int> = &local_data::Key; +//~^ ERROR only 'static is allowed fn main() {} |
