GNU Octave  8.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-2023 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 "parse.h"
37 #include "pt-misc.h"
38 
40  "onCleanup");
41 
43  : m_fcn (f)
44 {
45  if (f.is_function_handle ())
46  {
47  octave_function *fptr = f.function_value (true);
48  if (! fptr)
49  error ("onCleanup: no default dispatch for function handle");
50 
52  = dynamic_cast<octave_user_function *> (fptr);
53 
54  if (uptr != nullptr)
55  {
56  octave::tree_parameter_list *pl = uptr->parameter_list ();
57 
58  if (pl != nullptr && pl->length () > 0)
59  warning ("onCleanup: cleanup action takes parameters");
60  }
61  }
62  else
63  {
64  m_fcn = octave_value ();
65  error ("onCleanup: argument must be a function handle");
66  }
67 }
68 
70 {
72 }
73 
76 {
77  octave_scalar_map retval;
78  retval.setfield ("task", m_fcn);
79  return retval;
80 }
81 
82 bool
83 octave_oncleanup::save_ascii (std::ostream& /* os */)
84 {
85  warning ("save: unable to save onCleanup variables, skipping");
86 
87  return true;
88 }
89 
90 bool
91 octave_oncleanup::load_ascii (std::istream& /* is */)
92 {
93  // Silently skip object that was not saved
94  return true;
95 }
96 
97 bool
98 octave_oncleanup::save_binary (std::ostream& /* os */,
99  bool /* save_as_floats */)
100 {
101  warning ("save: unable to save onCleanup variables, skipping");
102 
103  return true;
104 }
105 
106 bool
107 octave_oncleanup::load_binary (std::istream& /* is */, bool /* swap */,
109 {
110  // Silently skip object that was not saved
111  return true;
112 }
113 
114 bool
116  const char * /* name */,
117  bool /* save_as_floats */)
118 {
119  warning ("save: unable to save onCleanup variables, skipping");
120 
121  return true;
122 }
123 
124 bool
126  const char * /* name */)
127 {
128  // Silently skip object that was not saved
129  return true;
130 }
131 
132 void
133 octave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax)
134 {
135  print_raw (os, pr_as_read_syntax);
136  newline (os);
137 }
138 
139 void
140 octave_oncleanup::print_raw (std::ostream& os, bool pr_as_read_syntax) const
141 {
142  os << "onCleanup (";
143  if (m_fcn.is_defined ())
144  m_fcn.print_raw (os, pr_as_read_syntax);
145  os << ')';
146 }
147 
148 void
150 {
151  if (m_fcn.is_undefined ())
152  return;
153 
154  octave_value the_fcn = m_fcn;
155  m_fcn = octave_value ();
156 
157  octave::unwind_protect frame;
158 
159  // Clear interrupts.
160  frame.protect_var (octave_interrupt_state);
162 
163  // Disallow quit().
164  frame.protect_var (quit_allowed);
165  quit_allowed = false;
166 
167  octave::interpreter& interp = octave::__get_interpreter__ ();
168 
169  octave::interpreter_try (frame);
170 
171  try
172  {
173  // Run the actual code.
174  octave::feval (the_fcn);
175  }
176  catch (const octave::interrupt_exception&)
177  {
178  interp.recover_from_exception ();
179 
180  warning ("onCleanup: interrupt occurred in cleanup action");
181  }
182  catch (const octave::execution_exception& ee)
183  {
184  interp.recover_from_exception ();
185 
186  std::string msg = ee.message ();
187 
188  warning ("onCleanup: error caught while executing cleanup function:\n%s\n",
189  msg.c_str ());
190 
191  }
192  catch (const octave::exit_exception&)
193  {
194  // This shouldn't happen since we disabled quit above.
195  warning ("onCleanup: exit disabled while executing cleanup function");
196  }
197  catch (...) // Yes, the black hole. We're in a d-tor.
198  {
199  // This shouldn't happen, in theory.
200  warning ("onCleanup: internal error: unhandled exception in cleanup action");
201  }
202 }
203 
205 
206 DEFUN (onCleanup, args, ,
207  doc: /* -*- texinfo -*-
208 @deftypefn {} {@var{obj} =} onCleanup (@var{function})
209 Create a special object that executes a given function upon destruction.
210 
211 If the object is copied to multiple variables (or cell or struct array
212 elements) or returned from a function, @var{function} will be executed after
213 clearing the last copy of the object. Note that if multiple local onCleanup
214 variables are created, the order in which they are called is unspecified.
215 For similar functionality @xref{The unwind_protect Statement}.
216 @end deftypefn */)
217 {
218  if (args.length () != 1)
219  print_usage ();
220 
221  return ovl (new octave_oncleanup (args(0)));
222 }
223 
224 /*
225 %!test
226 %! old_wstate = warning ("query");
227 %! unwind_protect
228 %! trigger = onCleanup (@() warning ("on", "__MY_WARNING__"));
229 %! warning ("off", "__MY_WARNING__");
230 %! assert ((warning ("query", "__MY_WARNING__")).state, "off");
231 %! clear trigger;
232 %! assert ((warning ("query", "__MY_WARNING__")).state, "on");
233 %! unwind_protect_cleanup
234 %! warning (old_wstate);
235 %! end_unwind_protect
236 */
237 
OCTAVE_END_NAMESPACE(octave)
OCTINTERP_API void newline(std::ostream &os) const
Definition: ov-base.cc:1388
friend class octave_value
Definition: ov-base.h:263
octave_scalar_map scalar_map_value(void) const
Definition: ov-oncleanup.cc:75
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
void call_object_destructor(void)
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
octave_oncleanup(void)=default
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
bool save_binary(std::ostream &os, bool save_as_floats)
Definition: ov-oncleanup.cc:98
bool load_ascii(std::istream &is)
Definition: ov-oncleanup.cc:91
octave_value m_fcn
Definition: ov-oncleanup.h:100
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:83
void setfield(const std::string &key, const octave_value &val)
Definition: oct-map.cc:190
octave::tree_parameter_list * parameter_list(void)
Definition: ov-usr-fcn.h:394
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov.h:1431
bool is_defined(void) const
Definition: ov.h:637
bool is_undefined(void) const
Definition: ov.h:640
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
OCTINTERP_API 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 interpreter_try(unwind_protect &frame)
Definition: error.cc:2177
void warning(const char *fmt,...)
Definition: error.cc:1054
void error(const char *fmt,...)
Definition: error.cc:979
interpreter & __get_interpreter__(void)
bool quit_allowed
Definition: interpreter.cc:87
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
octave_value_list feval(const char *name, const octave_value_list &args, int nargout)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
Definition: oct-parse.cc:10370
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:229
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211
sig_atomic_t octave_interrupt_state
Definition: quit.cc:38