Skip to content

Commit f089445

Browse files
committed
---
yaml --- r: 149098 b: refs/heads/try2 c: 852a49f h: refs/heads/master v: v3
1 parent e3ca21f commit f089445

File tree

5 files changed

+127
-72
lines changed

5 files changed

+127
-72
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 2ab248af38c982f42a0a1acf0769e71fa7e77db7
8+
refs/heads/try2: 852a49fd9cf3860aa018c1a2d66f644c6813d849
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/libstd/io/mod.rs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ use str::{StrSlice, OwnedStr};
277277
use str;
278278
use to_str::ToStr;
279279
use uint;
280-
use unstable::finally::Finally;
280+
use unstable::finally::try_finally;
281281
use vec::{OwnedVector, MutableVector, ImmutableVector, OwnedCloneableVector};
282282
use vec;
283283

@@ -473,25 +473,33 @@ pub trait Reader {
473473
/// pushed on to the vector, otherwise the amount `len` bytes couldn't be
474474
/// read (an error was encountered), and the error is returned.
475475
fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) -> IoResult<()> {
476+
struct State<'a> {
477+
buf: &'a mut ~[u8],
478+
total_read: uint
479+
}
480+
476481
let start_len = buf.len();
477-
let mut total_read = 0;
478-
479-
buf.reserve_additional(len);
480-
unsafe { buf.set_len(start_len + len); }
481-
482-
(|| {
483-
while total_read < len {
484-
let len = buf.len();
485-
let slice = buf.mut_slice(start_len + total_read, len);
486-
match self.read(slice) {
487-
Ok(nread) => {
488-
total_read += nread;
482+
let mut s = State { buf: buf, total_read: 0 };
483+
484+
s.buf.reserve_additional(len);
485+
unsafe { s.buf.set_len(start_len + len); }
486+
487+
try_finally(
488+
&mut s, (),
489+
|s, _| {
490+
while s.total_read < len {
491+
let len = s.buf.len();
492+
let slice = s.buf.mut_slice(start_len + s.total_read, len);
493+
match self.read(slice) {
494+
Ok(nread) => {
495+
s.total_read += nread;
496+
}
497+
Err(e) => return Err(e)
489498
}
490-
Err(e) => return Err(e)
491499
}
492-
}
493-
Ok(())
494-
}).finally(|| unsafe { buf.set_len(start_len + total_read) })
500+
Ok(())
501+
},
502+
|s| unsafe { s.buf.set_len(start_len + s.total_read) })
495503
}
496504

497505
/// Reads `len` bytes and gives you back a new vector of length `len`

branches/try2/src/libstd/iter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ This `for` loop syntax can be applied to any iterator over any type.
5959
## Iteration protocol and more
6060
6161
More detailed information about iterators can be found in the [container
62-
guide](http://static.rust-lang.org/doc/master/guide-container.html) with
62+
tutorial](http://static.rust-lang.org/doc/master/tutorial-container.html) with
6363
the rest of the rust manuals.
6464
6565
*/

branches/try2/src/libstd/unstable/finally.rs

Lines changed: 79 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
The Finally trait provides a method, `finally` on
1313
stack closures that emulates Java-style try/finally blocks.
1414
15+
Using the `finally` method is sometimes convenient, but the type rules
16+
prohibit any shared, mutable state between the "try" case and the
17+
"finally" case. For advanced cases, the `try_finally` function can
18+
also be used. See that function for more details.
19+
1520
# Example
1621
1722
```
@@ -31,67 +36,106 @@ pub trait Finally<T> {
3136
fn finally(&self, dtor: ||) -> T;
3237
}
3338

34-
macro_rules! finally_fn {
35-
($fnty:ty) => {
36-
impl<T> Finally<T> for $fnty {
37-
fn finally(&self, dtor: ||) -> T {
38-
let _d = Finallyalizer {
39-
dtor: dtor
40-
};
41-
(*self)()
42-
}
43-
}
39+
impl<'a,T> Finally<T> for 'a || -> T {
40+
fn finally(&self, dtor: ||) -> T {
41+
try_finally(&mut (), (),
42+
|_, _| (*self)(),
43+
|_| dtor())
4444
}
4545
}
4646

47-
impl<'a,T> Finally<T> for 'a || -> T {
47+
impl<T> Finally<T> for fn() -> T {
4848
fn finally(&self, dtor: ||) -> T {
49-
let _d = Finallyalizer {
50-
dtor: dtor
51-
};
52-
53-
(*self)()
49+
try_finally(&mut (), (),
50+
|_, _| (*self)(),
51+
|_| dtor())
5452
}
5553
}
5654

57-
finally_fn!(extern "Rust" fn() -> T)
55+
/**
56+
* The most general form of the `finally` functions. The function
57+
* `try_fn` will be invoked first; whether or not it fails, the
58+
* function `finally_fn` will be invoked next. The two parameters
59+
* `mutate` and `drop` are used to thread state through the two
60+
* closures. `mutate` is used for any shared, mutable state that both
61+
* closures require access to; `drop` is used for any state that the
62+
* `try_fn` requires ownership of.
63+
*
64+
* **WARNING:** While shared, mutable state between the try and finally
65+
* function is often necessary, one must be very careful; the `try`
66+
* function could have failed at any point, so the values of the shared
67+
* state may be inconsistent.
68+
*
69+
* # Example
70+
*
71+
* ```
72+
* struct State<'a> { buffer: &'a mut [u8], len: uint }
73+
* let mut state = State { buffer: buf, len: 0 };
74+
* try_finally(
75+
* &mut state, (),
76+
* |state, ()| {
77+
* // use state.buffer, state.len
78+
* }
79+
* |state| {
80+
* // use state.buffer, state.len to cleanup
81+
* })
82+
* ```
83+
*/
84+
pub fn try_finally<T,U,R>(mutate: &mut T,
85+
drop: U,
86+
try_fn: |&mut T, U| -> R,
87+
finally_fn: |&mut T|)
88+
-> R {
89+
let f = Finallyalizer {
90+
mutate: mutate,
91+
dtor: finally_fn,
92+
};
93+
try_fn(&mut *f.mutate, drop)
94+
}
5895

59-
struct Finallyalizer<'a> {
60-
dtor: 'a ||
96+
struct Finallyalizer<'a,A> {
97+
mutate: &'a mut A,
98+
dtor: 'a |&mut A|
6199
}
62100

63101
#[unsafe_destructor]
64-
impl<'a> Drop for Finallyalizer<'a> {
102+
impl<'a,A> Drop for Finallyalizer<'a,A> {
65103
#[inline]
66104
fn drop(&mut self) {
67-
(self.dtor)();
105+
(self.dtor)(self.mutate);
68106
}
69107
}
70108

71109
#[test]
72110
fn test_success() {
73111
let mut i = 0;
74-
(|| {
75-
i = 10;
76-
}).finally(|| {
77-
assert!(!failing());
78-
assert_eq!(i, 10);
79-
i = 20;
80-
});
112+
try_finally(
113+
&mut i, (),
114+
|i, ()| {
115+
*i = 10;
116+
},
117+
|i| {
118+
assert!(!failing());
119+
assert_eq!(*i, 10);
120+
*i = 20;
121+
});
81122
assert_eq!(i, 20);
82123
}
83124

84125
#[test]
85126
#[should_fail]
86127
fn test_fail() {
87128
let mut i = 0;
88-
(|| {
89-
i = 10;
90-
fail!();
91-
}).finally(|| {
92-
assert!(failing());
93-
assert_eq!(i, 10);
94-
})
129+
try_finally(
130+
&mut i, (),
131+
|i, ()| {
132+
*i = 10;
133+
fail!();
134+
},
135+
|i| {
136+
assert!(failing());
137+
assert_eq!(*i, 10);
138+
})
95139
}
96140

97141
#[test]

branches/try2/src/libstd/vec.rs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ use mem;
119119
use mem::size_of;
120120
use kinds::marker;
121121
use uint;
122-
use unstable::finally::Finally;
122+
use unstable::finally::try_finally;
123+
use unstable::intrinsics;
123124
use unstable::raw::{Repr, Slice, Vec};
124125

125126
/**
@@ -132,15 +133,16 @@ pub fn from_fn<T>(n_elts: uint, op: |uint| -> T) -> ~[T] {
132133
unsafe {
133134
let mut v = with_capacity(n_elts);
134135
let p = v.as_mut_ptr();
135-
let mut i: uint = 0u;
136-
(|| {
137-
while i < n_elts {
138-
mem::move_val_init(&mut(*ptr::mut_offset(p, i as int)), op(i));
139-
i += 1u;
140-
}
141-
}).finally(|| {
142-
v.set_len(i);
143-
});
136+
let mut i = 0;
137+
try_finally(
138+
&mut i, (),
139+
|i, ()| while *i < n_elts {
140+
mem::move_val_init(
141+
&mut(*ptr::mut_offset(p, *i as int)),
142+
op(*i));
143+
*i += 1u;
144+
},
145+
|i| v.set_len(*i));
144146
v
145147
}
146148
}
@@ -160,14 +162,15 @@ pub fn from_elem<T:Clone>(n_elts: uint, t: T) -> ~[T] {
160162
let mut v = with_capacity(n_elts);
161163
let p = v.as_mut_ptr();
162164
let mut i = 0u;
163-
(|| {
164-
while i < n_elts {
165-
mem::move_val_init(&mut(*ptr::mut_offset(p, i as int)), t.clone());
166-
i += 1u;
167-
}
168-
}).finally(|| {
169-
v.set_len(i);
170-
});
165+
try_finally(
166+
&mut i, (),
167+
|i, ()| while *i < n_elts {
168+
mem::move_val_init(
169+
&mut(*ptr::mut_offset(p, *i as int)),
170+
t.clone());
171+
*i += 1u;
172+
},
173+
|i| v.set_len(*i));
171174
v
172175
}
173176
}

0 commit comments

Comments
 (0)