# HG changeset patch # User Jaroslav Hajek # Date 1274183335 -7200 # Node ID a24f0eab8721089964a03bfece7d12d64cf62fd0 # Parent 5c594472f75e77f3e275f0a40c1be86e0a747392 [mq]: oncleanup.diff diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -0,0 +1,6 @@ +2010-05-18 Jaroslav Hajek + + * defun-int.h (octave_auto_shlib): Make members public. + * DLD-FUNCTIONS/onCleanup.cc: New source. + * DLD-FUNCTIONS/module-files: Add it here. + diff --git a/src/DLD-FUNCTIONS/module-files b/src/DLD-FUNCTIONS/module-files --- a/src/DLD-FUNCTIONS/module-files +++ b/src/DLD-FUNCTIONS/module-files @@ -53,6 +53,7 @@ matrix_type.cc max.cc md5sum.cc +onCleanup.cc pinv.cc qr.cc quad.cc diff --git a/src/DLD-FUNCTIONS/onCleanup.cc b/src/DLD-FUNCTIONS/onCleanup.cc new file mode 100644 --- /dev/null +++ b/src/DLD-FUNCTIONS/onCleanup.cc @@ -0,0 +1,260 @@ +/* + +Copyright (C) 2010 VZLU Prague + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "defun-dld.h" +#include "ov-base.h" +#include "ov.h" +#include "ov-fcn.h" +#include "ov-usr-fcn.h" +#include "pt-misc.h" +#include "toplev.h" + +static void gripe_internal (void) +{ + error ("onCleanup: internal error"); +} + +class octave_oncleanup : public octave_base_value, octave_auto_shlib +{ +public: + octave_oncleanup (void) : fcn () { } + octave_oncleanup (const octave_value& fcn); + + octave_base_value *clone (void) const + { + gripe_internal (); + return empty_clone (); + } + + octave_base_value *empty_clone (void) const { return new octave_oncleanup (); } + + ~octave_oncleanup (void); + + bool is_defined (void) const { return true; } + + bool is_object (void) const { return true; } // do we want this? + + dim_vector dims (void) const { static dim_vector dv (1, 1); return dv; } + + bool save_ascii (std::ostream& os); + + bool load_ascii (std::istream& is); + + bool save_binary (std::ostream& os, bool& save_as_floats); + + bool load_binary (std::istream& is, bool swap, + oct_mach_info::float_format fmt); + +#if defined (HAVE_HDF5) + bool save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats); + + bool load_hdf5 (hid_t loc_id, const char *name); +#endif + + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + + void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; + +private: + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA + +protected: + + octave_value fcn; + +}; + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_oncleanup, "onCleanup", "onCleanup"); + +octave_oncleanup::octave_oncleanup (const octave_value& f) + : fcn (f) +{ + if (f.is_function_handle ()) + { + octave_function *fptr = f.function_value (true); + if (fptr) + { + octave_user_function *uptr = dynamic_cast (fptr); + if (uptr != 0) + { + tree_parameter_list *pl = uptr->parameter_list (); + if (pl != 0 && pl->length () > 0) + warning ("onCleanup: cleanup action takes parameters"); + } + } + else + error ("onCleanup: no default dispatch for function handle"); + } + else + { + fcn = octave_value (); + error ("onCleanup: argument must be a function handle"); + } +} + +octave_oncleanup::~octave_oncleanup (void) +{ + if (fcn.is_undefined ()) + return; + + unwind_protect frame; + + // Clear interrupts. + frame.protect_var (octave_interrupt_state); + octave_interrupt_state = 0; + + // Disallow quit(). + frame.protect_var (quit_allowed); + quit_allowed = false; + + // Clear errors. + frame.protect_var (error_state); + error_state = 0; + + try + { + // Run the actual code. + fcn.do_multi_index_op (0, octave_value_list ()); + } + catch (octave_interrupt_exception) + { + // Swallow the interrupt. + warning ("onCleanup: interrupt occured in cleanup action"); + } + catch (std::bad_alloc) + { + // Swallow the exception. + warning ("onCleanup: out of memory occured in cleanup action"); + } + catch (...) // Yes, the black hole. We're in a d-tor. + { + // This shouldn't happen, in theory. + error ("onCleanup: internal error: unhandled exception in cleanup action"); + } + + // We don't want to ignore errors that occur in the cleanup code, so + // if an error is encountered there, leave error_state alone. + // Otherwise, set it back to what it was before. + if (error_state) + { + frame.discard_top (); + octave_call_stack::backtrace_error_message (); + } +} + +static void gripe_save_load (void) +{ + error ("onCleanup: load and save not supported"); +} + +bool +octave_oncleanup::save_ascii (std::ostream& os) +{ + gripe_save_load (); + return false; +} + +bool +octave_oncleanup::load_ascii (std::istream& is) +{ + gripe_save_load (); + return false; +} + +bool +octave_oncleanup::save_binary (std::ostream& os, bool& save_as_floats) +{ + gripe_save_load (); + return false; +} + + +bool +octave_oncleanup::load_binary (std::istream& is, bool swap, + oct_mach_info::float_format fmt) +{ + gripe_save_load (); + return false; +} + +#if defined (HAVE_HDF5) +bool +octave_oncleanup::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats) +{ + gripe_save_load (); + return false; +} + +bool +octave_oncleanup::load_hdf5 (hid_t loc_id, const char *name) +{ + gripe_save_load (); + return false; +} +#endif + +void +octave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax) const +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_oncleanup::print_raw (std::ostream& os, bool pr_as_read_syntax) const +{ + os << "onCleanup ("; + if (fcn.is_defined ()) + fcn.print_raw (os, pr_as_read_syntax); + os << ")"; +} + +DEFUN_DLD (onCleanup, args, , + "-*- texinfo -*-\n\ address@hidden {Loadable Function} address@hidden =} onCleanup (@var{action})\n\ +Creates a special object that executes a given function upon destruction.\n\ +If the object is copied to multiple variables (or cell or struct array elements)\n\ +or returned from a function, @var{action} will be executed after clearing the last\n\ +copy of the object. Note that if multiple local onCleanup variables are created, the\n\ +order in which they are called is unspecified.\n\ address@hidden address@hidden deftypefn") +{ + octave_value retval; + + if (args.length () == 1) + { + if (octave_oncleanup::static_type_id () < 0) + octave_oncleanup::register_type (); + + retval = new octave_oncleanup (args(0)); + } + else + print_usage (); + + return retval; +} diff --git a/src/defun-int.h b/src/defun-int.h --- a/src/defun-int.h +++ b/src/defun-int.h @@ -65,6 +65,7 @@ class octave_auto_shlib : public octave_shlib { +public: octave_auto_shlib (void) : octave_shlib (get_current_shlib ()) { } octave_auto_shlib (const octave_shlib& shl)