GNU Octave 7.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-2022 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 {
57
58 if (pl != nullptr && pl->length () > 0)
59 warning ("onCleanup: cleanup action takes parameters");
60 }
61 }
62 else
63 {
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
82bool
83octave_oncleanup::save_ascii (std::ostream& /* os */)
84{
85 warning ("save: unable to save onCleanup variables, skipping");
86
87 return true;
88}
89
90bool
91octave_oncleanup::load_ascii (std::istream& /* is */)
92{
93 // Silently skip object that was not saved
94 return true;
95}
96
97bool
98octave_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
106bool
107octave_oncleanup::load_binary (std::istream& /* is */, bool /* swap */,
109{
110 // Silently skip object that was not saved
111 return true;
112}
113
114bool
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
124bool
126 const char * /* name */)
127{
128 // Silently skip object that was not saved
129 return true;
130}
131
132void
133octave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax)
134{
135 print_raw (os, pr_as_read_syntax);
136 newline (os);
137}
138
139void
140octave_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
148void
150{
151 if (m_fcn.is_undefined ())
152 return;
153
154 octave_value the_fcn = m_fcn;
155 m_fcn = octave_value ();
156
158
159 // Clear interrupts.
162
163 // Disallow quit().
165 quit_allowed = false;
166
167 octave::interpreter& interp
168 = octave::__get_interpreter__ ("octave_oncleanup::call_object_destructor");
169
171
172 try
173 {
174 // Run the actual code.
175 octave::feval (the_fcn);
176 }
177 catch (const octave::interrupt_exception&)
178 {
179 interp.recover_from_exception ();
180
181 warning ("onCleanup: interrupt occurred in cleanup action");
182 }
183 catch (const octave::execution_exception& ee)
184 {
185 interp.recover_from_exception ();
186
187 std::string msg = ee.message ();
188
189 warning ("onCleanup: error caught while executing cleanup function:\n%s\n",
190 msg.c_str ());
191
192 }
193 catch (const octave::exit_exception&)
194 {
195 // This shouldn't happen since we disabled quit above.
196 warning ("onCleanup: exit disabled while executing cleanup function");
197 }
198 catch (...) // Yes, the black hole. We're in a d-tor.
199 {
200 // This shouldn't happen, in theory.
201 warning ("onCleanup: internal error: unhandled exception in cleanup action");
202 }
203}
204
205OCTAVE_NAMESPACE_BEGIN
206
207DEFUN (onCleanup, args, ,
208 doc: /* -*- texinfo -*-
209@deftypefn {} {@var{obj} =} onCleanup (@var{function})
210Create a special object that executes a given function upon destruction.
211
212If the object is copied to multiple variables (or cell or struct array
213elements) or returned from a function, @var{function} will be executed after
214clearing the last copy of the object. Note that if multiple local onCleanup
215variables are created, the order in which they are called is unspecified.
216For similar functionality @xref{The unwind_protect Statement}.
217@end deftypefn */)
218{
219 if (args.length () != 1)
220 print_usage ();
221
222 return ovl (new octave_oncleanup (args(0)));
223}
224
225/*
226%!test
227%! old_wstate = warning ("query");
228%! unwind_protect
229%! trigger = onCleanup (@() warning ("on", "__MY_WARNING__"));
230%! warning ("off", "__MY_WARNING__");
231%! assert ((warning ("query", "__MY_WARNING__")).state, "off");
232%! clear trigger;
233%! assert ((warning ("query", "__MY_WARNING__")).state, "on");
234%! unwind_protect_cleanup
235%! warning (old_wstate);
236%! end_unwind_protect
237*/
238
239OCTAVE_NAMESPACE_END
std::size_t length(void) const
Definition: base-list.h:53
OCTINTERP_API void newline(std::ostream &os) const
Definition: ov-base.cc:1383
friend class octave_value
Definition: ov-base.h:256
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:393
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov.h:1428
bool is_defined(void) const
Definition: ov.h:637
bool is_undefined(void) const
Definition: ov.h:640
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:2175
void warning(const char *fmt,...)
Definition: error.cc:1055
void error(const char *fmt,...)
Definition: error.cc:980
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:1128
OCTINTERP_API octave_value_list feval(const char *name, const octave_value_list &args=octave_value_list(), int nargout=0)
interpreter & __get_interpreter__(const std::string &who)
int64_t octave_hdf5_id
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:222
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