Skip to content

Commit 8aaf282

Browse files
committed
---
yaml --- r: 81059 b: refs/heads/snap-stage3 c: 5500d86 h: refs/heads/master i: 81057: a1fc152 81055: c7312a0 v: v3
1 parent 4ef2e23 commit 8aaf282

File tree

149 files changed

+2931
-2856
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

149 files changed

+2931
-2856
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: 4c6bf4872012c010f84dc7fa2cdfe87522533f89
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: d062de8aa48083439237cb338b38c25306bf6c94
4+
refs/heads/snap-stage3: 5500d86b457e1815941d4adb2d8bbc91f3c8c9b2
55
refs/heads/try: 70152ff55722878cde684ee6462c14c65f2c4729
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/doc/tutorial.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,34 @@ cannot be stored in data structures or returned from
14691469
functions. Despite these limitations, stack closures are used
14701470
pervasively in Rust code.
14711471

1472+
## Managed closures
1473+
1474+
When you need to store a closure in a data structure, a stack closure
1475+
will not do, since the compiler will refuse to let you store it. For
1476+
this purpose, Rust provides a type of closure that has an arbitrary
1477+
lifetime, written `@fn` (boxed closure, analogous to the `@` pointer
1478+
type described earlier). This type of closure *is* first-class.
1479+
1480+
A managed closure does not directly access its environment, but merely
1481+
copies out the values that it closes over into a private data
1482+
structure. This means that it can not assign to these variables, and
1483+
cannot observe updates to them.
1484+
1485+
This code creates a closure that adds a given string to its argument,
1486+
returns it from a function, and then calls it:
1487+
1488+
~~~~
1489+
fn mk_appender(suffix: ~str) -> @fn(~str) -> ~str {
1490+
// The compiler knows that we intend this closure to be of type @fn
1491+
return |s| s + suffix;
1492+
}
1493+
1494+
fn main() {
1495+
let shout = mk_appender(~"!");
1496+
println(shout(~"hey ho, let's go"));
1497+
}
1498+
~~~~
1499+
14721500
## Owned closures
14731501

14741502
Owned closures, written `~fn` in analogy to the `~` pointer type,

branches/snap-stage3/src/libextra/c_vec.rs

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -36,39 +36,37 @@
3636
* still held if needed.
3737
*/
3838

39+
40+
use std::option;
3941
use std::ptr;
40-
use std::routine::Runnable;
41-
use std::util;
4242

4343
/**
4444
* The type representing a foreign chunk of memory
45+
*
4546
*/
4647
pub struct CVec<T> {
4748
priv base: *mut T,
4849
priv len: uint,
49-
priv rsrc: @DtorRes,
50+
priv rsrc: @DtorRes
5051
}
5152

5253
struct DtorRes {
53-
dtor: Option<~Runnable>,
54+
dtor: Option<@fn()>,
5455
}
5556

