# HG changeset patch # User Jaroslav Hajek # Date 1245912444 -7200 # Node ID b3ab22ee8544e6f3bc0abce5a968ca2ceae960f5 # Parent d6c99b2ee94192428522e2a141509b4a67810354 further improve unwind_protect diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,18 @@ +2009-06-25 Jaroslav Hajek + + * unwind-prot.h (unwind_protect::elem): New polymorphic class. + (unwind_protect::restore_var): Remove. + (unwind_protect::restore_mem): Remove. + (unwind_protect::elt_list): Update. + (unwind_protect::add (elem *)): New method. + (unwind_protect::add (void (*)(void *), void *)): Reimplement. + (unwind_protect::run (void)): Rewrite. + (unwind_protect::discard (void)): Rewrite. + (unwind_protect::protect_var): Rewrite. + (unwind_protect::protect_mem): Rewrite. + (unwind_protect::add_action_var): New method. + * unwind-prot.cc (unwind_protect::restore_mem): Remove. + 2009-06-24 Thorsten Meyer * oct-map.cc (Octave_map::squeeze, Octave_map::permute, diff --git a/src/unwind-prot.cc b/src/unwind-prot.cc --- a/src/unwind-prot.cc +++ b/src/unwind-prot.cc @@ -33,22 +33,10 @@ #include "unwind-prot.h" #include "utils.h" -std::stack unwind_protect::elt_list; +std::stack unwind_protect::elt_list; std::stack > unwind_protect::tag_list; -unwind_protect::restore_mem::restore_mem (void *ptr, size_t size) - : rptr (ptr), sptr (reinterpret_cast (new char[size])), rsize (size) -{ - std::memcpy (sptr, rptr, size); -} - -unwind_protect::restore_mem::~restore_mem (void) -{ - std::memcpy (rptr, sptr, rsize); - delete [] reinterpret_cast (sptr); -} - void unwind_protect::begin_frame (const std::string& tag) { diff --git a/src/unwind-prot.h b/src/unwind-prot.h --- a/src/unwind-prot.h +++ b/src/unwind-prot.h @@ -29,7 +29,7 @@ #include #include -#include +#include class OCTINTERP_API @@ -37,86 +37,89 @@ { public: - // This template class can be used to restore value of a variable of any - // class posessing a copy constructor and assignment operator. - - template - class - restore_var + // A generic unwind_protect element. Knows how to run itself and discard itself. + class elem { public: - restore_var (T *ptr, const T& val) - : rptr (ptr), rval(val) { } - restore_var (T *ptr) - : rptr (ptr), rval(*ptr) { } - ~restore_var (void) - { *rptr = rval; } + virtual void run (void) { } + virtual ~elem (void) { } + }; - // For unwind_protect. - static void cleanup (void *ptr) - { - delete reinterpret_cast (ptr); - } + // An element that merely runs a void (*)(void *) function. + + class fcn_elem : public elem + { + public: + fcn_elem (void (*fptr) (void *), void *ptr) + : e_fptr (fptr), e_ptr (ptr) { } + + void run (void) { e_fptr (e_ptr); } private: - - // No copying! - restore_var (const restore_var&); - void operator = (const restore_var&); - - T *rptr, rval; + void (*e_fptr) (void *); + void *e_ptr; }; - // This class is used to restore arbitrary memory area using std::memcpy. + // An element that stores arbitrary variable, and restores it. - class - restore_mem + template + class restore_var_elem : public elem { public: - restore_mem (void *ptr, size_t size); - ~restore_mem (void); + restore_var_elem (T& ref, const T& val) + : e_ptr (&ref), e_val (val) { } - // For unwind_protect. - static void cleanup (void *ptr) - { - delete reinterpret_cast (ptr); - } + void run (void) { *e_ptr = e_val; } private: - - // No copying! - restore_mem (const restore_mem&); - void operator = (const restore_mem&); - - void *rptr, *sptr; - size_t rsize; + T *e_ptr, e_val; }; - typedef void (*cleanup_func) (void *ptr); + // 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 action_var_elem : public elem + { + public: + action_var_elem (void (*fcn) (T), T val) + : e_fcn (fcn), e_val (val) { } + + void run (void) { e_fcn (e_val); } + + private: + void (*e_fcn) (T); + T e_val; + }; typedef size_t frame_id_t; - typedef std::pair elem; + // Generic. Users may subclass elem to provide their own cleanup. + static void add (elem *el) + { + elt_list.push (el); + } static bool empty (void) { return elt_list.empty (); } - static void add (cleanup_func fptr, void *ptr = 0) - { - elt_list.push (elem (fptr, ptr)); - } - static void run (void) { - elem elt = elt_list.top (); + // Use auto_ptr, so that even if the following run () call throws an + // exception, we still clean up the element. + std::auto_ptr elt (elt_list.top ()); elt_list.pop (); - elt.first (elt.second); + elt->run (); } static void discard (void) { + // No need to use ato_ptr here. + elem *elt = elt_list.top (); elt_list.pop (); + + delete elt; } static frame_id_t begin_frame () @@ -158,29 +161,35 @@ tag_list.pop (); } + static void add (void (*fcn) (void *), void *ptr = 0) + { + elt_list.push (new fcn_elem (fcn, ptr)); + } + // Protect any variable. template static void protect_var (T& var) { - add (restore_var::cleanup, new restore_var (&var)); + elt_list.push (new restore_var_elem (var, var)); } // Protect any variable, value given. template static void protect_var (T& var, const T& val) { - add (restore_var::cleanup, new restore_var (&var, val)); + elt_list.push (new restore_var_elem (var, val)); } - // Protect an area of memory. - static void protect_mem (void *ptr, size_t size) + // Store a function pointer together with a single argument (passed by value). + template + static void add_action_var (void (*action) (T), T val) { - add (restore_mem::cleanup, new restore_mem (ptr, size)); + elt_list.push (new action_var_elem (action, val)); } private: - static std::stack elt_list; + static std::stack elt_list; static std::stack > tag_list; };