Mercurial > octave-nkf
comparison src/DLD-FUNCTIONS/onCleanup.cc @ 10641:ed6969880316
preliminary onCleanup support
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 19 May 2010 07:09:40 +0200 |
parents | |
children | 2a9f059758bd |
comparison
equal
deleted
inserted
replaced
10640:5c594472f75e | 10641:ed6969880316 |
---|---|
1 /* | |
2 | |
3 Copyright (C) 2010 VZLU Prague | |
4 | |
5 This file is part of Octave. | |
6 | |
7 Octave is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 3 of the License, or (at your | |
10 option) any later version. | |
11 | |
12 Octave is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with Octave; see the file COPYING. If not, see | |
19 <http://www.gnu.org/licenses/>. | |
20 | |
21 */ | |
22 | |
23 #ifdef HAVE_CONFIG_H | |
24 #include <config.h> | |
25 #endif | |
26 | |
27 #include "defun-dld.h" | |
28 #include "ov-base.h" | |
29 #include "ov.h" | |
30 #include "ov-fcn.h" | |
31 #include "ov-usr-fcn.h" | |
32 #include "pt-misc.h" | |
33 #include "toplev.h" | |
34 | |
35 static void gripe_internal (void) | |
36 { | |
37 error ("onCleanup: internal error: cloning nonempty object"); | |
38 } | |
39 | |
40 class octave_oncleanup : public octave_base_value, octave_auto_shlib | |
41 { | |
42 public: | |
43 octave_oncleanup (void) : fcn () { } | |
44 octave_oncleanup (const octave_value& fcn); | |
45 | |
46 octave_base_value *clone (void) const | |
47 { | |
48 if (fcn.is_defined ()) | |
49 gripe_internal (); | |
50 return empty_clone (); | |
51 } | |
52 | |
53 octave_base_value *empty_clone (void) const { return new octave_oncleanup (); } | |
54 | |
55 ~octave_oncleanup (void); | |
56 | |
57 bool is_defined (void) const { return true; } | |
58 | |
59 bool is_object (void) const { return true; } // do we want this? | |
60 | |
61 Octave_map map_value (void) const; | |
62 | |
63 dim_vector dims (void) const { static dim_vector dv (1, 1); return dv; } | |
64 | |
65 bool save_ascii (std::ostream& os); | |
66 | |
67 bool load_ascii (std::istream& is); | |
68 | |
69 bool save_binary (std::ostream& os, bool& save_as_floats); | |
70 | |
71 bool load_binary (std::istream& is, bool swap, | |
72 oct_mach_info::float_format fmt); | |
73 | |
74 #if defined (HAVE_HDF5) | |
75 bool save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats); | |
76 | |
77 bool load_hdf5 (hid_t loc_id, const char *name); | |
78 #endif | |
79 | |
80 void print (std::ostream& os, bool pr_as_read_syntax = false) const; | |
81 | |
82 void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; | |
83 | |
84 private: | |
85 | |
86 DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA | |
87 | |
88 protected: | |
89 | |
90 octave_value fcn; | |
91 | |
92 }; | |
93 | |
94 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_oncleanup, "onCleanup", "onCleanup"); | |
95 | |
96 octave_oncleanup::octave_oncleanup (const octave_value& f) | |
97 : fcn (f) | |
98 { | |
99 if (f.is_function_handle ()) | |
100 { | |
101 octave_function *fptr = f.function_value (true); | |
102 if (fptr) | |
103 { | |
104 octave_user_function *uptr = dynamic_cast<octave_user_function *> (fptr); | |
105 if (uptr != 0) | |
106 { | |
107 tree_parameter_list *pl = uptr->parameter_list (); | |
108 if (pl != 0 && pl->length () > 0) | |
109 warning ("onCleanup: cleanup action takes parameters"); | |
110 } | |
111 } | |
112 else | |
113 error ("onCleanup: no default dispatch for function handle"); | |
114 } | |
115 else | |
116 { | |
117 fcn = octave_value (); | |
118 error ("onCleanup: argument must be a function handle"); | |
119 } | |
120 } | |
121 | |
122 octave_oncleanup::~octave_oncleanup (void) | |
123 { | |
124 if (fcn.is_undefined ()) | |
125 return; | |
126 | |
127 unwind_protect frame; | |
128 | |
129 // Clear interrupts. | |
130 frame.protect_var (octave_interrupt_state); | |
131 octave_interrupt_state = 0; | |
132 | |
133 // Disallow quit(). | |
134 frame.protect_var (quit_allowed); | |
135 quit_allowed = false; | |
136 | |
137 // Clear errors. | |
138 frame.protect_var (error_state); | |
139 error_state = 0; | |
140 | |
141 try | |
142 { | |
143 // Run the actual code. | |
144 fcn.do_multi_index_op (0, octave_value_list ()); | |
145 } | |
146 catch (octave_interrupt_exception) | |
147 { | |
148 // Swallow the interrupt. | |
149 warning ("onCleanup: interrupt occured in cleanup action"); | |
150 } | |
151 catch (std::bad_alloc) | |
152 { | |
153 // Swallow the exception. | |
154 warning ("onCleanup: out of memory occured in cleanup action"); | |
155 } | |
156 catch (...) // Yes, the black hole. We're in a d-tor. | |
157 { | |
158 // This shouldn't happen, in theory. | |
159 error ("onCleanup: internal error: unhandled exception in cleanup action"); | |
160 } | |
161 | |
162 // We don't want to ignore errors that occur in the cleanup code, so | |
163 // if an error is encountered there, leave error_state alone. | |
164 // Otherwise, set it back to what it was before. | |
165 if (error_state) | |
166 { | |
167 frame.discard_top (); | |
168 octave_call_stack::backtrace_error_message (); | |
169 } | |
170 } | |
171 | |
172 Octave_map | |
173 octave_oncleanup::map_value (void) const | |
174 { | |
175 Octave_map map; | |
176 map.assign ("task", fcn); | |
177 return map; | |
178 } | |
179 | |
180 static void | |
181 warn_load_save (void) | |
182 { | |
183 warning ("onCleanup: load and save not supported"); | |
184 } | |
185 | |
186 bool | |
187 octave_oncleanup::save_ascii (std::ostream& os) | |
188 { | |
189 warn_save_load (); | |
190 return true; | |
191 } | |
192 | |
193 bool | |
194 octave_oncleanup::load_ascii (std::istream& is) | |
195 { | |
196 warn_save_load (); | |
197 return true; | |
198 } | |
199 | |
200 bool | |
201 octave_oncleanup::save_binary (std::ostream& os, bool& save_as_floats) | |
202 { | |
203 warn_save_load (); | |
204 return true; | |
205 } | |
206 | |
207 | |
208 bool | |
209 octave_oncleanup::load_binary (std::istream& is, bool swap, | |
210 oct_mach_info::float_format fmt) | |
211 { | |
212 warn_save_load (); | |
213 return true; | |
214 } | |
215 | |
216 #if defined (HAVE_HDF5) | |
217 bool | |
218 octave_oncleanup::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats) | |
219 { | |
220 warn_save_load (); | |
221 return true; | |
222 } | |
223 | |
224 bool | |
225 octave_oncleanup::load_hdf5 (hid_t loc_id, const char *name) | |
226 { | |
227 warn_save_load (); | |
228 return true; | |
229 } | |
230 #endif | |
231 | |
232 void | |
233 octave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax) const | |
234 { | |
235 print_raw (os, pr_as_read_syntax); | |
236 newline (os); | |
237 } | |
238 | |
239 void | |
240 octave_oncleanup::print_raw (std::ostream& os, bool pr_as_read_syntax) const | |
241 { | |
242 os << "onCleanup ("; | |
243 if (fcn.is_defined ()) | |
244 fcn.print_raw (os, pr_as_read_syntax); | |
245 os << ")"; | |
246 } | |
247 | |
248 DEFUN_DLD (onCleanup, args, , | |
249 "-*- texinfo -*-\n\ | |
250 @deftypefn {Loadable Function} {@var{c} =} onCleanup (@var{action})\n\ | |
251 Creates a special object that executes a given function upon destruction.\n\ | |
252 If the object is copied to multiple variables (or cell or struct array elements)\n\ | |
253 or returned from a function, @var{action} will be executed after clearing the last\n\ | |
254 copy of the object. Note that if multiple local onCleanup variables are created, the\n\ | |
255 order in which they are called is unspecified.\n\ | |
256 @seealso{unwind_protect}\n\ | |
257 @end deftypefn") | |
258 { | |
259 octave_value retval; | |
260 | |
261 if (args.length () == 1) | |
262 { | |
263 if (octave_oncleanup::static_type_id () < 0) | |
264 octave_oncleanup::register_type (); | |
265 | |
266 retval = new octave_oncleanup (args(0)); | |
267 } | |
268 else | |
269 print_usage (); | |
270 | |
271 return retval; | |
272 } |