diff options
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/condition.rs | 83 | ||||
| -rw-r--r-- | src/libstd/local_data.rs | 262 | ||||
| -rw-r--r-- | src/libstd/os.rs | 17 | ||||
| -rw-r--r-- | src/libstd/rand.rs | 16 | ||||
| -rw-r--r-- | src/libstd/rt/task.rs | 14 | ||||
| -rw-r--r-- | src/libstd/std.rs | 1 | ||||
| -rw-r--r-- | src/libstd/task/local_data_priv.rs | 6 | ||||
| -rw-r--r-- | src/libstd/task/spawn.rs | 19 |
8 files changed, 236 insertions, 182 deletions
diff --git a/src/libstd/condition.rs b/src/libstd/condition.rs index d6d09527f83..3a5be12b3c5 100644 --- a/src/libstd/condition.rs +++ b/src/libstd/condition.rs @@ -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 @@ impl<'self, T, U> Condition<'self, T, 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) } } } diff --git a/src/libstd/local_data.rs b/src/libstd/local_data.rs index b241de88700..be170cce07e 100644 --- a/src/libstd/local_data.rs +++ b/src/libstd/local_data.rs @@ -12,27 +12,26 @@ 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 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 monomorphic (no type parameters) global function at the type -to store, and use it as the 'key' when accessing. +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; -fn key_int(_: @int) {} -fn key_vector(_: @~[int]) {} +static key_int: local_data::Key<int> = &local_data::Key; +static key_vector: local_data::Key<~[int]> = &local_data::Key; -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 @@ -47,76 +46,77 @@ 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. - * - * 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). + * 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. * - * 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 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. */ #[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> = &Key; + 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> = &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"); } #[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> = &Key; + 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> = &Key; + 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> = &Key; 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> = &Key; + static box_key: Key<@@()> = &Key; + static int_key: Key<@int> = &Key; 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> = &Key; + static box_key: Key<@@()> = &Key; + static int_key: Key<@int> = &Key; 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 test_tls_overwrite_multiple_types() { #[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> = &Key; + static box_key: Key<@@()> = &Key; + static int_key: Key<@int> = &Key; + 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> = &Key; + 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> = &Key; + set(key, ~1); +} + +#[test] +fn test_same_key_type() { + 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); + 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)); } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 8d70732641d..58175db1241 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -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> = &local_data::Key; /// 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 diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs index 2cf45ba70ec..6f89e7ffb07 100644 --- a/src/libstd/rand.rs +++ b/src/libstd/rand.rs @@ -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> = &local_data::Key; /** * 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 } diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index c5961be40ec..17d0d59660f 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -348,14 +348,12 @@ mod test { 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::Key; + 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::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 42cfcbc16db..d46e5707f14 100644 --- a/src/libstd/task/local_data_priv.rs +++ b/src/libstd/task/local_data_priv.rs @@ -15,7 +15,6 @@ use libc; use local_data; use prelude::*; use ptr; -use sys; use task::rt; use util; @@ -142,9 +141,8 @@ unsafe fn get_local_map(handle: Handle) -> &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 { + 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. |
