ov-oncleanup.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2010-2012 VZLU Prague
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include "defun.h"
00028 #include "ov-oncleanup.h"
00029 #include "ov-fcn.h"
00030 #include "ov-usr-fcn.h"
00031 #include "pt-misc.h"
00032 #include "toplev.h"
00033 
00034 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_oncleanup, "onCleanup",
00035                                      "onCleanup");
00036 
00037 octave_oncleanup::octave_oncleanup (const octave_value& f)
00038   : fcn (f)
00039 {
00040   if (f.is_function_handle ())
00041     {
00042       octave_function *fptr = f.function_value (true);
00043       if (fptr)
00044         {
00045           octave_user_function *uptr
00046             = dynamic_cast<octave_user_function *> (fptr);
00047 
00048           if (uptr != 0)
00049             {
00050               tree_parameter_list *pl = uptr->parameter_list ();
00051 
00052               if (pl != 0 && pl->length () > 0)
00053                 warning ("onCleanup: cleanup action takes parameters");
00054             }
00055         }
00056       else
00057         error ("onCleanup: no default dispatch for function handle");
00058     }
00059   else
00060     {
00061       fcn = octave_value ();
00062       error ("onCleanup: argument must be a function handle");
00063     }
00064 }
00065 
00066 octave_oncleanup::~octave_oncleanup (void)
00067 {
00068   if (fcn.is_undefined ())
00069     return;
00070 
00071   unwind_protect frame;
00072 
00073   // Clear interrupts.
00074   frame.protect_var (octave_interrupt_state);
00075   octave_interrupt_state = 0;
00076 
00077   // Disallow quit().
00078   frame.protect_var (quit_allowed);
00079   quit_allowed = false;
00080 
00081   // Clear errors.
00082   frame.protect_var (error_state);
00083   error_state = 0;
00084 
00085   try
00086     {
00087       // Run the actual code.
00088       fcn.do_multi_index_op (0, octave_value_list ());
00089     }
00090   catch (octave_interrupt_exception)
00091     {
00092       // Swallow the interrupt.
00093       warning ("onCleanup: interrupt occured in cleanup action");
00094     }
00095   catch (std::bad_alloc)
00096     {
00097       // Swallow the exception.
00098       warning ("onCleanup: out of memory occured in cleanup action");
00099     }
00100   catch (...) // Yes, the black hole. We're in a d-tor.
00101     {
00102       // This shouldn't happen, in theory.
00103       error ("onCleanup: internal error: unhandled exception in cleanup action");
00104     }
00105 
00106   // We don't want to ignore errors that occur in the cleanup code, so
00107   // if an error is encountered there, leave error_state alone.
00108   // Otherwise, set it back to what it was before.
00109   if (error_state)
00110     {
00111       frame.discard_top ();
00112       octave_call_stack::backtrace_error_message ();
00113     }
00114 }
00115 
00116 octave_scalar_map
00117 octave_oncleanup::scalar_map_value (void) const
00118 {
00119   octave_scalar_map retval;
00120   retval.setfield ("task", fcn);
00121   return retval;
00122 }
00123 
00124 static void
00125 warn_save_load (void)
00126 {
00127   warning ("onCleanup: load and save not supported");
00128 }
00129 
00130 bool
00131 octave_oncleanup::save_ascii (std::ostream& /* os */)
00132 {
00133   warn_save_load ();
00134   return true;
00135 }
00136 
00137 bool
00138 octave_oncleanup::load_ascii (std::istream& /* is */)
00139 {
00140   warn_save_load ();
00141   return true;
00142 }
00143 
00144 bool
00145 octave_oncleanup::save_binary (std::ostream& /* os */, bool& /* save_as_floats */)
00146 {
00147   warn_save_load ();
00148   return true;
00149 }
00150 
00151 bool
00152 octave_oncleanup::load_binary (std::istream& /* is */, bool /* swap */,
00153                                oct_mach_info::float_format /* fmt */)
00154 {
00155   warn_save_load ();
00156   return true;
00157 }
00158 
00159 #if defined (HAVE_HDF5)
00160 bool
00161 octave_oncleanup::save_hdf5 (hid_t /* loc_id */, const char * /* name */,
00162                              bool /* save_as_floats */)
00163 {
00164   warn_save_load ();
00165   return true;
00166 }
00167 
00168 bool
00169 octave_oncleanup::load_hdf5 (hid_t /* loc_id */, const char * /* name */)
00170 {
00171   warn_save_load ();
00172   return true;
00173 }
00174 #endif
00175 
00176 void
00177 octave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax) const
00178 {
00179   print_raw (os, pr_as_read_syntax);
00180   newline (os);
00181 }
00182 
00183 void
00184 octave_oncleanup::print_raw (std::ostream& os, bool pr_as_read_syntax) const
00185 {
00186   os << "onCleanup (";
00187   if (fcn.is_defined ())
00188     fcn.print_raw (os, pr_as_read_syntax);
00189   os << ")";
00190 }
00191 
00192 DEFUN (onCleanup, args, ,
00193   "-*- texinfo -*-\n\
00194 @deftypefn {Loadable Function} {@var{c} =} onCleanup (@var{action})\n\
00195 Create a special object that executes a given function upon destruction.\n\
00196 If the object is copied to multiple variables (or cell or struct array\n\
00197 elements) or returned from a function, @var{action} will be executed after\n\
00198 clearing the last copy of the object.  Note that if multiple local onCleanup\n\
00199 variables are created, the order in which they are called is unspecified.\n\
00200 For similar functionality @xref{The unwind_protect Statement}.\n\
00201 @end deftypefn")
00202 {
00203   octave_value retval;
00204 
00205   if (args.length () == 1)
00206     retval = octave_value (new octave_oncleanup (args(0)));
00207   else
00208     print_usage ();
00209 
00210   return retval;
00211 }
00212 
00213 /*
00214 
00215 %!test
00216 %! old_wstate = warning ("query");
00217 %! unwind_protect
00218 %!   trigger = onCleanup (@() warning ("on", "__MY_WARNING__"));
00219 %!   warning ("off", "__MY_WARNING__");
00220 %!   assert ((warning ("query", "__MY_WARNING__")).state, "off");
00221 %!   clear trigger
00222 %!   assert ((warning ("query", "__MY_WARNING__")).state, "on");
00223 %! unwind_protect_cleanup
00224 %!   warning (old_wstate);
00225 %! end_unwind_protect
00226 
00227 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines