Rename local_data methods/types for less keystrokes
This commit is contained in:
parent
5c3a2e7eeb
commit
cb5b9a477c
12 changed files with 94 additions and 84 deletions
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#[allow(missing_doc)];
|
||||
|
||||
use local_data::{local_data_pop, local_data_set};
|
||||
use local_data;
|
||||
use prelude::*;
|
||||
|
||||
|
|
@ -26,14 +25,14 @@ pub struct Handler<T, U> {
|
|||
|
||||
pub struct Condition<'self, T, U> {
|
||||
name: &'static str,
|
||||
key: local_data::LocalDataKey<'self, @Handler<T, U>>
|
||||
key: local_data::Key<'self, @Handler<T, U>>
|
||||
}
|
||||
|
||||
impl<'self, T, U> Condition<'self, T, U> {
|
||||
pub fn trap(&'self self, h: &'self fn(T) -> U) -> Trap<'self, T, U> {
|
||||
unsafe {
|
||||
let p : *RustClosure = ::cast::transmute(&h);
|
||||
let prev = local_data::local_data_get(self.key);
|
||||
let prev = local_data::get(self.key);
|
||||
let h = @Handler { handle: *p, prev: prev };
|
||||
Trap { cond: self, handler: h }
|
||||
}
|
||||
|
|
@ -46,7 +45,7 @@ impl<'self, T, U> Condition<'self, T, U> {
|
|||
|
||||
pub fn raise_default(&self, t: T, default: &fn() -> U) -> U {
|
||||
unsafe {
|
||||
match local_data_pop(self.key) {
|
||||
match local_data::pop(self.key) {
|
||||
None => {
|
||||
debug!("Condition.raise: found no handler");
|
||||
default()
|
||||
|
|
@ -55,12 +54,12 @@ impl<'self, T, U> Condition<'self, T, U> {
|
|||
debug!("Condition.raise: found handler");
|
||||
match handler.prev {
|
||||
None => {}
|
||||
Some(hp) => local_data_set(self.key, hp)
|
||||
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);
|
||||
local_data::set(self.key, handler);
|
||||
u
|
||||
}
|
||||
}
|
||||
|
|
@ -78,7 +77,7 @@ impl<'self, T, U> Trap<'self, T, U> {
|
|||
unsafe {
|
||||
let _g = Guard { cond: self.cond };
|
||||
debug!("Trap: pushing handler to TLS");
|
||||
local_data_set(self.cond.key, self.handler);
|
||||
local_data::set(self.cond.key, self.handler);
|
||||
inner()
|
||||
}
|
||||
}
|
||||
|
|
@ -93,12 +92,12 @@ 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);
|
||||
let curr = local_data::pop(self.cond.key);
|
||||
match curr {
|
||||
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,14 +12,28 @@
|
|||
|
||||
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 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.
|
||||
|
||||
To use, declare a monomorphic global function at the type to store,
|
||||
and use it as the 'key' when accessing. See the 'tls' tests below for
|
||||
examples.
|
||||
To use, declare a monomorphic (no type parameters) global function at the type
|
||||
to store, and use it as the 'key' when accessing.
|
||||
|
||||
~~~{.rust}
|
||||
use std::local_data;
|
||||
|
||||
fn key_int(_: @int) {}
|
||||
fn key_vector(_: @~[int]) {}
|
||||
|
||||
unsafe {
|
||||
local_data::set(key_int, @3);
|
||||
assert!(local_data::get(key_int) == Some(@3));
|
||||
|
||||
local_data::set(key_vector, @~[3]);
|
||||
assert!(local_data::get(key_vector).unwrap()[0] == 3);
|
||||
}
|
||||
~~~
|
||||
|
||||
Casting 'Arcane Sight' reveals an overwhelming aura of Transmutation
|
||||
magic.
|
||||
|
|
@ -46,40 +60,37 @@ use task::local_data_priv::{local_get, local_pop, local_set, Handle};
|
|||
*
|
||||
* These two cases aside, the interface is safe.
|
||||
*/
|
||||
pub type LocalDataKey<'self,T> = &'self fn:Copy(v: T);
|
||||
pub type Key<'self,T> = &'self fn:Copy(v: T);
|
||||
|
||||
/**
|
||||
* Remove a task-local data value from the table, returning the
|
||||
* reference that was originally created to insert it.
|
||||
*/
|
||||
pub unsafe fn local_data_pop<T: 'static>(key: LocalDataKey<T>) -> Option<T> {
|
||||
pub unsafe fn pop<T: 'static>(key: Key<T>) -> Option<T> {
|
||||
local_pop(Handle::new(), key)
|
||||
}
|
||||
/**
|
||||
* Retrieve a task-local data value. It will also be kept alive in the
|
||||
* table until explicitly removed.
|
||||
*/
|
||||
pub unsafe fn local_data_get<T: 'static>(key: LocalDataKey<@T>) -> Option<@T> {
|
||||
pub unsafe fn get<T: 'static>(key: Key<@T>) -> Option<@T> {
|
||||
local_get(Handle::new(), key, |loc| loc.map(|&x| *x))
|
||||
}
|
||||
/**
|
||||
* Store a value in task-local data. If this key already has a value,
|
||||
* that value is overwritten (and its destructor is run).
|
||||
*/
|
||||
pub unsafe fn local_data_set<T: 'static>(key: LocalDataKey<@T>, data: @T) {
|
||||
pub unsafe fn set<T: 'static>(key: Key<@T>, data: @T) {
|
||||
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).
|
||||
*/
|
||||
pub unsafe fn local_data_modify<T: 'static>(
|
||||
key: LocalDataKey<@T>,
|
||||
modify_fn: &fn(Option<@T>) -> Option<@T>) {
|
||||
|
||||
let cur = local_data_pop(key);
|
||||
match modify_fn(cur) {
|
||||
Some(next) => { local_data_set(key, next); }
|
||||
pub unsafe fn modify<T: 'static>(key: Key<@T>,
|
||||
f: &fn(Option<@T>) -> Option<@T>) {
|
||||
match f(pop(key)) {
|
||||
Some(next) => { set(key, next); }
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -88,19 +99,19 @@ pub unsafe fn local_data_modify<T: 'static>(
|
|||
fn test_tls_multitask() {
|
||||
unsafe {
|
||||
fn my_key(_x: @~str) { }
|
||||
local_data_set(my_key, @~"parent data");
|
||||
set(my_key, @~"parent data");
|
||||
do task::spawn {
|
||||
// TLS shouldn't carry over.
|
||||
assert!(local_data_get(my_key).is_none());
|
||||
local_data_set(my_key, @~"child data");
|
||||
assert!(*(local_data_get(my_key).get()) ==
|
||||
assert!(get(my_key).is_none());
|
||||
set(my_key, @~"child data");
|
||||
assert!(*(get(my_key).get()) ==
|
||||
~"child data");
|
||||
// should be cleaned up for us
|
||||
}
|
||||
// Must work multiple times
|
||||
assert!(*(local_data_get(my_key).get()) == ~"parent data");
|
||||
assert!(*(local_data_get(my_key).get()) == ~"parent data");
|
||||
assert!(*(local_data_get(my_key).get()) == ~"parent data");
|
||||
assert!(*(get(my_key).get()) == ~"parent data");
|
||||
assert!(*(get(my_key).get()) == ~"parent data");
|
||||
assert!(*(get(my_key).get()) == ~"parent data");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,9 +119,9 @@ fn test_tls_multitask() {
|
|||
fn test_tls_overwrite() {
|
||||
unsafe {
|
||||
fn my_key(_x: @~str) { }
|
||||
local_data_set(my_key, @~"first data");
|
||||
local_data_set(my_key, @~"next data"); // Shouldn't leak.
|
||||
assert!(*(local_data_get(my_key).get()) == ~"next data");
|
||||
set(my_key, @~"first data");
|
||||
set(my_key, @~"next data"); // Shouldn't leak.
|
||||
assert!(*(get(my_key).get()) == ~"next data");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -118,10 +129,10 @@ fn test_tls_overwrite() {
|
|||
fn test_tls_pop() {
|
||||
unsafe {
|
||||
fn my_key(_x: @~str) { }
|
||||
local_data_set(my_key, @~"weasel");
|
||||
assert!(*(local_data_pop(my_key).get()) == ~"weasel");
|
||||
set(my_key, @~"weasel");
|
||||
assert!(*(pop(my_key).get()) == ~"weasel");
|
||||
// Pop must remove the data from the map.
|
||||
assert!(local_data_pop(my_key).is_none());
|
||||
assert!(pop(my_key).is_none());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -129,20 +140,20 @@ fn test_tls_pop() {
|
|||
fn test_tls_modify() {
|
||||
unsafe {
|
||||
fn my_key(_x: @~str) { }
|
||||
local_data_modify(my_key, |data| {
|
||||
modify(my_key, |data| {
|
||||
match data {
|
||||
Some(@ref val) => fail!("unwelcome value: %s", *val),
|
||||
None => Some(@~"first data")
|
||||
}
|
||||
});
|
||||
local_data_modify(my_key, |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!(*(local_data_pop(my_key).get()) == ~"next data");
|
||||
assert!(*(pop(my_key).get()) == ~"next data");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +167,7 @@ fn test_tls_crust_automorestack_memorial_bug() {
|
|||
// a stack smaller than 1 MB.
|
||||
fn my_key(_x: @~str) { }
|
||||
do task::spawn {
|
||||
unsafe { local_data_set(my_key, @~"hax"); }
|
||||
unsafe { set(my_key, @~"hax"); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -167,9 +178,9 @@ fn test_tls_multiple_types() {
|
|||
fn int_key(_x: @int) { }
|
||||
do task::spawn {
|
||||
unsafe {
|
||||
local_data_set(str_key, @~"string data");
|
||||
local_data_set(box_key, @@());
|
||||
local_data_set(int_key, @42);
|
||||
set(str_key, @~"string data");
|
||||
set(box_key, @@());
|
||||
set(int_key, @42);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -181,12 +192,12 @@ fn test_tls_overwrite_multiple_types() {
|
|||
fn int_key(_x: @int) { }
|
||||
do task::spawn {
|
||||
unsafe {
|
||||
local_data_set(str_key, @~"string data");
|
||||
local_data_set(int_key, @42);
|
||||
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.
|
||||
local_data_set(int_key, @31337);
|
||||
set(int_key, @31337);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -199,17 +210,17 @@ fn test_tls_cleanup_on_failure() {
|
|||
fn str_key(_x: @~str) { }
|
||||
fn box_key(_x: @@()) { }
|
||||
fn int_key(_x: @int) { }
|
||||
local_data_set(str_key, @~"parent data");
|
||||
local_data_set(box_key, @@());
|
||||
set(str_key, @~"parent data");
|
||||
set(box_key, @@());
|
||||
do task::spawn {
|
||||
// spawn_linked
|
||||
local_data_set(str_key, @~"string data");
|
||||
local_data_set(box_key, @@());
|
||||
local_data_set(int_key, @42);
|
||||
set(str_key, @~"string data");
|
||||
set(box_key, @@());
|
||||
set(int_key, @42);
|
||||
fail!();
|
||||
}
|
||||
// Not quite nondeterministic.
|
||||
local_data_set(int_key, @31337);
|
||||
set(int_key, @31337);
|
||||
fail!();
|
||||
}
|
||||
}
|
||||
|
|
@ -219,6 +230,6 @@ fn test_static_pointer() {
|
|||
unsafe {
|
||||
fn key(_x: @&'static int) { }
|
||||
static VALUE: int = 0;
|
||||
local_data_set(key, @&VALUE);
|
||||
set(key, @&VALUE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1230,7 +1230,7 @@ fn overridden_arg_key(_v: @OverriddenArgs) {}
|
|||
/// `os::set_args` function.
|
||||
pub fn args() -> ~[~str] {
|
||||
unsafe {
|
||||
match local_data::local_data_get(overridden_arg_key) {
|
||||
match local_data::get(overridden_arg_key) {
|
||||
None => real_args(),
|
||||
Some(args) => copy args.val
|
||||
}
|
||||
|
|
@ -1243,7 +1243,7 @@ pub fn args() -> ~[~str] {
|
|||
pub fn set_args(new_args: ~[~str]) {
|
||||
unsafe {
|
||||
let overridden_args = @OverriddenArgs { val: copy new_args };
|
||||
local_data::local_data_set(overridden_arg_key, overridden_args);
|
||||
local_data::set(overridden_arg_key, overridden_args);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -850,13 +850,13 @@ fn tls_rng_state(_v: @@mut IsaacRng) {}
|
|||
pub fn task_rng() -> @mut IsaacRng {
|
||||
let r : Option<@@mut IsaacRng>;
|
||||
unsafe {
|
||||
r = local_data::local_data_get(tls_rng_state);
|
||||
r = local_data::get(tls_rng_state);
|
||||
}
|
||||
match r {
|
||||
None => {
|
||||
unsafe {
|
||||
let rng = @@mut IsaacRng::new_seeded(seed());
|
||||
local_data::local_data_set(tls_rng_state, rng);
|
||||
local_data::set(tls_rng_state, rng);
|
||||
*rng
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
use cast;
|
||||
use libc;
|
||||
use local_data::LocalDataKey;
|
||||
use local_data;
|
||||
use managed::raw::BoxRepr;
|
||||
use prelude::*;
|
||||
use ptr;
|
||||
|
|
@ -131,7 +131,7 @@ unsafe fn get_local_map(handle: Handle) -> &mut TaskLocalMap {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn key_to_key_value<T: 'static>(key: LocalDataKey<T>) -> *libc::c_void {
|
||||
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;
|
||||
}
|
||||
|
|
@ -155,7 +155,7 @@ unsafe fn transmute_back<'a, T>(data: &'a TLSValue) -> (*BoxRepr, &'a T) {
|
|||
}
|
||||
|
||||
pub unsafe fn local_pop<T: 'static>(handle: Handle,
|
||||
key: LocalDataKey<T>) -> Option<T> {
|
||||
key: local_data::Key<T>) -> Option<T> {
|
||||
// If you've never seen horrendously unsafe code written in rust before,
|
||||
// just feel free to look a bit farther...
|
||||
let map = get_local_map(handle);
|
||||
|
|
@ -203,7 +203,7 @@ pub unsafe fn local_pop<T: 'static>(handle: Handle,
|
|||
}
|
||||
|
||||
pub unsafe fn local_get<T: 'static, U>(handle: Handle,
|
||||
key: LocalDataKey<T>,
|
||||
key: local_data::Key<T>,
|
||||
f: &fn(Option<&T>) -> U) -> U {
|
||||
// This does in theory take multiple mutable loans on the tls map, but the
|
||||
// references returned are never removed because the map is only increasing
|
||||
|
|
@ -227,7 +227,7 @@ pub unsafe fn local_get<T: 'static, U>(handle: Handle,
|
|||
|
||||
// FIXME(#7673): This shouldn't require '@', it should use '~'
|
||||
pub unsafe fn local_set<T: 'static>(handle: Handle,
|
||||
key: LocalDataKey<@T>,
|
||||
key: local_data::Key<@T>,
|
||||
data: @T) {
|
||||
let map = get_local_map(handle);
|
||||
let keyval = key_to_key_value(key);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue