Add finally method for deferred execution

This commit is contained in:
Brian Anderson 2013-01-15 17:11:16 -08:00
parent db1abbec4c
commit 1bf8e57943
2 changed files with 90 additions and 0 deletions

View File

@ -32,6 +32,8 @@ use uint;
pub mod at_exit;
#[path = "private/global.rs"]
pub mod global;
#[path = "private/finally.rs"]
pub mod finally;
extern mod rustrt {
#[legacy_exports];

View File

@ -0,0 +1,88 @@
/*!
The Finally trait provides a method, `finally` on
stack closures that emulates Java-style try/finally blocks.
# Example
~~~
do || {
...
}.finally {
alway_run_this();
}
~~~
*/
use ops::Drop;
use task::{spawn, failing};
pub trait Finally<T> {
fn finally(&self, +dtor: &fn()) -> T;
}
impl<T> &fn() -> T: Finally<T> {
// XXX: Should not require a mode here
fn finally(&self, +dtor: &fn()) -> T {
let _d = Finallyalizer {
dtor: dtor
};
(*self)()
}
}
struct Finallyalizer {
dtor: &fn()
}
impl Finallyalizer: Drop {
fn finalize(&self) {
(self.dtor)();
}
}
#[test]
fn test_success() {
let mut i = 0;
do (|| {
i = 10;
}).finally {
assert !failing();
assert i == 10;
i = 20;
}
assert i == 20;
}
#[test]
#[ignore(cfg(windows))]
#[should_fail]
fn test_fail() {
let mut i = 0;
do (|| {
i = 10;
fail;
}).finally {
assert failing();
assert i == 10;
}
}
#[test]
fn test_retval() {
let i = do (fn&() -> int {
10
}).finally { };
assert i == 10;
}
#[test]
fn test_compact() {
// XXX Should be able to use a fn item instead
// of a closure for do_some_fallible_work,
// but it's a type error.
let do_some_fallible_work: &fn() = || { };
fn but_always_run_this_function() { }
do_some_fallible_work.finally(
but_always_run_this_function);
}