# HG changeset patch # User John W. Eaton # Date 1380817908 14400 # Node ID d07d59cc8775821d01cf6c42f28837730aa48ff5 # Parent 8fca0bbdd4c14bb96b178e2a4824b7c0c3f9336f move unwind-protect to liboctave * liboctave/util/action-container.h, liboctave/util/unwind-prot.cc, liboctave/util/unwind-prot.h: Move here from libinterp/corefcn. * unwind-prot.cc (unwind_protect_safe::gripe_exception): Use current_liboctave_error_handler to handle error message. * libinterp/corefcn/module.mk, liboctave/util/module.mk: Update file lists. diff -r 8fca0bbdd4c1 -r d07d59cc8775 libinterp/corefcn/action-container.h --- a/libinterp/corefcn/action-container.h Thu Oct 03 12:15:00 2013 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,341 +0,0 @@ -/* - -Copyright (C) 1993-2012 John W. Eaton -Copyright (C) 2009-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 -. - -*/ - -#if !defined (octave_action_container_h) -#define octave_action_container_h 1 - -// This class allows registering actions in a list for later -// execution, either explicitly or when the container goes out of -// scope. - -// FIXME -- is there a better name for this class? - -class -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 - { - public: - elem (void) { } - - virtual void run (void) { } - - virtual ~elem (void) { } - - friend class action_container; - - 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) { } - - 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 fcn_arg_elem : public elem - { - public: - fcn_arg_elem (void (*fcn) (T), T arg) - : e_fcn (fcn), e_arg (arg) { } - - 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. - - template - class fcn_crefarg_elem : public elem - { - public: - fcn_crefarg_elem (void (*fcn) (const T&), const 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 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&); - - method_elem operator = (const method_elem&); - }; - - // An element for calling a member function with a single argument - - template - class method_arg_elem : public elem - { - public: - method_arg_elem (T *obj, void (T::*method) (A), A arg) - : e_obj (obj), e_method (method), e_arg (arg) { } - - void run (void) { (e_obj->*e_method) (e_arg); } - - private: - - T *e_obj; - void (T::*e_method) (A); - A e_arg; - - // No copying! - - method_arg_elem (const method_arg_elem&); - - method_arg_elem operator = (const method_arg_elem&); - }; - - // An element for calling a member function with a single argument - - template - class method_crefarg_elem : public elem - { - public: - method_crefarg_elem (T *obj, void (T::*method) (const A&), const A& arg) - : e_obj (obj), e_method (method), e_arg (arg) { } - - void run (void) { (e_obj->*e_method) (e_arg); } - - private: - - T *e_obj; - void (T::*e_method) (const A&); - A e_arg; - - // No copying! - - method_crefarg_elem (const method_crefarg_elem&); - - method_crefarg_elem operator = (const method_crefarg_elem&); - }; - - // An element that stores arbitrary variable, and restores it. - - template - class restore_var_elem : public elem - { - public: - restore_var_elem (T& ref, const T& val) - : e_ptr (&ref), e_val (val) { } - - void run (void) { *e_ptr = e_val; } - - private: - - // No copying! - - restore_var_elem (const restore_var_elem&); - - restore_var_elem& operator = (const restore_var_elem&); - - T *e_ptr, e_val; - }; - - // Deletes a class allocated using new. - - template - class delete_ptr_elem : public elem - { - public: - delete_ptr_elem (T *ptr) - : e_ptr (ptr) { } - - 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&); - }; - - action_container (void) { } - - virtual ~action_container (void) { } - - virtual void add (elem *new_elem) = 0; - - // Call to void func (void). - void add_fcn (void (*fcn) (void)) - { - add (new fcn_elem (fcn)); - } - - // Call to void func (T). - template - void add_fcn (void (*action) (T), T val) - { - add (new fcn_arg_elem (action, val)); - } - - // Call to void func (const T&). - template - void add_fcn (void (*action) (const T&), const T& val) - { - add (new fcn_crefarg_elem (action, val)); - } - - // Call to T::method (void). - template - void add_method (T *obj, void (T::*method) (void)) - { - add (new method_elem (obj, method)); - } - - // Call to T::method (A). - template - void add_method (T *obj, void (T::*method) (A), A arg) - { - add (new method_arg_elem (obj, method, arg)); - } - - // Call to T::method (const A&). - template - void add_method (T *obj, void (T::*method) (const A&), const A& arg) - { - add (new method_crefarg_elem (obj, method, arg)); - } - - // Call to delete (T*). - - template - void add_delete (T *obj) - { - add (new delete_ptr_elem (obj)); - } - - // Protect any variable. - template - void protect_var (T& var) - { - add (new restore_var_elem (var, var)); - } - - // Protect any variable, value given. - template - void protect_var (T& var, const T& val) - { - add (new restore_var_elem (var, val)); - } - - operator bool (void) const { return ! empty (); } - - virtual void run_first (void) = 0; - - void run (size_t num) - { - if (num > size ()) - num = size (); - - for (size_t i = 0; i < num; i++) - run_first (); - } - - void run (void) { run (size ()); } - - virtual void discard_first (void) = 0; - - void discard (size_t num) - { - if (num > size ()) - num = size (); - - for (size_t i = 0; i < num; i++) - discard_first (); - } - - void discard (void) { discard (size ()); } - - virtual size_t size (void) const = 0; - - bool empty (void) const { return size () == 0; } - -private: - - // No copying! - - action_container (const action_container&); - - action_container& operator = (const action_container&); -}; - -#endif diff -r 8fca0bbdd4c1 -r d07d59cc8775 libinterp/corefcn/module.mk --- a/libinterp/corefcn/module.mk Thu Oct 03 12:15:00 2013 -0400 +++ b/libinterp/corefcn/module.mk Thu Oct 03 12:31:48 2013 -0400 @@ -44,7 +44,6 @@ COREFCN_INC = \ corefcn/Cell.h \ - corefcn/action-container.h \ corefcn/c-file-ptr-stream.h \ corefcn/comment-list.h \ corefcn/cutils.h \ @@ -108,7 +107,6 @@ corefcn/toplev.h \ corefcn/txt-eng-ft.h \ corefcn/txt-eng.h \ - corefcn/unwind-prot.h \ corefcn/utils.h \ corefcn/variables.h \ corefcn/workspace-element.h \ @@ -256,7 +254,6 @@ corefcn/txt-eng.cc \ corefcn/txt-eng-ft.cc \ corefcn/typecast.cc \ - corefcn/unwind-prot.cc \ corefcn/utils.cc \ corefcn/variables.cc \ corefcn/xdiv.cc \ diff -r 8fca0bbdd4c1 -r d07d59cc8775 libinterp/corefcn/unwind-prot.cc --- a/libinterp/corefcn/unwind-prot.cc Thu Oct 03 12:15:00 2013 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - -Copyright (C) 1993-2012 John W. Eaton -Copyright (C) 2009 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 "error.h" -#include "unwind-prot.h" - -void unwind_protect_safe::gripe_exception (void) -{ - // FIXME: can this throw an exception? - error ("internal: unhandled exception in unwind_protect handler"); -} diff -r 8fca0bbdd4c1 -r d07d59cc8775 libinterp/corefcn/unwind-prot.h --- a/libinterp/corefcn/unwind-prot.h Thu Oct 03 12:15:00 2013 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/* - -Copyright (C) 1993-2012 John W. Eaton -Copyright (C) 2009-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 -. - -*/ - -#if !defined (octave_unwind_prot_h) -#define octave_unwind_prot_h 1 - -#include -#include - -#include "action-container.h" - -class -OCTINTERP_API -unwind_protect : public action_container -{ -public: - - unwind_protect (void) : lifo () { } - - // 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 (); } - - virtual void add (elem *new_elem) - { - lifo.push (new_elem); - } - - void add (void (*fcn) (void *), void *ptr = 0) GCC_ATTR_DEPRECATED - { - add (new fcn_arg_elem (fcn, ptr)); - } - - operator bool (void) const { return ! empty (); } - - void run_top (void) GCC_ATTR_DEPRECATED { run_first (); } - - void run_first (void) - { - if (! empty ()) - { - // No leak on exception! - std::auto_ptr ptr (lifo.top ()); - lifo.pop (); - ptr->run (); - } - } - - void run_top (int num) GCC_ATTR_DEPRECATED { run (num); } - - void discard_top (void) GCC_ATTR_DEPRECATED { discard_first (); } - - void discard_first (void) - { - if (! empty ()) - { - elem *ptr = lifo.top (); - lifo.pop (); - delete ptr; - } - } - - void discard_top (int num) GCC_ATTR_DEPRECATED { discard (num); } - - size_t size (void) const { return lifo.size (); } - -protected: - - std::stack lifo; - -private: - - // No copying! - - unwind_protect (const unwind_protect&); - - 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. - -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 (! empty ()) - { - try - { - run_first (); - } - catch (...) // Yes, the black hole. Remember we're in a dtor. - { - gripe_exception (); - } - } - } - -private: - - // No copying! - - unwind_protect_safe (const unwind_protect_safe&); - - unwind_protect_safe& operator = (const unwind_protect_safe&); -}; - -#endif diff -r 8fca0bbdd4c1 -r d07d59cc8775 liboctave/util/action-container.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liboctave/util/action-container.h Thu Oct 03 12:31:48 2013 -0400 @@ -0,0 +1,341 @@ +/* + +Copyright (C) 1993-2012 John W. Eaton +Copyright (C) 2009-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 +. + +*/ + +#if !defined (octave_action_container_h) +#define octave_action_container_h 1 + +// This class allows registering actions in a list for later +// execution, either explicitly or when the container goes out of +// scope. + +// FIXME -- is there a better name for this class? + +class +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 + { + public: + elem (void) { } + + virtual void run (void) { } + + virtual ~elem (void) { } + + friend class action_container; + + 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) { } + + 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 fcn_arg_elem : public elem + { + public: + fcn_arg_elem (void (*fcn) (T), T arg) + : e_fcn (fcn), e_arg (arg) { } + + 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. + + template + class fcn_crefarg_elem : public elem + { + public: + fcn_crefarg_elem (void (*fcn) (const T&), const 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 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&); + + method_elem operator = (const method_elem&); + }; + + // An element for calling a member function with a single argument + + template + class method_arg_elem : public elem + { + public: + method_arg_elem (T *obj, void (T::*method) (A), A arg) + : e_obj (obj), e_method (method), e_arg (arg) { } + + void run (void) { (e_obj->*e_method) (e_arg); } + + private: + + T *e_obj; + void (T::*e_method) (A); + A e_arg; + + // No copying! + + method_arg_elem (const method_arg_elem&); + + method_arg_elem operator = (const method_arg_elem&); + }; + + // An element for calling a member function with a single argument + + template + class method_crefarg_elem : public elem + { + public: + method_crefarg_elem (T *obj, void (T::*method) (const A&), const A& arg) + : e_obj (obj), e_method (method), e_arg (arg) { } + + void run (void) { (e_obj->*e_method) (e_arg); } + + private: + + T *e_obj; + void (T::*e_method) (const A&); + A e_arg; + + // No copying! + + method_crefarg_elem (const method_crefarg_elem&); + + method_crefarg_elem operator = (const method_crefarg_elem&); + }; + + // An element that stores arbitrary variable, and restores it. + + template + class restore_var_elem : public elem + { + public: + restore_var_elem (T& ref, const T& val) + : e_ptr (&ref), e_val (val) { } + + void run (void) { *e_ptr = e_val; } + + private: + + // No copying! + + restore_var_elem (const restore_var_elem&); + + restore_var_elem& operator = (const restore_var_elem&); + + T *e_ptr, e_val; + }; + + // Deletes a class allocated using new. + + template + class delete_ptr_elem : public elem + { + public: + delete_ptr_elem (T *ptr) + : e_ptr (ptr) { } + + 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&); + }; + + action_container (void) { } + + virtual ~action_container (void) { } + + virtual void add (elem *new_elem) = 0; + + // Call to void func (void). + void add_fcn (void (*fcn) (void)) + { + add (new fcn_elem (fcn)); + } + + // Call to void func (T). + template + void add_fcn (void (*action) (T), T val) + { + add (new fcn_arg_elem (action, val)); + } + + // Call to void func (const T&). + template + void add_fcn (void (*action) (const T&), const T& val) + { + add (new fcn_crefarg_elem (action, val)); + } + + // Call to T::method (void). + template + void add_method (T *obj, void (T::*method) (void)) + { + add (new method_elem (obj, method)); + } + + // Call to T::method (A). + template + void add_method (T *obj, void (T::*method) (A), A arg) + { + add (new method_arg_elem (obj, method, arg)); + } + + // Call to T::method (const A&). + template + void add_method (T *obj, void (T::*method) (const A&), const A& arg) + { + add (new method_crefarg_elem (obj, method, arg)); + } + + // Call to delete (T*). + + template + void add_delete (T *obj) + { + add (new delete_ptr_elem (obj)); + } + + // Protect any variable. + template + void protect_var (T& var) + { + add (new restore_var_elem (var, var)); + } + + // Protect any variable, value given. + template + void protect_var (T& var, const T& val) + { + add (new restore_var_elem (var, val)); + } + + operator bool (void) const { return ! empty (); } + + virtual void run_first (void) = 0; + + void run (size_t num) + { + if (num > size ()) + num = size (); + + for (size_t i = 0; i < num; i++) + run_first (); + } + + void run (void) { run (size ()); } + + virtual void discard_first (void) = 0; + + void discard (size_t num) + { + if (num > size ()) + num = size (); + + for (size_t i = 0; i < num; i++) + discard_first (); + } + + void discard (void) { discard (size ()); } + + virtual size_t size (void) const = 0; + + bool empty (void) const { return size () == 0; } + +private: + + // No copying! + + action_container (const action_container&); + + action_container& operator = (const action_container&); +}; + +#endif diff -r 8fca0bbdd4c1 -r d07d59cc8775 liboctave/util/module.mk --- a/liboctave/util/module.mk Thu Oct 03 12:15:00 2013 -0400 +++ b/liboctave/util/module.mk Thu Oct 03 12:31:48 2013 -0400 @@ -2,6 +2,7 @@ util/module.mk UTIL_INC = \ + util/action-container.h \ util/base-list.h \ util/byte-swap.h \ util/caseless-str.h \ @@ -40,7 +41,8 @@ util/sparse-util.h \ util/statdefs.h \ util/str-vec.h \ - util/sun-utils.h + util/sun-utils.h \ + util/unwind-prot.cc UTIL_C_SRC = \ util/f2c-main.c \ @@ -71,6 +73,7 @@ util/sparse-sort.cc \ util/sparse-util.cc \ util/str-vec.cc \ + util/unwind-prot.cc \ $(UTIL_C_SRC) TEMPLATE_SRC += \ diff -r 8fca0bbdd4c1 -r d07d59cc8775 liboctave/util/unwind-prot.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liboctave/util/unwind-prot.cc Thu Oct 03 12:31:48 2013 -0400 @@ -0,0 +1,38 @@ +/* + +Copyright (C) 1993-2012 John W. Eaton +Copyright (C) 2009 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 "lo-error.h" +#include "unwind-prot.h" + +void +unwind_protect_safe::gripe_exception (void) +{ + // FIXME: can this throw an exception? + + (*current_liboctave_error_handler) + ("internal: unhandled exception in unwind_protect handler"); +} diff -r 8fca0bbdd4c1 -r d07d59cc8775 liboctave/util/unwind-prot.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liboctave/util/unwind-prot.h Thu Oct 03 12:31:48 2013 -0400 @@ -0,0 +1,145 @@ +/* + +Copyright (C) 1993-2012 John W. Eaton +Copyright (C) 2009-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 +. + +*/ + +#if !defined (octave_unwind_prot_h) +#define octave_unwind_prot_h 1 + +#include + +#include +#include + +#include "action-container.h" + +class +OCTINTERP_API +unwind_protect : public action_container +{ +public: + + unwind_protect (void) : lifo () { } + + // 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 (); } + + virtual void add (elem *new_elem) + { + lifo.push (new_elem); + } + + void add (void (*fcn) (void *), void *ptr = 0) GCC_ATTR_DEPRECATED + { + add (new fcn_arg_elem (fcn, ptr)); + } + + operator bool (void) const { return ! empty (); } + + void run_top (void) GCC_ATTR_DEPRECATED { run_first (); } + + void run_first (void) + { + if (! empty ()) + { + // No leak on exception! + std::auto_ptr ptr (lifo.top ()); + lifo.pop (); + ptr->run (); + } + } + + void run_top (int num) GCC_ATTR_DEPRECATED { run (num); } + + void discard_top (void) GCC_ATTR_DEPRECATED { discard_first (); } + + void discard_first (void) + { + if (! empty ()) + { + elem *ptr = lifo.top (); + lifo.pop (); + delete ptr; + } + } + + void discard_top (int num) GCC_ATTR_DEPRECATED { discard (num); } + + size_t size (void) const { return lifo.size (); } + +protected: + + std::stack lifo; + +private: + + // No copying! + + unwind_protect (const unwind_protect&); + + 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. + +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 (! empty ()) + { + try + { + run_first (); + } + catch (...) // Yes, the black hole. Remember we're in a dtor. + { + gripe_exception (); + } + } + } + +private: + + // No copying! + + unwind_protect_safe (const unwind_protect_safe&); + + unwind_protect_safe& operator = (const unwind_protect_safe&); +}; + +#endif