GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ov-oncleanup.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2010-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include "defun.h"
31 #include "interpreter.h"
32 #include "interpreter-private.h"
33 #include "ov-oncleanup.h"
34 #include "ov-fcn.h"
35 #include "ov-usr-fcn.h"
36 #include "pt-misc.h"
37 
39  "onCleanup");
40 
42  : m_fcn (f)
43 {
44  if (f.is_function_handle ())
45  {
46  octave_function *fptr = f.function_value (true);
47  if (! fptr)
48  error ("onCleanup: no default dispatch for function handle");
49 
51  = dynamic_cast<octave_user_function *> (fptr);
52 
53  if (uptr != nullptr)
54  {
55  octave::tree_parameter_list *pl = uptr->parameter_list ();
56 
57  if (pl != nullptr && pl->length () > 0)
58  warning ("onCleanup: cleanup action takes parameters");
59  }
60  }
61  else
62  {
63  m_fcn = octave_value ();
64  error ("onCleanup: argument must be a function handle");
65  }
66 }
67 
69 {
71 }
72 
75 {
76  octave_scalar_map retval;
77  retval.setfield ("task", m_fcn);
78  return retval;
79 }
80 
81 bool
82 octave_oncleanup::save_ascii (std::ostream& /* os */)
83 {
84  warning ("save: unable to save onCleanup variables, skipping");
85 
86  return true;
87 }
88 
89 bool
90 octave_oncleanup::load_ascii (std::istream& /* is */)
91 {
92  // Silently skip object that was not saved
93  return true;
94 }
95 
96 bool
97 octave_oncleanup::save_binary (std::ostream& /* os */,
98  bool /* save_as_floats */)
99 {
100  warning ("save: unable to save onCleanup variables, skipping");
101 
102  return true;
103 }
104 
105 bool
106 octave_oncleanup::load_binary (std::istream& /* is */, bool /* swap */,
108 {
109  // Silently skip object that was not saved
110  return true;
111 }
112 
113 bool
115  const char * /* name */,
116  bool /* save_as_floats */)
117 {
118  warning ("save: unable to save onCleanup variables, skipping");
119 
120  return true;
121 }
122 
123 bool
125  const char * /* name */)
126 {
127  // Silently skip object that was not saved
128  return true;
129 }
130 
131 void
132 octave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax)
133 {
134  print_raw (os, pr_as_read_syntax);
135  newline (os);
136 }
137 
138 void
139 octave_oncleanup::print_raw (std::ostream& os, bool pr_as_read_syntax) const
140 {
141  os << "onCleanup (";
142  if (m_fcn.is_defined ())
143  m_fcn.print_raw (os, pr_as_read_syntax);
144  os << ')';
145 }
146 
147 void
149 {
150  if (m_fcn.is_undefined ())
151  return;
152 
153  octave_value the_fcn = m_fcn;
154  m_fcn = octave_value ();
155 
156  octave::unwind_protect frame;
157 
158  // Clear interrupts.
159  frame.protect_var (octave_interrupt_state);
161 
162  // Disallow quit().
163  frame.protect_var (quit_allowed);
164  quit_allowed = false;
165 
166  octave::interpreter& interp = octave::__get_interpreter__ ();
167 
168  octave::interpreter_try (frame);
169 
170  try
171  {
172  // Run the actual code.
173  interp.feval (the_fcn);
174  }
175  catch (const octave::interrupt_exception&)
176  {
177  interp.recover_from_exception ();
178 
179  warning ("onCleanup: interrupt occurred in cleanup action");
180  }
181  catch (const octave::execution_exception& ee)
182  {
183  interp.recover_from_exception ();
184 
185  std::string msg = ee.message ();
186 
187  warning ("onCleanup: error caught while executing cleanup function:\n%s\n",
188  msg.c_str ());
189 
190  }
191  catch (const octave::exit_exception&)
192  {
193  // This shouldn't happen since we disabled quit above.
194  warning ("onCleanup: exit disabled while executing cleanup function");
195  }
196  catch (...) // Yes, the black hole. We're in a d-tor.
197  {
198  // This shouldn't happen, in theory.
199  warning ("onCleanup: internal error: unhandled exception in cleanup action");
200  }
201 }
202 
204 
205 DEFUN (onCleanup, args, ,
206  doc: /* -*- texinfo -*-
207 @deftypefn {} {@var{obj} =} onCleanup (@var{function})
208 Create a special object that executes a given @var{function} upon destruction.
209 
210 If the object is copied to multiple variables (or cell or struct array
211 elements) or returned from a function, then @var{function} will be executed
212 only after the last copy of the object is cleared.
213 
214 The input @var{function} is a handle to a function. The handle may point to an
215 anonymous function in order to directly place commands in the @code{onCleanup}
216 call.
217 
218 Programming Note: If multiple local @code{onCleanup} variables are created, the
219 order in which they are called is unspecified. For similar functionality
220 @xref{The unwind_protect Statement}.
221 
222 Example
223 
224 @example
225 @group
226 octave:1> trigger = onCleanup (@@() disp ('onCleanup was executed'));
227 octave:2> clear trigger
228 onCleanup was executed
229 octave:3
230 @end group
231 @end example
232 
233 @end deftypefn */)
234 {
235  if (args.length () != 1)
236  print_usage ();
237 
238  return ovl (new octave_oncleanup (args(0)));
239 }
240 
241 /*
242 %!test
243 %! old_wstate = warning ("query");
244 %! unwind_protect
245 %! trigger = onCleanup (@() warning ("on", "__MY_WARNING__"));
246 %! warning ("off", "__MY_WARNING__");
247 %! assert ((warning ("query", "__MY_WARNING__")).state, "off");
248 %! clear trigger;
249 %! assert ((warning ("query", "__MY_WARNING__")).state, "on");
250 %! unwind_protect_cleanup
251 %! warning (old_wstate);
252 %! end_unwind_protect
253 */
254 
255 OCTAVE_END_NAMESPACE(octave)
void newline(std::ostream &os) const
Definition: ov-base.cc:1388
friend class octave_value
Definition: ov-base.h:269
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
void call_object_destructor()
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
octave_scalar_map scalar_map_value() const
Definition: ov-oncleanup.cc:74
bool save_binary(std::ostream &os, bool save_as_floats)
Definition: ov-oncleanup.cc:97
bool load_ascii(std::istream &is)
Definition: ov-oncleanup.cc:90
octave_value m_fcn
Definition: ov-oncleanup.h:106
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
void print(std::ostream &os, bool pr_as_read_syntax=false)
bool save_ascii(std::ostream &os)
Definition: ov-oncleanup.cc:82
octave_oncleanup()=default
void setfield(const std::string &key, const octave_value &val)
Definition: oct-map.cc:190
octave::tree_parameter_list * parameter_list()
Definition: ov-usr-fcn.h:384
bool is_undefined() const
Definition: ov.h:595
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov.h:1324
bool is_defined() const
Definition: ov.h:592
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage(void)
Definition: defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
void warning(const char *fmt,...)
Definition: error.cc:1063
void() error(const char *fmt,...)
Definition: error.cc:988
void interpreter_try(octave::unwind_protect &)
interpreter & __get_interpreter__()
bool quit_allowed
Definition: interpreter.cc:88
F77_RET_T const F77_DBLE const F77_DBLE * f
FloatComplex(* fptr)(const FloatComplex &, float, int, octave_idx_type &)
Definition: lo-specfun.cc:1102
float_format
Definition: mach-info.h:38
int64_t octave_hdf5_id
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:235
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:219
std::atomic< sig_atomic_t > octave_interrupt_state
Definition: quit.cc:39