prevent regions from escaping in ifaces; remove &r.T syntax

This commit is contained in:
Niko Matsakis
2012-07-18 11:01:54 -07:00
parent eb0a34c398
commit e0ea67a2a6
36 changed files with 411 additions and 130 deletions

View File

@@ -832,10 +832,10 @@ fn spawn_raw(opts: task_opts, +f: fn~()) {
* types; arbitrary type coercion is possible this way. The interface is safe
* as long as all key functions are monomorphic.
*/
type local_data_key<T> = fn@(+@T);
type local_data_key<T: owned> = fn@(+@T);
iface local_data { }
impl<T> of local_data for @T { }
impl<T: owned> of local_data for @T { }
// We use dvec because it's the best data structure in core. If TLS is used
// heavily in future, this could be made more efficient with a proper map.
@@ -852,6 +852,7 @@ extern fn cleanup_task_local_map(map_ptr: *libc::c_void) unsafe {
// Gets the map from the runtime. Lazily initialises if not done so already.
unsafe fn get_task_local_map(task: *rust_task) -> task_local_map {
// Relies on the runtime initialising the pointer to null.
// NOTE: The map's box lives in TLS invisibly referenced once. Each time
// we retrieve it for get/set, we make another reference, which get/set
@@ -872,7 +873,9 @@ unsafe fn get_task_local_map(task: *rust_task) -> task_local_map {
}
}
unsafe fn key_to_key_value<T>(key: local_data_key<T>) -> *libc::c_void {
unsafe fn key_to_key_value<T: owned>(
key: local_data_key<T>) -> *libc::c_void {
// Keys are closures, which are (fnptr,envptr) pairs. Use fnptr.
// Use reintepret_cast -- transmute would leak (forget) the closure.
let pair: (*libc::c_void, *libc::c_void) = unsafe::reinterpret_cast(key);
@@ -880,8 +883,10 @@ unsafe fn key_to_key_value<T>(key: local_data_key<T>) -> *libc::c_void {
}
// If returning some(..), returns with @T with the map's reference. Careful!
unsafe fn local_data_lookup<T>(map: task_local_map, key: local_data_key<T>)
-> option<(uint, *libc::c_void)> {
unsafe fn local_data_lookup<T: owned>(
map: task_local_map, key: local_data_key<T>)
-> option<(uint, *libc::c_void)> {
let key_value = key_to_key_value(key);
let map_pos = (*map).position(|entry|
alt entry { some((k,_,_)) { k == key_value } none { false } }
@@ -893,8 +898,10 @@ unsafe fn local_data_lookup<T>(map: task_local_map, key: local_data_key<T>)
}
}
unsafe fn local_get_helper<T>(task: *rust_task, key: local_data_key<T>,
do_pop: bool) -> option<@T> {
unsafe fn local_get_helper<T: owned>(
task: *rust_task, key: local_data_key<T>,
do_pop: bool) -> option<@T> {
let map = get_task_local_map(task);
// Interpret our findings from the map
do local_data_lookup(map, key).map |result| {
@@ -912,17 +919,23 @@ unsafe fn local_get_helper<T>(task: *rust_task, key: local_data_key<T>,
}
}
unsafe fn local_pop<T>(task: *rust_task,
key: local_data_key<T>) -> option<@T> {
unsafe fn local_pop<T: owned>(
task: *rust_task,
key: local_data_key<T>) -> option<@T> {
local_get_helper(task, key, true)
}
unsafe fn local_get<T>(task: *rust_task,
key: local_data_key<T>) -> option<@T> {
unsafe fn local_get<T: owned>(
task: *rust_task,
key: local_data_key<T>) -> option<@T> {
local_get_helper(task, key, false)
}
unsafe fn local_set<T>(task: *rust_task, key: local_data_key<T>, +data: @T) {
unsafe fn local_set<T: owned>(
task: *rust_task, key: local_data_key<T>, +data: @T) {
let map = get_task_local_map(task);
// Store key+data as *voids. Data is invisibly referenced once; key isn't.
let keyval = key_to_key_value(key);
@@ -956,8 +969,10 @@ unsafe fn local_set<T>(task: *rust_task, key: local_data_key<T>, +data: @T) {
}
}
unsafe fn local_modify<T>(task: *rust_task, key: local_data_key<T>,
modify_fn: fn(option<@T>) -> option<@T>) {
unsafe fn local_modify<T: owned>(
task: *rust_task, key: local_data_key<T>,
modify_fn: fn(option<@T>) -> option<@T>) {
// Could be more efficient by doing the lookup work, but this is easy.
let newdata = modify_fn(local_pop(task, key));
if newdata.is_some() {
@@ -970,29 +985,37 @@ unsafe fn local_modify<T>(task: *rust_task, key: local_data_key<T>,
* Remove a task-local data value from the table, returning the
* reference that was originally created to insert it.
*/
unsafe fn local_data_pop<T>(key: local_data_key<T>) -> option<@T> {
unsafe fn local_data_pop<T: owned>(
key: local_data_key<T>) -> option<@T> {
local_pop(rustrt::rust_get_task(), key)
}
/**
* Retrieve a task-local data value. It will also be kept alive in the
* table until explicitly removed.
*/
unsafe fn local_data_get<T>(key: local_data_key<T>) -> option<@T> {
unsafe fn local_data_get<T: owned>(
key: local_data_key<T>) -> option<@T> {
local_get(rustrt::rust_get_task(), key)
}
/**
* Store a value in task-local data. If this key already has a value,
* that value is overwritten (and its destructor is run).
*/
unsafe fn local_data_set<T>(key: local_data_key<T>, +data: @T) {
unsafe fn local_data_set<T: owned>(
key: local_data_key<T>, +data: @T) {
local_set(rustrt::rust_get_task(), key, data)
}
/**
* Modify a task-local data value. If the function returns 'none', the
* data is removed (and its reference dropped).
*/
unsafe fn local_data_modify<T>(key: local_data_key<T>,
modify_fn: fn(option<@T>) -> option<@T>) {
unsafe fn local_data_modify<T: owned>(
key: local_data_key<T>,
modify_fn: fn(option<@T>) -> option<@T>) {
local_modify(rustrt::rust_get_task(), key, modify_fn)
}