diff libinterp/interp-core/unwind-prot.h @ 15396:1054ab58cd58

abstract unwind_protect * action-container.h: New file. Provide action_container base class. * event-queue.h: New file. Provide event_queue class. * unwind-prot.h: Derive unwind_protect from action_container.
author John W. Eaton <jwe@octave.org>
date Mon, 17 Sep 2012 19:52:20 -0400
parents 2fc554ffbc28
children
line wrap: on
line diff
--- a/libinterp/interp-core/unwind-prot.h	Mon Sep 17 08:50:46 2012 -0400
+++ b/libinterp/interp-core/unwind-prot.h	Mon Sep 17 19:52:20 2012 -0400
@@ -24,289 +24,74 @@
 #if !defined (octave_unwind_prot_h)
 #define octave_unwind_prot_h 1
 
-#include <cstddef>
-
-#include <string>
+#include <stack>
 #include <memory>
 
-// This class allows registering cleanup actions.
+#include "action-container.h"
+
 class
 OCTINTERP_API
-unwind_protect
+unwind_protect : public action_container
 {
 public:
 
-  // A generic unwind_protect element. Knows how to run itself and discard itself.
-  // Also, contains a pointer to the next element.
-  class elem
-  {
-    elem *next;
-
-  public:
-    elem (void) : next (0) { }
-
-    virtual void run (void) { }
-
-    virtual ~elem (void) { }
-
-    friend class unwind_protect;
-
-  private:
-
-    // No copying!
-
-    elem (const elem&);
-
-    elem& operator = (const elem&);
-  };
-
-  // An element that merely runs a void (*)(void) function.
-
-  class fcn_elem : public elem
-  {
-  public:
-    fcn_elem (void (*fptr) (void))
-      : e_fptr (fptr) { }
+  unwind_protect (void) : lifo () { }
 
-    void run (void) { e_fptr (); }
-
-  private:
-    void (*e_fptr) (void);
-  };
-
-  // An element that stores a variable of type T along with a void (*) (T)
-  // function pointer, and calls the function with the parameter.
-
-  template <class T>
-  class fcn_arg_elem : public elem
-  {
-  public:
-    fcn_arg_elem (void (*fcn) (T), T arg)
-      : e_fcn (fcn), e_arg (arg) { }
+  // Destructor should not raise an exception, so all actions
+  // registered should be exception-safe (but setting error_state is
+  // allowed). If you're not sure, see unwind_protect_safe.
 
-    void run (void) { e_fcn (e_arg); }
-
-  private:
-
-    // No copying!
-
-    fcn_arg_elem (const fcn_arg_elem&);
-
-    fcn_arg_elem& operator = (const fcn_arg_elem&);
-
-    void (*e_fcn) (T);
-    T e_arg;
-  };
-
-  // An element that stores a variable of type T along with a void (*) (const T&)
-  // function pointer, and calls the function with the parameter.
+  ~unwind_protect (void) { run (); }
 
-  template <class T>
-  class fcn_crefarg_elem : public elem
+  virtual void add (elem *new_elem)
   {
-  public:
-    fcn_crefarg_elem (void (*fcn) (const T&), T arg)
-      : e_fcn (fcn), e_arg (arg) { }
-
-    void run (void) { e_fcn (e_arg); }
-
-  private:
-    void (*e_fcn) (const T&);
-    T e_arg;
-  };
-
-  // An element for calling a member function.
-
-  template <class T>
-  class method_elem : public elem
-  {
-  public:
-    method_elem (T *obj, void (T::*method) (void))
-      : e_obj (obj), e_method (method) { }
-
-    void run (void) { (e_obj->*e_method) (); }
-
-  private:
-
-    T *e_obj;
-    void (T::*e_method) (void);
-
-    // No copying!
-
-    method_elem (const method_elem&);
+    lifo.push (new_elem);
+  }
 
-    method_elem operator = (const method_elem&);
-  };
-
-  // An element that stores arbitrary variable, and restores it.
-
-  template <class T>
-  class restore_var_elem : public elem
+  void add (void (*fcn) (void *), void *ptr = 0) GCC_ATTR_DEPRECATED
   {
-  public:
-    restore_var_elem (T& ref, const T& val)
-      : e_ptr (&ref), e_val (val) { }
-
-    void run (void) { *e_ptr = e_val; }
-
-  private:
+    add (new fcn_arg_elem<void *> (fcn, ptr));
+  }
 
-    // No copying!
-
-    restore_var_elem (const restore_var_elem&);
-
-    restore_var_elem& operator = (const restore_var_elem&);
-
-    T *e_ptr, e_val;
-  };
+  operator bool (void) const { return ! empty (); }
 
