// magic.
use cast;
-use option::{None, Option, Some};
-use vec::{ImmutableVector, MutableVector, OwnedVector};
use iter::{Iterator};
-use rt::task::{Task, LocalStorage};
+use kinds::Send;
use mem::replace;
+use option::{None, Option, Some};
+use rt::task::{Task, LocalStorage};
+use slice::{ImmutableVector, MutableVector};
+use vec::Vec;
/**
* Indexes a task-local data slot. This pointer is used for comparison to
// n.b. If TLS is used heavily in future, this could be made more efficient with
// a proper map.
#[doc(hidden)]
-pub type Map = ~[Option<(*u8, TLSValue, LoanState)>];
-type TLSValue = ~LocalData;
+pub type Map = Vec<Option<(*u8, TLSValue, LoanState)>>;
+type TLSValue = ~LocalData:Send;
// Gets the map from the runtime. Lazily initialises if not done so already.
unsafe fn get_local_map() -> &mut Map {
// If this is the first time we've accessed TLS, perform similar
// actions to the oldsched way of doing things.
&LocalStorage(ref mut slot) => {
- *slot = Some(~[]);
+ *slot = Some(vec!());
match *slot {
Some(ref mut map_ptr) => { return map_ptr }
None => abort()
Some(i) => {
let ret;
let mut return_loan = false;
- match map[i] {
+ match *map.get_mut(i) {
Some((_, ref data, ref mut loan)) => {
match (state, *loan) {
(_, NoLoan) => {
// in turn relocated the vector. Hence we do another lookup here to
// fixup the loans.
if return_loan {
- match map[i] {
+ match *map.get_mut(i) {
Some((_, _, ref mut loan)) => { *loan = NoLoan; }
None => abort()
}
// transmute here to add the Send bound back on. This doesn't actually
// matter because TLS will always own the data (until its moved out) and
// we're not actually sending it to other schedulers or anything.
- let data: ~LocalData = unsafe { cast::transmute(data) };
+ let data: ~LocalData:Send = unsafe { cast::transmute(data) };
match insertion_position(map, keyval) {
- Some(i) => { map[i] = Some((keyval, data, NoLoan)); }
+ Some(i) => { *map.get_mut(i) = Some((keyval, data, NoLoan)); }
None => { map.push(Some((keyval, data, NoLoan))); }
}
}
use prelude::*;
use super::*;
use task;
+ use str::StrSlice;
#[test]
fn test_tls_multitask() {
static my_key: Key<~str> = &Key;
- set(my_key, ~"parent data");
+ set(my_key, "parent data".to_owned());
task::spawn(proc() {
// TLS shouldn't carry over.
assert!(get(my_key, |k| k.map(|k| (*k).clone())).is_none());
- set(my_key, ~"child data");
+ set(my_key, "child data".to_owned());
assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() ==
- ~"child data");
+ "child data".to_owned());
// should be cleaned up for us
});
// Must work multiple times
- assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() == ~"parent data");
- assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() == ~"parent data");
- assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() == ~"parent data");
+ assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() == "parent data".to_owned());
+ assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() == "parent data".to_owned());
+ assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() == "parent data".to_owned());
}
#[test]
fn test_tls_overwrite() {
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).clone())).unwrap() == ~"next data");
+ set(my_key, "first data".to_owned());
+ set(my_key, "next data".to_owned()); // Shouldn't leak.
+ assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() == "next data".to_owned());
}
#[test]
fn test_tls_pop() {
static my_key: Key<~str> = &Key;
- set(my_key, ~"weasel");
- assert!(pop(my_key).unwrap() == ~"weasel");
+ set(my_key, "weasel".to_owned());
+ assert!(pop(my_key).unwrap() == "weasel".to_owned());
// Pop must remove the data from the map.
assert!(pop(my_key).is_none());
}
modify(my_key, |data| {
match data {
Some(ref val) => fail!("unwelcome value: {}", *val),
- None => Some(~"first data")
+ None => Some("first data".to_owned())
}
});
modify(my_key, |data| {
match data.as_ref().map(|s| s.as_slice()) {
- Some("first data") => Some(~"next data"),
+ Some("first data") => Some("next data".to_owned()),
Some(ref val) => fail!("wrong value: {}", *val),
None => fail!("missing value")
}
});
- assert!(pop(my_key).unwrap() == ~"next data");
+ assert!(pop(my_key).unwrap() == "next data".to_owned());
}
#[test]
// a stack smaller than 1 MB.
static my_key: Key<~str> = &Key;
task::spawn(proc() {
- set(my_key, ~"hax");
+ set(my_key, "hax".to_owned());
});
}
static box_key: Key<@()> = &Key;
static int_key: Key<int> = &Key;
task::spawn(proc() {
- set(str_key, ~"string data");
+ set(str_key, "string data".to_owned());
set(box_key, @());
set(int_key, 42);
});
static box_key: Key<@()> = &Key;
static int_key: Key<int> = &Key;
task::spawn(proc() {
- set(str_key, ~"string data");
- set(str_key, ~"string data 2");
+ set(str_key, "string data".to_owned());
+ set(str_key, "string data 2".to_owned());
set(box_key, @());
set(box_key, @());
set(int_key, 42);
static str_key: Key<~str> = &Key;
static box_key: Key<@()> = &Key;
static int_key: Key<int> = &Key;
- set(str_key, ~"parent data");
+ set(str_key, "parent data".to_owned());
set(box_key, @());
task::spawn(proc() {
// spawn_linked
- set(str_key, ~"string data");
+ set(str_key, "string data".to_owned());
set(box_key, @());
set(int_key, 42);
fail!();