changeset 10641:ed6969880316

preliminary onCleanup support
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 19 May 2010 07:09:40 +0200
parents 5c594472f75e
children 2a9f059758bd
files src/ChangeLog src/DLD-FUNCTIONS/module-files src/DLD-FUNCTIONS/onCleanup.cc src/defun-int.h
diffstat 4 files changed, 280 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Tue May 18 08:34:02 2010 +0200
+++ b/src/ChangeLog	Wed May 19 07:09:40 2010 +0200
@@ -1,3 +1,9 @@
+2010-05-18  Jaroslav Hajek  <highegg@gmail.com>
+
+	* defun-int.h (octave_auto_shlib): Make members public.
+	* DLD-FUNCTIONS/onCleanup.cc: New source.
+	* DLD-FUNCTIONS/module-files: Add it here.
+
 2010-05-18  Jaroslav Hajek  <highegg@gmail.com>
 
 	* variables.cc (set_internal_variable (int&, ..., const char **)):
--- a/src/DLD-FUNCTIONS/module-files	Tue May 18 08:34:02 2010 +0200
+++ b/src/DLD-FUNCTIONS/module-files	Wed May 19 07:09:40 2010 +0200
@@ -53,6 +53,7 @@
 matrix_type.cc
 max.cc
 md5sum.cc
+onCleanup.cc
 pinv.cc
 qr.cc
 quad.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/DLD-FUNCTIONS/onCleanup.cc	Wed May 19 07:09:40 2010 +0200
@@ -0,0 +1,272 @@
+/*
+
+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
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#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: cloning nonempty object");
+}
+
+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 
+    { 
+      if (fcn.is_defined ())
+        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?
+
+  Octave_map map_value (void) const;
+
+  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<octave_user_function *> (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 ();
+    }
+}
+
+Octave_map 
+octave_oncleanup::map_value (void) const
+{
+  Octave_map map;
+  map.assign ("task", fcn);
+  return map;
+}
+
+static void 
+warn_load_save (void)
+{
+  warning ("onCleanup: load and save not supported");
+}
+
+bool 
+octave_oncleanup::save_ascii (std::ostream& os)
+{
+  warn_save_load ();
+  return true;
+}
+
+bool 
+octave_oncleanup::load_ascii (std::istream& is)
+{
+  warn_save_load ();
+  return true;
+}
+
+bool 
+octave_oncleanup::save_binary (std::ostream& os, bool& save_as_floats)
+{
+  warn_save_load ();
+  return true;
+}
+
+
+bool 
+octave_oncleanup::load_binary (std::istream& is, bool swap, 
+                               oct_mach_info::float_format fmt)
+{
+  warn_save_load ();
+  return true;
+}
+
+#if defined (HAVE_HDF5)
+bool 
+octave_oncleanup::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats)
+{
+  warn_save_load ();
+  return true;
+}
+
+bool 
+octave_oncleanup::load_hdf5 (hid_t loc_id, const char *name)
+{
+  warn_save_load ();
+  return true;
+}
+#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\
+@deftypefn {Loadable Function} {@var{c} =} 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\
+@seealso{unwind_protect}\n\
+@end 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;
+}
--- a/src/defun-int.h	Tue May 18 08:34:02 2010 +0200
+++ b/src/defun-int.h	Wed May 19 07:09:40 2010 +0200
@@ -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)