Mercurial > hg > octave-max
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: *** |