Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
e3211fa1
R
Rust
项目概览
int
/
Rust
接近 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e3211fa1
编写于
7月 12, 2013
作者:
A
Alex Crichton
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Purge the last remnants of the old TLS api
Closes #3273
上级
242606c7
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
291 addition
and
293 deletion
+291
-293
src/libextra/rl.rs
src/libextra/rl.rs
+15
-11
src/libextra/sort.rs
src/libextra/sort.rs
+0
-35
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/base.rs
+18
-23
src/librustc/middle/trans/context.rs
src/librustc/middle/trans/context.rs
+8
-6
src/librusti/program.rs
src/librusti/program.rs
+8
-16
src/libstd/condition.rs
src/libstd/condition.rs
+68
-15
src/libstd/local_data.rs
src/libstd/local_data.rs
+121
-119
src/libstd/os.rs
src/libstd/os.rs
+8
-9
src/libstd/rand.rs
src/libstd/rand.rs
+7
-9
src/libstd/rt/task.rs
src/libstd/rt/task.rs
+6
-8
src/libstd/task/local_data_priv.rs
src/libstd/task/local_data_priv.rs
+3
-4
src/libsyntax/ast_util.rs
src/libsyntax/ast_util.rs
+11
-13
src/libsyntax/ext/expand.rs
src/libsyntax/ext/expand.rs
+6
-6
src/libsyntax/parse/token.rs
src/libsyntax/parse/token.rs
+10
-13
src/test/compile-fail/core-tls-store-pointer.rs
src/test/compile-fail/core-tls-store-pointer.rs
+2
-6
未找到文件。
src/libextra/rl.rs
浏览文件 @
e3211fa1
...
...
@@ -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
);
}
}
}
}
}
}
...
...
src/libextra/sort.rs
浏览文件 @
e3211fa1
...
...
@@ -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
}
}
}
src/librustc/middle/trans/base.rs
浏览文件 @
e3211fa1
...
...
@@ -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
:
()
}
...
...
src/librustc/middle/trans/context.rs
浏览文件 @
e3211fa1
...
...
@@ -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
);
}
src/librusti/program.rs
浏览文件 @
e3211fa1
...
...
@@ -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
;
}
...
...
src/libstd/condition.rs
浏览文件 @
e3211fa1
...
...
@@ -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
)
}
}
}
...
...
src/libstd/local_data.rs
浏览文件 @
e3211fa1
...
...
@@ -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
a
nywhere 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
));
}
src/libstd/os.rs
浏览文件 @
e3211fa1
...
...
@@ -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
...
...
src/libstd/rand.rs
浏览文件 @
e3211fa1
...
...
@@ -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
}
...
...
src/libstd/rt/task.rs
浏览文件 @
e3211fa1
...
...
@@ -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"
);
}
}
...
...
src/libstd/task/local_data_priv.rs
浏览文件 @
e3211fa1
...
...
@@ -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
,
...
...
src/libsyntax/ast_util.rs
浏览文件 @
e3211fa1
...
...
@@ -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
}
}
...
...
src/libsyntax/ext/expand.rs
浏览文件 @
e3211fa1
...
...
@@ -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
...
...
src/libsyntax/parse/token.rs
浏览文件 @
e3211fa1
...
...
@@ -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
}
}
}
...
...
src/test/compile-fail/core-tls-store-pointer.rs
浏览文件 @
e3211fa1
...
...
@@ -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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录