-  // Deletes a class allocated using new.
-
-  template <class T>
-  class delete_ptr_elem : public elem
-  {
-  public:
-    delete_ptr_elem (T *ptr)
-      : e_ptr (ptr) { }
+  void run_top (void) GCC_ATTR_DEPRECATED { run_first (); }
 
-    void run (void) { delete e_ptr; }
-
-  private:
-
-    T *e_ptr;
-
-    // No copying!
-
-    delete_ptr_elem (const delete_ptr_elem&);
-
-    delete_ptr_elem operator = (const delete_ptr_elem&);
-  };
-
-  unwind_protect (void) : head () { }
-
-  void add (elem *new_elem)
-    {
-      new_elem->next = head;
-      head = new_elem;
-    }
-
-  // For backward compatibility.
-  void add (void (*fcn) (void *), void *ptr = 0)
-    {
-      add (new fcn_arg_elem<void *> (fcn, ptr));
-    }
+  void run_first (void)
+  {
+    if (! empty ())
+      {
+        // No leak on exception!
+        std::auto_ptr<elem> ptr (lifo.top ());
+        lifo.pop ();
+        ptr->run ();
+      }
+  }
 
-  // Call to void func (void).
-  void add_fcn (void (*fcn) (void))
-    {
-      add (new fcn_elem (fcn));
-    }
-
-  // Call to void func (T).
-  template <class T>
-  void add_fcn (void (*action) (T), T val)
-    {
-      add (new fcn_arg_elem<T> (action, val));
-    }
+  void run_top (int num) GCC_ATTR_DEPRECATED { run (num); }
 
-  // Call to void func (const T&).
-  template <class T>
-  void add_fcn (void (*action) (const T&), T val)
-    {
-      add (new fcn_crefarg_elem<T> (action, val));
-    }
-
-  // Call to T::method (void).
-  template <class T>
-  void add_method (T *obj, void (T::*method) (void))
-    {
-      add (new method_elem<T> (obj, method));
-    }
-
-  // Call to delete (T*).
-
-  template <class T>
-  void add_delete (T *obj)
-    {
-      add (new delete_ptr_elem<T> (obj));
-    }
+  void discard_top (void) GCC_ATTR_DEPRECATED { discard_first (); }
 
-  // Protect any variable.
-  template <class T>
-  void protect_var (T& var)
-    {
-      add (new restore_var_elem<T> (var, var));
-    }
-
-  // Protect any variable, value given.
-  template <class T>
-  void protect_var (T& var, const T& val)
-    {
-      add (new restore_var_elem<T> (var, val));
-    }
-
-  operator bool (void) const
-    {
-      return head != 0;
-    }
-
-  void run_top (void)
-    {
-      if (head)
-        {
-          // No leak on exception!
-          std::auto_ptr<elem> ptr (head);
-          head = ptr->next;
-          ptr->run ();
-        }
-    }
-
-  void run_top (int num)
-    {
-      while (num-- > 0)
-        run_top ();
-    }
+  void discard_first (void)
+  {
+    if (! empty ())
+      {
+        elem *ptr = lifo.top ();
+        lifo.pop ();
+        delete ptr;
+      }
+  }
 
-  void discard_top (void)
-    {
-      if (head)
-        {
-          elem *ptr = head;
-          head = ptr->next;
-          delete ptr;
-        }
-    }
+  void discard_top (int num) GCC_ATTR_DEPRECATED { discard (num); }
 
-  void discard_top (int num)
-    {
-      while (num-- > 0)
-        discard_top ();
-    }
+  size_t size (void) const { return lifo.size (); }
 
-  void run (void)
-    {
-      while (head)
-        run_top ();
-    }
+protected:
 
-  void discard (void)
-    {
-      while (head)
-        discard_top ();
-    }
-
-  // Destructor should not raise an exception, so all actions registered should
-  // be exception-safe (but setting error_state is allowed). If you're not sure,
-  // see unwind_protect_safe.
-  ~unwind_protect (void)
-    {
-      run ();
-    }
+  std::stack<elem *> lifo;
 
 private:
 
-  elem *head;
-
   // No copying!
 
   unwind_protect (const unwind_protect&);
@@ -314,24 +99,30 @@
   unwind_protect& operator = (const unwind_protect&);
 };
 
-// Like unwind_protect, but this one will guard against the possibility of seeing
-// an exception (or interrupt) in the cleanup actions. Not that we can do much about
-// it, but at least we won't crash.
+// Like unwind_protect, but this one will guard against the
+// possibility of seeing an exception (or interrupt) in the cleanup
+// actions. Not that we can do much about it, but at least we won't
+// crash.
 
 class
 OCTINTERP_API
 unwind_protect_safe : public unwind_protect
 {
+private:
+
   static void gripe_exception (void);
 
 public:
+
+  unwind_protect_safe (void) : unwind_protect () { }
+
   ~unwind_protect_safe (void)
     {
-      while (*this)
+      while (! empty ())
         {
           try
             {
-              run_top ();
+              run_first ();
             }
           catch (...) // Yes, the black hole. Remember we're in a dtor.
             {
@@ -339,6 +130,14 @@
             }
         }
     }
+
+private:
+
+  // No copying!
+
+  unwind_protect_safe (const unwind_protect_safe&);
+
+  unwind_protect_safe& operator = (const unwind_protect_safe&);
 };
 
 #endif