comparison src/unwind-prot.h @ 9376:d58086453171

refactor unwind_protect
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 23 Jun 2009 07:55:44 +0200
parents eb63fbe60fab
children 8bec23396924
comparison
equal deleted inserted replaced
9375:14b1d3451858 9376:d58086453171
1 /* 1 /*
2 2
3 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2004, 3 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2004,
4 2005, 2006, 2007, 2008 John W. Eaton 4 2005, 2006, 2007, 2008 John W. Eaton
5 Copyright (C) 2009 VZLU Prague
5 6
6 This file is part of Octave. 7 This file is part of Octave.
7 8
8 Octave is free software; you can redistribute it and/or modify it 9 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the 10 under the terms of the GNU General Public License as published by the
26 27
27 #include <cstddef> 28 #include <cstddef>
28 29
29 #include <string> 30 #include <string>
30 #include <stack> 31 #include <stack>
31 32 #include <utility>
32 class
33 OCTINTERP_API
34 unwind_elem
35 {
36 public:
37
38 typedef void (*cleanup_func) (void *ptr);
39
40 unwind_elem (void)
41 : ue_tag (), ue_fptr (0), ue_ptr (0) { }
42
43 unwind_elem (const std::string &t)
44 : ue_tag (t), ue_fptr (0), ue_ptr (0) { }
45
46 unwind_elem (cleanup_func f, void *p)
47 : ue_tag (), ue_fptr (f), ue_ptr (p) { }
48
49 unwind_elem (const unwind_elem& el)
50 : ue_tag (el.ue_tag), ue_fptr (el.ue_fptr), ue_ptr (el.ue_ptr) { }
51
52 ~unwind_elem (void) { }
53
54 unwind_elem& operator = (const unwind_elem& el)
55 {
56 ue_tag = el.ue_tag;
57 ue_fptr = el.ue_fptr;
58 ue_ptr = el.ue_ptr;
59
60 return *this;
61 }
62
63 std::string tag (void) { return ue_tag; }
64
65 cleanup_func fptr (void) { return ue_fptr; }
66
67 void *ptr (void) { return ue_ptr; }
68
69 private:
70
71 std::string ue_tag;
72
73 cleanup_func ue_fptr;
74
75 void *ue_ptr;
76 };
77 33
78 class 34 class
79 OCTINTERP_API 35 OCTINTERP_API
80 unwind_protect 36 unwind_protect
81 { 37 {
82 public: 38 public:
83 39
84 static void add (unwind_elem::cleanup_func fptr, void *ptr = 0); 40 // This template class can be used to restore value of a variable of any
85 41 // class posessing a copy constructor and assignment operator.
86 static void run (void); 42
87 43 template <class T>
88 static void discard (void); 44 class
89 45 restore_var
90 static void begin_frame (const std::string& tag); 46 {
91 47 public:
92 static void run_frame (const std::string& tag); 48 restore_var (T *ptr, const T& val)
93 49 : rptr (ptr), rval(val) { }
94 static void discard_frame (const std::string& tag); 50 restore_var (T *ptr)
95 51 : rptr (ptr), rval(*ptr) { }
96 static void run_all (void); 52 ~restore_var (void)
97 53 { *rptr = rval; }
98 static void discard_all (void); 54
99 55 // For unwind_protect.
100 // Ways to save variables. 56 static void cleanup (void *ptr)
101 57 {
102 static void save_bool (bool *ptr, bool value); 58 delete reinterpret_cast<restore_var *> (ptr);
103 59 }
104 static void save_int (int *ptr, int value); 60
105 61 private:
106 static void save_size_t (size_t *ptr, size_t value); 62
107 63 // No copying!
108 static void save_str (std::string *ptr, const std::string& value); 64 void operator = (const restore_var&);
109 65
110 static void save_ptr (void **ptr, void *value); 66 T *rptr, rval;
111 67 };
112 static void save_var (void *ptr, void *value, size_t size); 68
113 69 // This class is used to restore arbitrary memory area using std::memcpy.
114 static std::stack<unwind_elem> elt_list; 70
71 class
72 restore_mem
73 {
74 public:
75 restore_mem (void *ptr, size_t size);
76 ~restore_mem (void);
77
78 // For unwind_protect.
79 static void cleanup (void *ptr)
80 {
81 delete reinterpret_cast<restore_mem *> (ptr);
82 }
83
84 private:
85
86 // No copying!
87 void operator = (const restore_mem&);
88
89 void *rptr, *sptr;
90 size_t rsize;
91 };
92
93 typedef void (*cleanup_func) (void *ptr);
94
95 typedef size_t frame_id_t;
96
97 typedef std::pair<cleanup_func, void *> elem;
98
99 static bool empty (void)
100 { return elt_list.empty (); }
101
102 static void add (cleanup_func fptr, void *ptr = 0)
103 {
104 elt_list.push (elem (fptr, ptr));
105 }
106
107 static void run (void)
108 {
109 elem elt = elt_list.top ();
110 elt_list.pop ();
111
112 elt.first (elt.second);
113 }
114
115 static void discard (void)
116 {
117 elt_list.pop ();
118 }
119
120 static frame_id_t begin_frame ()
121 {
122 return elt_list.size ();
123 }
124
125 static void run_frame (frame_id_t frame_id)
126 {
127 while (elt_list.size () > frame_id)
128 run ();
129 }
130
131 static void discard_frame (frame_id_t frame_id)
132 {
133 while (elt_list.size () > frame_id)
134 discard ();
135 }
136
137 // String tags are deprecated. Use the above trio.
138
139 static void begin_frame (const std::string& tag) GCC_ATTR_DEPRECATED;
140
141 static void run_frame (const std::string& tag) GCC_ATTR_DEPRECATED;
142
143 static void discard_frame (const std::string& tag) GCC_ATTR_DEPRECATED;
144
145 static void run_all (void)
146 {
147 run_frame (0);
148 while (! tag_list.empty ())
149 tag_list.pop ();
150 }
151
152 static void discard_all (void)
153 {
154 discard_frame (0);
155 while (! tag_list.empty ())
156 tag_list.pop ();
157 }
158
159 // Protect any variable.
160 template <class T>
161 static void protect_var (T& var)
162 {
163 add (restore_var<T>::cleanup, new restore_var<T> (&var));
164 }
165
166 // Protect any variable, value given.
167 template <class T>
168 static void protect_var (T& var, const T& val)
169 {
170 add (restore_var<T>::cleanup, new restore_var<T> (&var, val));
171 }
172
173 // Protect an area of memory.
174 static void protect_mem (void *ptr, size_t size)
175 {
176 add (restore_mem::cleanup, new restore_mem (ptr, size));
177 }
178
179 private:
180
181 static std::stack<elem> elt_list;
182
183 static std::stack<std::pair <std::string, frame_id_t> > tag_list;
115 }; 184 };
116 185
117 // We could get by without these macros, but they are nice to have... 186 // Backward compatibility macros. Avoid them; use protect_var directly.
118 187
119 #define unwind_protect_bool(b) \ 188 #define unwind_protect_bool(b) \
120 unwind_protect::save_bool (&(b), (b)) 189 unwind_protect::protect_var (b)
121 190
122 #define unwind_protect_int(i) \ 191 #define unwind_protect_int(i) \
123 unwind_protect::save_int (&(i), (i)) 192 unwind_protect::protect_var (i)
124 193
125 #define unwind_protect_size_t(i) \ 194 #define unwind_protect_size_t(i) \
126 unwind_protect::save_size_t (&(i), (i)) 195 unwind_protect::protect_var (i)
127 196
128 #define unwind_protect_str(s) \ 197 #define unwind_protect_str(s) \
129 unwind_protect::save_str (&(s), (s)) 198 unwind_protect::protect_var (s)
130 199
131 #define unwind_protect_ptr(p) \ 200 #define unwind_protect_ptr(p) \
132 unwind_protect::save_ptr (reinterpret_cast<void **> (&(p)), \ 201 unwind_protect::protect_var (p)
133 reinterpret_cast<void *> (p))
134 202
135 #define unwind_protect_fptr(p) \ 203 #define unwind_protect_fptr(p) \
136 unwind_protect::save_ptr (reinterpret_cast<void **> (&(p)), \ 204 unwind_protect::protect_var (p)
137 FCN_PTR_CAST (void *, p))
138 205
139 #define unwind_protect_const_ptr(p) \ 206 #define unwind_protect_const_ptr(p) \
140 unwind_protect::save_ptr (const_cast<void **> (reinterpret_cast<const void **> (&(p))), \ 207 unwind_protect::protect_var (p)
141 const_cast<void *> (reinterpret_cast<const void *> (p)))
142 208
143 #endif 209 #endif
144 210
145 /* 211 /*
146 ;;; Local Variables: *** 212 ;;; Local Variables: ***