diff --git a/src/libcore/private.rs b/src/libcore/private.rs index ef25cb52e8ba..3eadce1c30cc 100644 --- a/src/libcore/private.rs +++ b/src/libcore/private.rs @@ -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]; diff --git a/src/libcore/private/finally.rs b/src/libcore/private/finally.rs new file mode 100644 index 000000000000..f4d76dfd54db --- /dev/null +++ b/src/libcore/private/finally.rs @@ -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 { + fn finally(&self, +dtor: &fn()) -> T; +} + +impl &fn() -> T: Finally { + // 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); +} \ No newline at end of file