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 }