5657
#[unsafe_destructor]
5758
impl Drop for DtorRes {
5859
fn drop(&mut self) {
59-
let dtor = util::replace(&mut self.dtor, None);
60-
match dtor {
61-
None => (),
62-
Some(f) => f.run()
60+
match self.dtor {
61+
option::None => (),
62+
option::Some(f) => f()
6363
}
6464
}
6565
}
6666

67-
impl DtorRes {
68-
fn new(dtor: Option<~Runnable>) -> DtorRes {
69-
DtorRes {
70-
dtor: dtor,
71-
}
67+
fn DtorRes(dtor: Option<@fn()>) -> DtorRes {
68+
DtorRes {
69+
dtor: dtor
7270
}
7371
}
7472

@@ -85,10 +83,10 @@ impl DtorRes {
8583
* * len - The number of elements in the buffer
8684
*/
8785
pub unsafe fn CVec<T>(base: *mut T, len: uint) -> CVec<T> {
88-
return CVec {
86+
return CVec{
8987
base: base,
9088
len: len,
91-
rsrc: @DtorRes::new(None)
89+
rsrc: @DtorRes(option::None)
9290
};
9391
}
9492

@@ -103,12 +101,12 @@ pub unsafe fn CVec<T>(base: *mut T, len: uint) -> CVec<T> {
103101
* * dtor - A function to run when the value is destructed, useful
104102
* for freeing the buffer, etc.
105103
*/
106-
pub unsafe fn c_vec_with_dtor<T>(base: *mut T, len: uint, dtor: ~Runnable)
107-
-> CVec<T> {
104+
pub unsafe fn c_vec_with_dtor<T>(base: *mut T, len: uint, dtor: @fn())
105+
-> CVec<T> {
108106
return CVec{
109107
base: base,
110108
len: len,
111-
rsrc: @DtorRes::new(Some(dtor))
109+
rsrc: @DtorRes(option::Some(dtor))
112110
};
113111
}
114112

@@ -155,20 +153,6 @@ mod tests {
155153

156154
use std::libc::*;
157155
use std::libc;
158-
use std::routine::Runnable;
159-
160-
struct LibcFree {
161-
mem: *c_void,
162-
}
163-
164-
impl Runnable for LibcFree {
165-
#[fixed_stack_segment]
166-
fn run(~self) {
167-
unsafe {
168-
libc::free(self.mem)
169-
}
170-
}
171-
}
172156

173157
fn malloc(n: size_t) -> CVec<u8> {
174158
#[fixed_stack_segment];
@@ -179,11 +163,12 @@ mod tests {
179163

180164
assert!(mem as int != 0);
181165

182-
return c_vec_with_dtor(mem as *mut u8,
183-
n as uint,
184-
~LibcFree {
185-
mem: mem,
186-
} as ~Runnable);
166+
return c_vec_with_dtor(mem as *mut u8, n as uint, || f(mem));
167+
}
168+
169+
fn f(mem: *c_void) {
170+
#[fixed_stack_segment]; #[inline(never)];
171+
unsafe { libc::free(mem) }
187172
}
188173
}
189174

branches/snap-stage3/src/libextra/rl.rs

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub mod rustrt {
3030

3131
macro_rules! locked {
3232
($expr:expr) => {
33-
{
33+
unsafe {
3434
// FIXME #9105: can't use a static mutex in pure Rust yet.
3535
rustrt::rust_take_linenoise_lock();
3636
let x = $expr;
@@ -43,46 +43,35 @@ macro_rules! locked {
4343
/// Add a line to history
4444
pub fn add_history(line: &str) -> bool {
4545
do line.with_c_str |buf| {
46-
unsafe {
47-
(locked!(rustrt::linenoiseHistoryAdd(buf))) == 1 as c_int
48-
}
46+
(locked!(rustrt::linenoiseHistoryAdd(buf))) == 1 as c_int
4947
}
5048
}
5149

5250
/// Set the maximum amount of lines stored
5351
pub fn set_history_max_len(len: int) -> bool {
54-
unsafe {
55-
(locked!(rustrt::linenoiseHistorySetMaxLen(len as c_int))) == 1
56-
as c_int
57-
}
52+
(locked!(rustrt::linenoiseHistorySetMaxLen(len as c_int))) == 1 as c_int
5853
}
5954

6055
/// Save line history to a file
6156
pub fn save_history(file: &str) -> bool {
6257
do file.with_c_str |buf| {
6358
// 0 on success, -1 on failure
64-
unsafe {
65-
(locked!(rustrt::linenoiseHistorySave(buf))) == 0 as c_int
66-
}
59+
(locked!(rustrt::linenoiseHistorySave(buf))) == 0 as c_int
6760
}
6861
}
6962

7063
/// Load line history from a file
7164
pub fn load_history(file: &str) -> bool {
7265
do file.with_c_str |buf| {
7366
// 0 on success, -1 on failure
74-
unsafe {
75-
(locked!(rustrt::linenoiseHistoryLoad(buf))) == 0 as c_int
76-
}
67+
(locked!(rustrt::linenoiseHistoryLoad(buf))) == 0 as c_int
7768
}
7869
}
7970

8071
/// Print out a prompt and then wait for input and return it
8172
pub fn read(prompt: &str) -> Option<~str> {
8273
do prompt.with_c_str |buf| {
83-
let line = unsafe {
84-
locked!(rustrt::linenoise(buf))
85-
};
74+
let line = locked!(rustrt::linenoise(buf));
8675

8776
if line.is_null() { None }
8877
else {
@@ -99,36 +88,35 @@ pub fn read(prompt: &str) -> Option<~str> {
9988
}
10089
}
10190

102-
/// The callback used to perform completions.
103-
pub trait CompletionCb {
104-
/// Performs a completion.
105-
fn complete(&self, line: ~str, suggestion: &fn(~str));
106-
}
91+
pub type CompletionCb = @fn(~str, @fn(~str));
10792

108-
local_data_key!(complete_key: @CompletionCb)
93+
local_data_key!(complete_key: CompletionCb)
10994

11095
/// Bind to the main completion callback in the current task.
11196
///
11297
/// The completion callback should not call any `extra::rl` functions
11398
/// other than the closure that it receives as its second
11499
/// argument. Calling such a function will deadlock on the mutex used
115100
/// to ensure that the calls are thread-safe.
116-
pub unsafe fn complete(cb: @CompletionCb) {
101+
pub fn complete(cb: CompletionCb) {
117102
local_data::set(complete_key, cb);
118103

119-
extern fn callback(line: *c_char, completions: *()) {
104+
extern fn callback(c_line: *c_char, completions: *()) {
120105
do local_data::get(complete_key) |opt_cb| {
121106
// only fetch completions if a completion handler has been
122107
// registered in the current task.
123108
match opt_cb {
124-
None => {}
109+
None => {},
125110
Some(cb) => {
126-
unsafe {
127-
do cb.complete(str::raw::from_c_str(line))
128-
|suggestion| {
129-
do suggestion.with_c_str |buf| {
130-
rustrt::linenoiseAddCompletion(completions,
131-
buf);
111+
let line = unsafe { str::raw::from_c_str(c_line) };
112+
do (*cb)(line) |suggestion| {
113+
do suggestion.with_c_str |buf| {
114+
// This isn't locked, because `callback` gets
115+
// called inside `rustrt::linenoise`, which
116+
// *is* already inside the mutex, so
117+
// re-locking would be a deadlock.
118+
unsafe {
119+
rustrt::linenoiseAddCompletion(completions, buf);
132120
}
133121
}
134122
}

branches/snap-stage3/src/libextra/test.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,11 @@ pub fn filter_tests(
807807
}
808808
}
809809

810+
struct TestFuture {
811+
test: TestDesc,
812+
wait: @fn() -> TestResult,
813+
}
814+
810815
pub fn run_test(force_ignore: bool,
811816
test: TestDescAndFn,
812817
monitor_ch: SharedChan<MonitorMsg>) {

0 commit comments

Comments
 (0)