(index<- ) ./libcore/finally.rs
git branch: * master 5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
modified: Fri May 9 13:02:28 2014
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 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
20 # Example
21
22 ```
23 use std::unstable::finally::Finally;
24
25 (|| {
26 // ...
27 }).finally(|| {
28 // this code is always run
29 })
30 ```
31 */
32
33 #![experimental]
34
35 use ops::Drop;
36
37 /// A trait for executing a destructor unconditionally after a block of code,
38 /// regardless of whether the blocked fails.
39 pub trait Finally<T> {
40 /// Executes this object, unconditionally running `dtor` after this block of
41 /// code has run.
42 fn finally(&mut self, dtor: ||) -> T;
43 }
44
45 impl<'a,T> Finally<T> for ||: 'a -> T {
46 fn finally(&mut self, dtor: ||) -> T {
47 try_finally(&mut (), self,
48 |_, f| (*f)(),
49 |_| dtor())
50 }
51 }
52
53 impl<T> Finally<T> for fn() -> T {
54 fn finally(&mut self, dtor: ||) -> T {
55 try_finally(&mut (), (),
56 |_, _| (*self)(),
57 |_| dtor())
58 }
59 }
60
61 /**
62 * The most general form of the `finally` functions. The function
63 * `try_fn` will be invoked first; whether or not it fails, the
64 * function `finally_fn` will be invoked next. The two parameters
65 * `mutate` and `drop` are used to thread state through the two
66 * closures. `mutate` is used for any shared, mutable state that both
67 * closures require access to; `drop` is used for any state that the
68 * `try_fn` requires ownership of.
69 *
70 * **WARNING:** While shared, mutable state between the try and finally
71 * function is often necessary, one must be very careful; the `try`
72 * function could have failed at any point, so the values of the shared
73 * state may be inconsistent.
74 *
75 * # Example
76 *
77 * ```
78 * use std::unstable::finally::try_finally;
79 *
80 * struct State<'a> { buffer: &'a mut [u8], len: uint }
81 * # let mut buf = [];
82 * let mut state = State { buffer: buf, len: 0 };
83 * try_finally(
84 * &mut state, (),
85 * |state, ()| {
86 * // use state.buffer, state.len
87 * },
88 * |state| {
89 * // use state.buffer, state.len to cleanup
90 * })
91 * ```
92 */
93 pub fn try_finally<T,U,R>(mutate: &mut T,
94 drop: U,
95 try_fn: |&mut T, U| -> R,
96 finally_fn: |&mut T|)
97 -> R {
98 let f = Finallyalizer {
99 mutate: mutate,
100 dtor: finally_fn,
101 };
102 try_fn(&mut *f.mutate, drop)
103 }
104
105 struct Finallyalizer<'a,A> {
106 mutate: &'a mut A,
107 dtor: |&mut A|: 'a
108 }
109
110 #[unsafe_destructor]
111 impl<'a,A> Drop for Finallyalizer<'a,A> {
112 #[inline]
113 fn drop(&mut self) {
114 (self.dtor)(self.mutate);
115 }
116 }
117
118 #[cfg(test)]
119 mod test {
120 use super::{try_finally, Finally};
121 use realstd::task::failing;
122
123 #[test]
124 fn test_success() {
125 let mut i = 0;
126 try_finally(
127 &mut i, (),
128 |i, ()| {
129 *i = 10;
130 },
131 |i| {
132 assert!(!failing());
133 assert_eq!(*i, 10);
134 *i = 20;
135 });
136 assert_eq!(i, 20);
137 }
138
139 #[test]
140 #[should_fail]
141 fn test_fail() {
142 let mut i = 0;
143 try_finally(
144 &mut i, (),
145 |i, ()| {
146 *i = 10;
147 fail!();
148 },
149 |i| {
150 assert!(failing());
151 assert_eq!(*i, 10);
152 })
153 }
154
155 #[test]
156 fn test_retval() {
157 let mut closure: || -> int = || 10;
158 let i = closure.finally(|| { });
159 assert_eq!(i, 10);
160 }
161
162 #[test]
163 fn test_compact() {
164 fn do_some_fallible_work() {}
165 fn but_always_run_this_function() { }
166 let mut f = do_some_fallible_work;
167 f.finally(but_always_run_this_function);
168 }
169 }
libcore/finally.rs:104:1-104:1 -struct- definition:
struct Finallyalizer<'a,A> {
mutate: &'a mut A,
dtor: |&mut A|: 'a
references:- 2111: impl<'a,A> Drop for Finallyalizer<'a,A> {
112: #[inline]
libcore/finally.rs:92:4-92:4 -fn- definition:
*/
pub fn try_finally<T,U,R>(mutate: &mut T,
drop: U,
references:- 346: fn finally(&mut self, dtor: ||) -> T {
47: try_finally(&mut (), self,
48: |_, f| (*f)(),
libcore/should_not_exist.rs:
161: let p = &mut (*ret).data as *mut _ as *mut A;
162: try_finally(
163: &mut i, (),
libcore/finally.rs:
54: fn finally(&mut self, dtor: ||) -> T {
55: try_finally(&mut (), (),
56: |_, _| (*self)(),
libcore/finally.rs:38:45-38:45 -trait- definition:
/// regardless of whether the blocked fails.
pub trait Finally<T> {
/// Executes this object, unconditionally running `dtor` after this block of
references:- 253: impl<T> Finally<T> for fn() -> T {
54: fn finally(&mut self, dtor: ||) -> T {