# 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)