about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2013-01-15 17:11:16 -0800
committerBrian Anderson <banderson@mozilla.com>2013-01-17 19:24:52 -0800
commit1bf8e579436941a82e4a4806b74dfd27ed4d1d74 (patch)
tree8a469ef891d85cee00e71f520de12f6d46e5918f
parentdb1abbec4ca9f18a224441c483cf23bb4f8361fd (diff)
downloadrust-1bf8e579436941a82e4a4806b74dfd27ed4d1d74.tar.gz
rust-1bf8e579436941a82e4a4806b74dfd27ed4d1d74.zip
Add `finally` method for deferred execution
-rw-r--r--src/libcore/private.rs2
-rw-r--r--src/libcore/private/finally.rs88
2 files changed, 90 insertions, 0 deletions
diff --git a/src/libcore/private.rs b/src/libcore/private.rs
index ef25cb52e8b..3eadce1c30c 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 00000000000..f4d76dfd54d
--- /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<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);
+}
\ No newline at end of file