]> git.lizzy.rs Git - rust.git/blob - src/libstd/unstable/finally.rs
Find the cratemap at runtime on windows.
[rust.git] / src / libstd / unstable / finally.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /*!
12 The Finally trait provides a method, `finally` on
13 stack closures that emulates Java-style try/finally blocks.
14
15 # Example
16
17 ~~~
18 do || {
19     ...
20 }.finally {
21     always_run_this();
22 }
23 ~~~
24 */
25
26 use ops::Drop;
27
28 #[cfg(test)] use task::{failing, spawn};
29
30 pub trait Finally<T> {
31     fn finally(&self, dtor: &fn()) -> T;
32 }
33
34 macro_rules! finally_fn {
35     ($fnty:ty) => {
36         impl<T> Finally<T> for $fnty {
37             fn finally(&self, dtor: &fn()) -> T {
38                 let _d = Finallyalizer {
39                     dtor: dtor
40                 };
41                 (*self)()
42             }
43         }
44     }
45 }
46
47 impl<'self,T> Finally<T> for &'self fn() -> T {
48     fn finally(&self, dtor: &fn()) -> T {
49         let _d = Finallyalizer {
50             dtor: dtor
51         };
52
53         (*self)()
54     }
55 }
56
57 finally_fn!(~fn() -> T)
58 finally_fn!(@fn() -> T)
59 finally_fn!(extern "Rust" fn() -> T)
60
61 struct Finallyalizer<'self> {
62     dtor: &'self fn()
63 }
64
65 #[unsafe_destructor]
66 impl<'self> Drop for Finallyalizer<'self> {
67     fn drop(&mut self) {
68         (self.dtor)();
69     }
70 }
71
72 #[test]
73 fn test_success() {
74     let mut i = 0;
75     do (|| {
76         i = 10;
77     }).finally {
78         assert!(!failing());
79         assert_eq!(i, 10);
80         i = 20;
81     }
82     assert_eq!(i, 20);
83 }
84
85 #[test]
86 #[should_fail]
87 fn test_fail() {
88     let mut i = 0;
89     do (|| {
90         i = 10;
91         fail!();
92     }).finally {
93         assert!(failing());
94         assert_eq!(i, 10);
95     }
96 }
97
98 #[test]
99 fn test_retval() {
100     let closure: &fn() -> int = || 10;
101     let i = do closure.finally { };
102     assert_eq!(i, 10);
103 }
104
105 #[test]
106 fn test_compact() {
107     fn do_some_fallible_work() {}
108     fn but_always_run_this_function() { }
109     do_some_fallible_work.finally(
110         but_always_run_this_function);
111 }
112
113 #[test]
114 fn test_owned() {
115     fn spawn_with_finalizer(f: ~fn()) {
116         do spawn { do f.finally { } }
117     }
118     let owned: ~fn() = || { };
119     spawn_with_finalizer(owned);
120 }
121
122 #[test]
123 fn test_managed() {
124     let i = @mut 10;
125     let managed: @fn() -> int = || {
126         let r = *i;
127         *i += 10;
128         r
129     };
130     assert_eq!(do managed.finally {}, 10);
131     assert_eq!(*i, 20);
132 }