# HG changeset patch # User Jaroslav Hajek # Date 1245736544 -7200 # Node ID d58086453171b5a476cbb809b91e3fd4b3a453ce # Parent 14b1d34518586066123fa539c645b06911867469 refactor unwind_protect diff -r 14b1d3451858 -r d58086453171 src/ChangeLog --- a/src/ChangeLog Mon Jun 22 21:00:18 2009 -0400 +++ b/src/ChangeLog Tue Jun 23 07:55:44 2009 +0200 @@ -1,3 +1,12 @@ +2009-06-22 Jaroslav Hajek + + * unwind-prot.h (unwind_protect): Rewrite. + (unwind_protect::protect_var): New class. + (unwind_protect::protect_mem): New class. + * unwind-prot.cc (unwind_protect): Rewrite. + * pt-eval.cc (tree_evaluator::visit_try_catch_command): Delete frame + properly. + 2009-06-22 Jaroslav Hajek * ov-cell.cc (octave_cell::all_strings): Avoid duplicate conversions. diff -r 14b1d3451858 -r d58086453171 src/pt-eval.cc --- a/src/pt-eval.cc Mon Jun 22 21:00:18 2009 -0400 +++ b/src/pt-eval.cc Tue Jun 23 07:55:44 2009 +0200 @@ -900,7 +900,7 @@ unwind_protect::run (); // Also clear the frame marker. - unwind_protect::discard (); + unwind_protect::run_frame ("tree_evaluator::visit_try_catch_command"); } } diff -r 14b1d3451858 -r d58086453171 src/unwind-prot.cc --- a/src/unwind-prot.cc Mon Jun 22 21:00:18 2009 -0400 +++ b/src/unwind-prot.cc Tue Jun 23 07:55:44 2009 +0200 @@ -2,6 +2,7 @@ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2002, 2004, 2005, 2006, 2007, 2008 John W. Eaton +Copyright (C) 2009 VZLU Prague This file is part of Octave. @@ -28,303 +29,58 @@ #include #include -#include "CMatrix.h" - #include "error.h" #include "unwind-prot.h" #include "utils.h" -std::stack unwind_protect::elt_list; - -class -saved_variable -{ -public: - - enum var_type - { - boolean, - integer, - size_type, - string_type, - generic_ptr, - generic - }; +std::stack unwind_protect::elt_list; - saved_variable (void); - - saved_variable (bool *p, bool v); - - saved_variable (int *p, int v); - - saved_variable (size_t *p, size_t v); - - saved_variable (std::string *p, const std::string& v); - - saved_variable (void **p, void *v); - - ~saved_variable (void); - - void restore_value (void); - - static void restore (void *s); - -private: +std::stack > unwind_protect::tag_list; - union - { - bool *ptr_to_bool; - int *ptr_to_int; - size_t *ptr_to_size_t; - void *gen_ptr; - void **ptr_to_gen_ptr; - }; - - union - { - bool bool_value; - int int_value; - size_t size_t_value; - std::string *str_value; - void *gen_ptr_value; - }; - - var_type type_tag; - - size_t size; -}; - -saved_variable::saved_variable (void) +unwind_protect::restore_mem::restore_mem (void *ptr, size_t size) + : rptr (ptr), sptr (reinterpret_cast (new char[size])), rsize (size) { - gen_ptr = 0; - gen_ptr_value = 0; - type_tag = generic; - size = 0; -} - -saved_variable::saved_variable (bool *p, bool v) -{ - type_tag = boolean; - ptr_to_bool = p; - bool_value = v; - size = sizeof (bool); // Is this necessary? -} - -saved_variable::saved_variable (int *p, int v) -{ - type_tag = integer; - ptr_to_int = p; - int_value = v; - size = sizeof (int); // Is this necessary? -} - -saved_variable::saved_variable (size_t *p, size_t v) -{ - type_tag = size_type; - ptr_to_size_t = p; - size_t_value = v; - size = sizeof (size_t); // Is this necessary? + std::memcpy (sptr, rptr, size); } -saved_variable::saved_variable (std::string *p, const std::string& v) -{ - type_tag = string_type; - gen_ptr = p; - str_value = new std::string (v); - size = sizeof (std::string); // Is this necessary? -} - -saved_variable::saved_variable (void **p, void *v) -{ - type_tag = generic_ptr; - ptr_to_gen_ptr = p; - gen_ptr_value = v; - size = sizeof (void *); -} - -saved_variable::~saved_variable (void) -{ - switch (type_tag) - { - case string_type: - delete str_value; - break; - - case generic: - // FIXME - // delete [] gen_ptr_value; - break; - - default: - break; - } -} - -void -saved_variable::restore_value (void) +unwind_protect::restore_mem::~restore_mem (void) { - switch (type_tag) - { - case boolean: - *ptr_to_bool = bool_value; - break; - - case integer: - *ptr_to_int = int_value; - break; - - case size_type: - *ptr_to_size_t = size_t_value; - break; - - case string_type: - (static_cast (gen_ptr)) -> assign (*str_value); - break; - - case generic_ptr: - *ptr_to_gen_ptr = gen_ptr_value; - break; - - case generic: - memcpy (gen_ptr, gen_ptr_value, size); - break; - - default: - panic_impossible (); - break; - } -} - -void -saved_variable::restore (void *s) -{ - saved_variable *sv = static_cast (s); - sv->restore_value (); - delete sv; -} - -void -unwind_protect::add (unwind_elem::cleanup_func fptr, void *ptr) -{ - unwind_elem el (fptr, ptr); - elt_list.push (el); -} - -void -unwind_protect::run (void) -{ - unwind_elem el = elt_list.top (); - - elt_list.pop (); - - unwind_elem::cleanup_func f = el.fptr (); - - if (f) - f (el.ptr ()); -} - -void -unwind_protect::discard (void) -{ - elt_list.pop (); + std::memcpy (rptr, sptr, rsize); + delete [] reinterpret_cast (sptr); } void unwind_protect::begin_frame (const std::string& tag) { - unwind_elem elem (tag); - elt_list.push (elem); + tag_list.push (std::make_pair (tag, begin_frame ())); } void unwind_protect::run_frame (const std::string& tag) { - while (! elt_list.empty ()) + while (! tag_list.empty ()) { - unwind_elem el = elt_list.top (); - - elt_list.pop (); + std::pair top = tag_list.top (); + tag_list.pop (); - unwind_elem::cleanup_func f = el.fptr (); - - if (f) - f (el.ptr ()); - - if (tag == el.tag ()) - break; + run_frame (top.second); + if (top.first == tag) + break; } } void unwind_protect::discard_frame (const std::string& tag) { - while (! elt_list.empty ()) - { - unwind_elem el = elt_list.top (); - - elt_list.pop (); - - if (tag == el.tag ()) - break; - } -} - -void -unwind_protect::run_all (void) -{ - while (! elt_list.empty ()) + while (! tag_list.empty ()) { - unwind_elem el = elt_list.top (); - - elt_list.pop (); - - unwind_elem::cleanup_func f = el.fptr (); - - if (f) - f (el.ptr ()); - } -} - -void -unwind_protect::discard_all (void) -{ - while (! elt_list.empty ()) - elt_list.pop (); -} + std::pair top = tag_list.top (); + tag_list.pop (); -void -unwind_protect::save_bool (bool *ptr, bool value) -{ - saved_variable *s = new saved_variable (ptr, value); - add (saved_variable::restore, s); -} - -void -unwind_protect::save_int (int *ptr, int value) -{ - saved_variable *s = new saved_variable (ptr, value); - add (saved_variable::restore, s); -} - -void -unwind_protect::save_size_t (size_t *ptr, size_t value) -{ - saved_variable *s = new saved_variable (ptr, value); - add (saved_variable::restore, s); -} - -void -unwind_protect::save_str (std::string *ptr, const std::string& value) -{ - saved_variable *s = new saved_variable (ptr, value); - add (saved_variable::restore, s); -} - -void -unwind_protect::save_ptr (void **ptr, void *value) -{ - saved_variable *s = new saved_variable (ptr, value); - add (saved_variable::restore, s); + run_frame (top.second); + if (top.first == tag) + break; + } } /* diff -r 14b1d3451858 -r d58086453171 src/unwind-prot.h --- a/src/unwind-prot.h Mon Jun 22 21:00:18 2009 -0400 +++ b/src/unwind-prot.h Tue Jun 23 07:55:44 2009 +0200 @@ -2,6 +2,7 @@ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2004, 2005, 2006, 2007, 2008 John W. Eaton +Copyright (C) 2009 VZLU Prague This file is part of Octave. @@ -28,52 +29,7 @@ #include #include - -class -OCTINTERP_API -unwind_elem -{ -public: - - typedef void (*cleanup_func) (void *ptr); - - unwind_elem (void) - : ue_tag (), ue_fptr (0), ue_ptr (0) { } - - unwind_elem (const std::string &t) - : ue_tag (t), ue_fptr (0), ue_ptr (0) { } - - unwind_elem (cleanup_func f, void *p) - : ue_tag (), ue_fptr (f), ue_ptr (p) { } - - unwind_elem (const unwind_elem& el) - : ue_tag (el.ue_tag), ue_fptr (el.ue_fptr), ue_ptr (el.ue_ptr) { } - - ~unwind_elem (void) { } - - unwind_elem& operator = (const unwind_elem& el) - { - ue_tag = el.ue_tag; - ue_fptr = el.ue_fptr; - ue_ptr = el.ue_ptr; - - return *this; - } - - std::string tag (void) { return ue_tag; } - - cleanup_func fptr (void) { return ue_fptr; } - - void *ptr (void) { return ue_ptr; } - -private: - - std::string ue_tag; - - cleanup_func ue_fptr; - - void *ue_ptr; -}; +#include class OCTINTERP_API @@ -81,64 +37,174 @@ { public: - static void add (unwind_elem::cleanup_func fptr, void *ptr = 0); + // This template class can be used to restore value of a variable of any + // class posessing a copy constructor and assignment operator. - static void run (void); + template + class + restore_var + { + 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; } - static void discard (void); + // For unwind_protect. + static void cleanup (void *ptr) + { + delete reinterpret_cast (ptr); + } + + private: - static void begin_frame (const std::string& tag); + // No copying! + void operator = (const restore_var&); + + T *rptr, rval; + }; + + // This class is used to restore arbitrary memory area using std::memcpy. - static void run_frame (const std::string& tag); + class + restore_mem + { + public: + restore_mem (void *ptr, size_t size); + ~restore_mem (void); - static void discard_frame (const std::string& tag); + // For unwind_protect. + static void cleanup (void *ptr) + { + delete reinterpret_cast (ptr); + } + + private: + + // No copying! + void operator = (const restore_mem&); - static void run_all (void); + void *rptr, *sptr; + size_t rsize; + }; + + typedef void (*cleanup_func) (void *ptr); + + typedef size_t frame_id_t; + + typedef std::pair elem; - static void discard_all (void); + 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 (); + elt_list.pop (); - // Ways to save variables. + elt.first (elt.second); + } - static void save_bool (bool *ptr, bool value); + static void discard (void) + { + elt_list.pop (); + } + + static frame_id_t begin_frame () + { + return elt_list.size (); + } - static void save_int (int *ptr, int value); + static void run_frame (frame_id_t frame_id) + { + while (elt_list.size () > frame_id) + run (); + } - static void save_size_t (size_t *ptr, size_t value); + static void discard_frame (frame_id_t frame_id) + { + while (elt_list.size () > frame_id) + discard (); + } + + // String tags are deprecated. Use the above trio. + + static void begin_frame (const std::string& tag) GCC_ATTR_DEPRECATED; + + static void run_frame (const std::string& tag) GCC_ATTR_DEPRECATED; + + static void discard_frame (const std::string& tag) GCC_ATTR_DEPRECATED; - static void save_str (std::string *ptr, const std::string& value); + static void run_all (void) + { + run_frame (0); + while (! tag_list.empty ()) + tag_list.pop (); + } - static void save_ptr (void **ptr, void *value); + static void discard_all (void) + { + discard_frame (0); + while (! tag_list.empty ()) + tag_list.pop (); + } - static void save_var (void *ptr, void *value, size_t size); + // Protect any variable. + template + static void protect_var (T& var) + { + add (restore_var::cleanup, new restore_var (&var)); + } - static std::stack elt_list; + // Protect any variable, value given. + template + static void protect_var (T& var, const T& val) + { + add (restore_var::cleanup, new restore_var (&var, val)); + } + + // Protect an area of memory. + static void protect_mem (void *ptr, size_t size) + { + add (restore_mem::cleanup, new restore_mem (ptr, size)); + } + +private: + + static std::stack elt_list; + + static std::stack > tag_list; }; -// We could get by without these macros, but they are nice to have... +// Backward compatibility macros. Avoid them; use protect_var directly. #define unwind_protect_bool(b) \ - unwind_protect::save_bool (&(b), (b)) + unwind_protect::protect_var (b) #define unwind_protect_int(i) \ - unwind_protect::save_int (&(i), (i)) + unwind_protect::protect_var (i) #define unwind_protect_size_t(i) \ - unwind_protect::save_size_t (&(i), (i)) + unwind_protect::protect_var (i) #define unwind_protect_str(s) \ - unwind_protect::save_str (&(s), (s)) + unwind_protect::protect_var (s) #define unwind_protect_ptr(p) \ - unwind_protect::save_ptr (reinterpret_cast (&(p)), \ - reinterpret_cast (p)) + unwind_protect::protect_var (p) #define unwind_protect_fptr(p) \ - unwind_protect::save_ptr (reinterpret_cast (&(p)), \ - FCN_PTR_CAST (void *, p)) + unwind_protect::protect_var (p) #define unwind_protect_const_ptr(p) \ - unwind_protect::save_ptr (const_cast (reinterpret_cast (&(p))), \ - const_cast (reinterpret_cast (p))) + unwind_protect::protect_var (p) #endif