提交 e3211fa1 编写于 作者: A Alex Crichton

Purge the last remnants of the old TLS api

Closes #3273
上级 242606c7
......@@ -66,24 +66,28 @@ pub unsafe fn read(prompt: &str) -> Option<~str> {
}
}
pub type CompletionCb<'self> = @fn(~str, &'self fn(~str));
pub type CompletionCb = @fn(~str, @fn(~str));
fn complete_key(_v: @CompletionCb) {}
#[cfg(not(stage0))]
static complete_key: local_data::Key<@CompletionCb> = &[];
#[cfg(stage0)]
fn complete_key(_: @CompletionCb) {}
/// Bind to the main completion callback
pub unsafe fn complete(cb: CompletionCb) {
local_data::set(complete_key, @(cb));
local_data::set(complete_key, @cb);
extern fn callback(line: *c_char, completions: *()) {
unsafe {
let cb = *local_data::get(complete_key, |k| k.map(|&k| *k))
.get();
do cb(str::raw::from_c_str(line)) |suggestion| {
do str::as_c_str(suggestion) |buf| {
rustrt::linenoiseAddCompletion(completions, buf);
do local_data::get(complete_key) |cb| {
let cb = **cb.unwrap();
unsafe {
do cb(str::raw::from_c_str(line)) |suggestion| {
do str::as_c_str(suggestion) |buf| {
rustrt::linenoiseAddCompletion(completions, buf);
}
}
}
}
}
}
......
......@@ -1195,39 +1195,4 @@ fn isSorted<T:Ord>(arr: &[@T]) {
isSorted(arr);
}
}
struct LVal<'self> {
val: uint,
key: &'self fn:Copy(@uint),
}
#[unsafe_destructor]
impl<'self> Drop for LVal<'self> {
fn drop(&self) {
let x = unsafe { local_data::get(self.key, |k| k.map(|&k| *k)) };
match x {
Some(@y) => {
unsafe {
local_data::set(self.key, @(y+1));
}
}
_ => fail!("Expected key to work"),
}
}
}
impl<'self> Ord for LVal<'self> {
fn lt<'a>(&self, other: &'a LVal<'self>) -> bool {
(*self).val < other.val
}
fn le<'a>(&self, other: &'a LVal<'self>) -> bool {
(*self).val <= other.val
}
fn gt<'a>(&self, other: &'a LVal<'self>) -> bool {
(*self).val > other.val
}
fn ge<'a>(&self, other: &'a LVal<'self>) -> bool {
(*self).val >= other.val
}
}
}
......@@ -87,21 +87,20 @@
pub use middle::trans::context::task_llcx;
fn task_local_insn_key(_v: @~[&'static str]) {}
#[cfg(not(stage0))]
static task_local_insn_key: local_data::Key<@~[&'static str]> = &[];
#[cfg(stage0)]
fn task_local_insn_key(_: @~[&'static str]) {}
pub fn with_insn_ctxt(blk: &fn(&[&'static str])) {
unsafe {
let opt = local_data::get(task_local_insn_key, |k| k.map(|&k| *k));
if opt.is_some() {
blk(*opt.unwrap());
}
let opt = local_data::get(task_local_insn_key, |k| k.map(|&k| *k));
if opt.is_some() {
blk(*opt.unwrap());
}
}
pub fn init_insn_ctxt() {
unsafe {
local_data::set(task_local_insn_key, @~[]);
}
local_data::set(task_local_insn_key, @~[]);
}
pub struct _InsnCtxt { _x: () }
......@@ -109,13 +108,11 @@ pub struct _InsnCtxt { _x: () }
#[unsafe_destructor]
impl Drop for _InsnCtxt {
fn drop(&self) {
unsafe {
do local_data::modify(task_local_insn_key) |c| {
do c.map_consume |ctx| {
let mut ctx = copy *ctx;
ctx.pop();
@ctx
}
do local_data::modify(task_local_insn_key) |c| {
do c.map_consume |ctx| {
let mut ctx = copy *ctx;
ctx.pop();
@ctx
}
}
}
......@@ -123,13 +120,11 @@ fn drop(&self) {
pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
debug!("new InsnCtxt: %s", s);
unsafe {
do local_data::modify(task_local_insn_key) |c| {
do c.map_consume |ctx| {
let mut ctx = copy *ctx;
ctx.push(s);
@ctx
}
do local_data::modify(task_local_insn_key) |c| {
do c.map_consume |ctx| {
let mut ctx = copy *ctx;
ctx.push(s);
@ctx
}
}
_InsnCtxt { _x: () }
......
......@@ -232,22 +232,24 @@ pub fn new(sess: session::Session,
#[unsafe_destructor]
impl Drop for CrateContext {
fn drop(&self) {
unsafe {
unset_task_llcx();
}
unset_task_llcx();
}
}
#[cfg(stage0)]
fn task_local_llcx_key(_v: @ContextRef) {}
#[cfg(not(stage0))]
static task_local_llcx_key: local_data::Key<@ContextRef> = &[];
pub fn task_llcx() -> ContextRef {
let opt = unsafe { local_data::get(task_local_llcx_key, |k| k.map(|&k| *k)) };
let opt = local_data::get(task_local_llcx_key, |k| k.map(|&k| *k));
*opt.expect("task-local LLVMContextRef wasn't ever set!")
}
unsafe fn set_task_llcx(c: ContextRef) {
fn set_task_llcx(c: ContextRef) {
local_data::set(task_local_llcx_key, @c);
}
unsafe fn unset_task_llcx() {
fn unset_task_llcx() {
local_data::pop(task_local_llcx_key);
}
......@@ -8,10 +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::sys;
use std::vec;
use syntax::ast;
use syntax::parse::token;
......@@ -58,7 +57,7 @@ struct LocalVariable {
}
type LocalCache = @mut HashMap<~str, @~[u8]>;
fn tls_key(_k: LocalCache) {}
static tls_key: local_data::Key<LocalCache> = &[];
impl Program {
pub fn new() -> Program {
......@@ -131,21 +130,18 @@ pub fn code(&mut self, user_input: &str, to_print: &Option<~str>) -> ~str {
fn main() {
");
let key: sys::Closure = unsafe {
let tls_key: &'static fn(LocalCache) = tls_key;
cast::transmute(tls_key)
};
let key: *LocalCache = vec::raw::to_ptr(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::sys::Closure{ code: %? as *(),
env: ::std::ptr::null() };
let key = ::std::vec::raw::SliceRepr{ data: %? as *u8,
len: 0 };
let key = ::std::cast::transmute(key);
::std::local_data::get(key, |k| k.map(|&x| *x)).unwrap()
};\n", key.code as uint));
};\n", key as uint));
// Using this __tls_map handle, deserialize each variable binding that
// we know about
......@@ -226,18 +222,14 @@ pub fn set_cache(&self) {
for self.local_vars.iter().advance |(name, value)| {
map.insert(copy *name, @copy value.data);
}
unsafe {
local_data::set(tls_key, map);
}
local_data::set(tls_key, map);
}
/// Once the program has finished running, this function will consume the
/// task-local cache of local variables. After the program finishes running,
/// it updates this cache with the new values of each local variable.
pub fn consume_cache(&mut self) {
let map = unsafe {
local_data::pop(tls_key).expect("tls is empty")
};
let map = local_data::pop(tls_key).expect("tls is empty");
do map.consume |name, value| {
match self.local_vars.find_mut(&name) {
Some(v) => { v.data = copy *value; }
......
......@@ -23,13 +23,59 @@ pub struct Handler<T, U> {
prev: Option<@Handler<T, U>>,
}
#[cfg(stage0)]
pub struct Condition<'self, T, U> {
name: &'static str,
key: local_data::Key<'self, @Handler<T, U>>
}
#[cfg(not(stage0))]
pub struct Condition<T, U> {
name: &'static str,
key: local_data::Key<@Handler<T, U>>
}
#[cfg(not(stage0))]
impl<T, U> Condition<T, U> {
pub fn trap<'a>(&'a self, h: &'a fn(T) -> U) -> Trap<'a, T, U> {
unsafe {
let p : *RustClosure = ::cast::transmute(&h);
let prev = local_data::get(self.key, |k| k.map(|&x| *x));
let h = @Handler { handle: *p, prev: prev };
Trap { cond: self, handler: h }
}
}
pub fn raise(&self, t: T) -> U {
let msg = fmt!("Unhandled condition: %s: %?", self.name, t);
self.raise_default(t, || fail!(copy msg))
}
pub fn raise_default(&self, t: T, default: &fn() -> U) -> U {
unsafe {
match local_data::pop(self.key) {
None => {
debug!("Condition.raise: found no handler");
default()
}
Some(handler) => {
debug!("Condition.raise: found handler");
match handler.prev {
None => {}
Some(hp) => local_data::set(self.key, hp)
}
let handle : &fn(T) -> U =
::cast::transmute(handler.handle);
let u = handle(t);
local_data::set(self.key, handler);
u
}
}
}
}
}
#[cfg(stage0)]
impl<'self, T, U> Condition<'self, T, U> {
pub fn trap(&'self self, h: &'self fn(T) -> U) -> Trap<'self, T, U> {
pub fn trap<'a>(&'a self, h: &'a fn(T) -> U) -> Trap<'a, T, U> {
unsafe {
let p : *RustClosure = ::cast::transmute(&h);
let prev = local_data::get(self.key, |k| k.map(|&x| *x));
......@@ -67,38 +113,45 @@ pub fn raise_default(&self, t: T, default: &fn() -> U) -> U {
}
}
#[cfg(stage0)]
struct Trap<'self, T, U> {
cond: &'self Condition<'self, T, U>,
handler: @Handler<T, U>
}
#[cfg(not(stage0))]
struct Trap<'self, T, U> {
cond: &'self Condition<T, U>,
handler: @Handler<T, U>
}
impl<'self, T, U> Trap<'self, T, U> {
pub fn in<V>(&self, inner: &'self fn() -> V) -> V {
unsafe {
let _g = Guard { cond: self.cond };
debug!("Trap: pushing handler to TLS");
local_data::set(self.cond.key, self.handler);
inner()
}
let _g = Guard { cond: self.cond };
debug!("Trap: pushing handler to TLS");
local_data::set(self.cond.key, self.handler);
inner()
}
}
#[cfg(stage0)]
struct Guard<'self, T, U> {
cond: &'self Condition<'self, T, U>
}
#[cfg(not(stage0))]
struct Guard<'self, T, U> {
cond: &'self Condition<T, U>
}
#[unsafe_destructor]
impl<'self, T, U> Drop for Guard<'self, T, U> {
fn drop(&self) {
unsafe {
debug!("Guard: popping handler from TLS");
let curr = local_data::pop(self.cond.key);
match curr {
debug!("Guard: popping handler from TLS");
let curr = local_data::pop(self.cond.key);
match curr {
None => {}
Some(h) => match h.prev {
None => {}
Some(h) => match h.prev {
None => {}
Some(hp) => local_data::set(self.cond.key, hp)
}
Some(hp) => local_data::set(self.cond.key, hp)
}
}
}
......
......@@ -12,27 +12,25 @@
Task local data management
Allows storing boxes with arbitrary types inside, to be accessed anywhere within
a task, keyed by a pointer to a global finaliser function. Useful for dynamic
variables, singletons, and interfacing with foreign code with bad callback
interfaces.
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.
To use, declare a monomorphic (no type parameters) global function at the type
to store, and use it as the 'key' when accessing.
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.
~~~{.rust}
use std::local_data;
fn key_int(_: @int) {}
fn key_vector(_: @~[int]) {}
static key_int: local_data::Key<int> = &[];
static key_vector: local_data::Key<~[int]> = &[];
unsafe {
local_data::set(key_int, @3);
assert!(local_data::get(key_int) == Some(@3));
local_data::set(key_int, 3);
local_data::get(key_int, |opt| assert_eq!(opt, Some(&3)));
local_data::set(key_vector, @~[3]);
assert!(local_data::get(key_vector).unwrap()[0] == 3);
}
local_data::set(key_vector, ~[4]);
local_data::get(key_int, |opt| assert_eq!(opt, Some(&~[4])));
~~~
Casting 'Arcane Sight' reveals an overwhelming aura of Transmutation
......@@ -60,6 +58,9 @@ fn key_vector(_: @~[int]) {}
*
* These two cases aside, the interface is safe.
*/
#[cfg(not(stage0))]
pub type Key<T> = &'static [T];
#[cfg(stage0)]
pub type Key<'self,T> = &'self fn:Copy(v: T);
/**
......@@ -67,56 +68,55 @@ fn key_vector(_: @~[int]) {}
* reference that was originally created to insert it.
*/
#[cfg(stage0)]
pub unsafe fn pop<T: 'static>(key: Key<@T>) -> Option<@T> {
local_pop(Handle::new(), key)
pub fn pop<T: 'static>(key: Key<@T>) -> Option<@T> {
unsafe { local_pop(Handle::new(), key) }
}
/**
* Remove a task-local data value from the table, returning the
* reference that was originally created to insert it.
*/
#[cfg(not(stage0))]
pub unsafe fn pop<T: 'static>(key: Key<T>) -> Option<T> {
local_pop(Handle::new(), key)
pub fn pop<T: 'static>(key: Key<T>) -> Option<T> {
unsafe { local_pop(Handle::new(), key) }
}
/**
* Retrieve a task-local data value. It will also be kept alive in the
* table until explicitly removed.
*/
#[cfg(stage0)]
pub unsafe fn get<T: 'static, U>(key: Key<@T>, f: &fn(Option<&@T>) -> U) -> U {
local_get(Handle::new(), key, f)
pub fn get<T: 'static, U>(key: Key<@T>, f: &fn(Option<&@T>) -> U) -> U {
unsafe { local_get(Handle::new(), key, f) }
}
/**
* Retrieve a task-local data value. It will also be kept alive in the
* table until explicitly removed.
*/
#[cfg(not(stage0))]
pub unsafe fn get<T: 'static, U>(key: Key<T>, f: &fn(Option<&T>) -> U) -> U {
local_get(Handle::new(), key, f)
pub fn get<T: 'static, U>(key: Key<T>, f: &fn(Option<&T>) -> U) -> U {
unsafe { local_get(Handle::new(), key, f) }
}
/**
* Store a value in task-local data. If this key already has a value,
* that value is overwritten (and its destructor is run).
*/
#[cfg(stage0)]
pub unsafe fn set<T: 'static>(key: Key<@T>, data: @T) {
local_set(Handle::new(), key, data)
pub fn set<T: 'static>(key: Key<@T>, data: @T) {
unsafe { local_set(Handle::new(), key, data) }
}
/**
* Store a value in task-local data. If this key already has a value,
* that value is overwritten (and its destructor is run).
*/
#[cfg(not(stage0))]
pub unsafe fn set<T: 'static>(key: Key<T>, data: T) {
local_set(Handle::new(), key, data)
pub fn set<T: 'static>(key: Key<T>, data: T) {
unsafe { local_set(Handle::new(), key, data) }
}
/**
* Modify a task-local data value. If the function returns 'None', the
* data is removed (and its reference dropped).
*/
#[cfg(stage0)]
pub unsafe fn modify<T: 'static>(key: Key<@T>,
f: &fn(Option<@T>) -> Option<@T>) {
pub fn modify<T: 'static>(key: Key<@T>, f: &fn(Option<@T>) -> Option<@T>) {
match f(pop(key)) {
Some(next) => { set(key, next); }
None => {}
......@@ -127,8 +127,7 @@ pub unsafe fn modify<T: 'static>(key: Key<@T>,
* data is removed (and its reference dropped).
*/
#[cfg(not(stage0))]
pub unsafe fn modify<T: 'static>(key: Key<T>,
f: &fn(Option<T>) -> Option<T>) {
pub fn modify<T: 'static>(key: Key<T>, f: &fn(Option<T>) -> Option<T>) {
match f(pop(key)) {
Some(next) => { set(key, next); }
None => {}
......@@ -137,64 +136,56 @@ pub unsafe fn modify<T: 'static>(key: Key<T>,
#[test]
fn test_tls_multitask() {
unsafe {
fn my_key(_x: @~str) { }
set(my_key, @~"parent data");
do task::spawn {
// TLS shouldn't carry over.
assert!(get(my_key, |k| k.map(|&k| *k)).is_none());
set(my_key, @~"child data");
assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) ==
~"child data");
// should be cleaned up for us
}
// Must work multiple times
assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"parent data");
assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"parent data");
assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"parent data");
static my_key: Key<@~str> = &[];
set(my_key, @~"parent data");
do task::spawn {
// TLS shouldn't carry over.
assert!(get(my_key, |k| k.map(|&k| *k)).is_none());
set(my_key, @~"child data");
assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) ==
~"child data");
// should be cleaned up for us
}
// Must work multiple times
assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"parent data");
assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"parent data");
assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"parent data");
}
#[test]
fn test_tls_overwrite() {
unsafe {
fn my_key(_x: @~str) { }
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");
}
static my_key: Key<@~str> = &[];
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");
}
#[test]
fn test_tls_pop() {
unsafe {
fn my_key(_x: @~str) { }
set(my_key, @~"weasel");
assert!(*(pop(my_key).get()) == ~"weasel");
// Pop must remove the data from the map.
assert!(pop(my_key).is_none());
}
static my_key: Key<@~str> = &[];
set(my_key, @~"weasel");
assert!(*(pop(my_key).get()) == ~"weasel");
// Pop must remove the data from the map.
assert!(pop(my_key).is_none());
}
#[test]
fn test_tls_modify() {
unsafe {
fn my_key(_x: @~str) { }
modify(my_key, |data| {
match data {
Some(@ref val) => fail!("unwelcome value: %s", *val),
None => Some(@~"first data")
}
});
modify(my_key, |data| {
match data {
Some(@~"first data") => Some(@~"next data"),
Some(@ref val) => fail!("wrong value: %s", *val),
None => fail!("missing value")
}
});
assert!(*(pop(my_key).get()) == ~"next data");
}
static my_key: Key<@~str> = &[];
modify(my_key, |data| {
match data {
Some(@ref val) => fail!("unwelcome value: %s", *val),
None => Some(@~"first data")
}
});
modify(my_key, |data| {
match data {
Some(@~"first data") => Some(@~"next data"),
Some(@ref val) => fail!("wrong value: %s", *val),
None => fail!("missing value")
}
});
assert!(*(pop(my_key).get()) == ~"next data");
}
#[test]
......@@ -205,40 +196,36 @@ 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.
fn my_key(_x: @~str) { }
static my_key: Key<@~str> = &[];
do task::spawn {
unsafe { set(my_key, @~"hax"); }
set(my_key, @~"hax");
}
}
#[test]
fn test_tls_multiple_types() {
fn str_key(_x: @~str) { }
fn box_key(_x: @@()) { }
fn int_key(_x: @int) { }
static str_key: Key<@~str> = &[];
static box_key: Key<@@()> = &[];
static int_key: Key<@int> = &[];
do task::spawn {
unsafe {
set(str_key, @~"string data");
set(box_key, @@());
set(int_key, @42);
}
set(str_key, @~"string data");
set(box_key, @@());
set(int_key, @42);
}
}
#[test]
fn test_tls_overwrite_multiple_types() {
fn str_key(_x: @~str) { }
fn box_key(_x: @@()) { }
fn int_key(_x: @int) { }
static str_key: Key<@~str> = &[];
static box_key: Key<@@()> = &[];
static int_key: Key<@int> = &[];
do task::spawn {
unsafe {
set(str_key, @~"string data");
set(int_key, @42);
// This could cause a segfault if overwriting-destruction is done
// with the crazy polymorphic transmute rather than the provided
// finaliser.
set(int_key, @31337);
}
set(str_key, @~"string data");
set(int_key, @42);
// This could cause a segfault if overwriting-destruction is done
// with the crazy polymorphic transmute rather than the provided
// finaliser.
set(int_key, @31337);
}
}
......@@ -246,38 +233,53 @@ fn int_key(_x: @int) { }
#[should_fail]
#[ignore(cfg(windows))]
fn test_tls_cleanup_on_failure() {
unsafe {
fn str_key(_x: @~str) { }
fn box_key(_x: @@()) { }
fn int_key(_x: @int) { }
set(str_key, @~"parent data");
static str_key: Key<@~str> = &[];
static box_key: Key<@@()> = &[];
static int_key: Key<@int> = &[];
set(str_key, @~"parent data");
set(box_key, @@());
do task::spawn {
// spawn_linked
set(str_key, @~"string data");
set(box_key, @@());
do task::spawn {
// spawn_linked
set(str_key, @~"string data");
set(box_key, @@());
set(int_key, @42);
fail!();
}
// Not quite nondeterministic.
set(int_key, @31337);
set(int_key, @42);
fail!();
}
// Not quite nondeterministic.
set(int_key, @31337);
fail!();
}
#[test]
fn test_static_pointer() {
unsafe {
fn key(_x: @&'static int) { }
static VALUE: int = 0;
set(key, @&VALUE);
}
static key: Key<@&'static int> = &[];
static VALUE: int = 0;
let v: @&'static int = @&VALUE;
set(key, v);
}
#[test]
fn test_owned() {
unsafe {
fn key(_x: ~int) { }
set(key, ~1);
}
static key: Key<~int> = &[];
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> = &[];
set(key1, 1);
set(key2, 2);
set(key3, 3);
set(key4, 4);
set(key5, 5);
get(key1, |x| assert_eq!(*x.unwrap(), 1));
get(key2, |x| assert_eq!(*x.unwrap(), 2));
get(key3, |x| assert_eq!(*x.unwrap(), 3));
get(key4, |x| assert_eq!(*x.unwrap(), 4));
get(key5, |x| assert_eq!(*x.unwrap(), 5));
}
......@@ -1239,7 +1239,10 @@ struct OverriddenArgs {
val: ~[~str]
}
#[cfg(stage0)]
fn overridden_arg_key(_v: @OverriddenArgs) {}
#[cfg(not(stage0))]
static overridden_arg_key: local_data::Key<@OverriddenArgs> = &[];
/// Returns the arguments which this program was started with (normally passed
/// via the command line).
......@@ -1247,11 +1250,9 @@ fn overridden_arg_key(_v: @OverriddenArgs) {}
/// The return value of the function can be changed by invoking the
/// `os::set_args` function.
pub fn args() -> ~[~str] {
unsafe {
match local_data::get(overridden_arg_key, |k| k.map(|&k| *k)) {
None => real_args(),
Some(args) => copy args.val
}
match local_data::get(overridden_arg_key, |k| k.map(|&k| *k)) {
None => real_args(),
Some(args) => copy args.val
}
}
......@@ -1259,10 +1260,8 @@ pub fn args() -> ~[~str] {
/// program had when it started. These new arguments are only available to the
/// current task via the `os::args` method.
pub fn set_args(new_args: ~[~str]) {
unsafe {
let overridden_args = @OverriddenArgs { val: copy new_args };
local_data::set(overridden_arg_key, overridden_args);
}
let overridden_args = @OverriddenArgs { val: copy new_args };
local_data::set(overridden_arg_key, overridden_args);
}
// FIXME #6100 we should really use an internal implementation of this - using
......
......@@ -851,7 +851,10 @@ pub fn seed() -> ~[u8] {
}
// used to make space in TLS for a random number generator
#[cfg(stage0)]
fn tls_rng_state(_v: @@mut IsaacRng) {}
#[cfg(not(stage0))]
static tls_rng_state: local_data::Key<@@mut IsaacRng> = &[];
/**
* Gives back a lazily initialized task-local random number generator,
......@@ -860,17 +863,12 @@ fn tls_rng_state(_v: @@mut IsaacRng) {}
*/
#[inline]
pub fn task_rng() -> @mut IsaacRng {
let r : Option<@@mut IsaacRng>;
unsafe {
r = local_data::get(tls_rng_state, |k| k.map(|&k| *k));
}
let r = local_data::get(tls_rng_state, |k| k.map(|&k| *k));
match r {
None => {
unsafe {
let rng = @@mut IsaacRng::new_seeded(seed());
local_data::set(tls_rng_state, rng);
*rng
}
let rng = @@mut IsaacRng::new_seeded(seed());
local_data::set(tls_rng_state, rng);
*rng
}
Some(rng) => *rng
}
......
......@@ -348,14 +348,12 @@ fn local_heap() {
fn tls() {
use local_data;
do run_in_newsched_task() {
unsafe {
fn key(_x: @~str) { }
local_data::set(key, @~"data");
assert!(*local_data::get(key, |k| k.map(|&k| *k)).get() == ~"data");
fn key2(_x: @~str) { }
local_data::set(key2, @~"data");
assert!(*local_data::get(key2, |k| k.map(|&k| *k)).get() == ~"data");
}
static key: local_data::Key<@~str> = &[];
local_data::set(key, @~"data");
assert!(*local_data::get(key, |k| k.map(|&k| *k)).get() == ~"data");
static key2: local_data::Key<@~str> = &[];
local_data::set(key2, @~"data");
assert!(*local_data::get(key2, |k| k.map(|&k| *k)).get() == ~"data");
}
}
......
......@@ -15,9 +15,9 @@
use local_data;
use prelude::*;
use ptr;
use sys;
use task::rt;
use util;
use vec;
use super::rt::rust_task;
use rt::task::{Task, LocalStorage};
......@@ -142,9 +142,8 @@ unsafe fn newsched_map(local: *mut LocalStorage) -> &mut TaskLocalMap {
}
}
unsafe fn key_to_key_value<T: 'static>(key: local_data::Key<T>) -> *libc::c_void {
let pair: sys::Closure = cast::transmute(key);
return pair.code as *libc::c_void;
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;
}
pub unsafe fn local_pop<T: 'static>(handle: Handle,
......
......@@ -20,7 +20,6 @@
use std::int;
use std::num;
use std::option;
use std::cast;
use std::local_data;
pub fn path_name_i(idents: &[ident]) -> ~str {
......@@ -695,18 +694,17 @@ 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 {
unsafe {
let sctable_key = (cast::transmute::<(uint, uint),
&fn:Copy(v: @@mut SCTable)>(
(-4 as uint, 0u)));
match local_data::get(sctable_key, |k| k.map(|&k| *k)) {
None => {
let new_table = @@mut new_sctable_internal();
local_data::set(sctable_key,new_table);
*new_table
},
Some(intr) => *intr
}
#[cfg(not(stage0))]
static sctable_key: local_data::Key<@@mut SCTable> = &[];
#[cfg(stage0)]
fn sctable_key(_: @@mut SCTable) {}
match local_data::get(sctable_key, |k| k.map(|&k| *k)) {
None => {
let new_table = @@mut new_sctable_internal();
local_data::set(sctable_key,new_table);
*new_table
},
Some(intr) => *intr
}
}
......
......@@ -579,11 +579,11 @@ pub fn core_macros() -> @str {
{ pub $c:ident: $in:ty -> $out:ty; } => {
pub mod $c {
fn key(_x: @::std::condition::Handler<$in,$out>) { }
#[allow(non_uppercase_statics)];
static key: &'static [@::std::condition::Handler<$in, $out>] = &[];
#[allow(non_uppercase_statics)]
pub static cond :
::std::condition::Condition<'static,$in,$out> =
::std::condition::Condition<$in,$out> =
::std::condition::Condition {
name: stringify!($c),
key: key
......@@ -595,11 +595,11 @@ fn key(_x: @::std::condition::Handler<$in,$out>) { }
// FIXME (#6009): remove mod's `pub` below once variant above lands.
pub mod $c {
fn key(_x: @::std::condition::Handler<$in,$out>) { }
#[allow(non_uppercase_statics)];
static key: &'static [@::std::condition::Handler<$in, $out>] = &[];
#[allow(non_uppercase_statics)]
pub static cond :
::std::condition::Condition<'static,$in,$out> =
::std::condition::Condition<$in,$out> =
::std::condition::Condition {
name: stringify!($c),
key: key
......
......@@ -15,7 +15,6 @@
use util::interner::StrInterner;
use util::interner;
use std::cast;
use std::cmp::Equiv;
use std::local_data;
use std::rand;
......@@ -485,18 +484,16 @@ fn mk_fresh_ident_interner() -> @ident_interner {
// if an interner exists in TLS, return it. Otherwise, prepare a
// fresh one.
pub fn get_ident_interner() -> @ident_interner {
unsafe {
let key =
(cast::transmute::<(uint, uint),
&fn:Copy(v: @@::parse::token::ident_interner)>(
(-3 as uint, 0u)));
match local_data::get(key, |k| k.map(|&k| *k)) {
Some(interner) => *interner,
None => {
let interner = mk_fresh_ident_interner();
local_data::set(key, @interner);
interner
}
#[cfg(not(stage0))]
static key: local_data::Key<@@::parse::token::ident_interner> = &[];
#[cfg(stage0)]
fn key(_: @@::parse::token::ident_interner) {}
match local_data::get(key, |k| k.map(|&k| *k)) {
Some(interner) => *interner,
None => {
let interner = mk_fresh_ident_interner();
local_data::set(key, @interner);
interner
}
}
}
......
......@@ -12,10 +12,6 @@
use std::local_data;
fn key(_x: @&int) { }
static key: local_data::Key<@&int> = &[]; //~ ERROR only 'static is allowed
fn main() {
unsafe {
local_data::set(key, @&0); //~ ERROR does not fulfill `'static`
}
}
fn main() {}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册