Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #if !defined (octave_unwind_prot_h)
00025 #define octave_unwind_prot_h 1
00026
00027 #include <cstddef>
00028
00029 #include <string>
00030 #include <memory>
00031
00032
00033 class
00034 OCTINTERP_API
00035 unwind_protect
00036 {
00037 public:
00038
00039
00040
00041 class elem
00042 {
00043 elem *next;
00044
00045 public:
00046 elem (void) : next (0) { }
00047
00048 virtual void run (void) { }
00049
00050 virtual ~elem (void) { }
00051
00052 friend class unwind_protect;
00053
00054 private:
00055
00056
00057
00058 elem (const elem&);
00059
00060 elem& operator = (const elem&);
00061 };
00062
00063
00064
00065 class fcn_elem : public elem
00066 {
00067 public:
00068 fcn_elem (void (*fptr) (void))
00069 : e_fptr (fptr) { }
00070
00071 void run (void) { e_fptr (); }
00072
00073 private:
00074 void (*e_fptr) (void);
00075 };
00076
00077
00078
00079
00080 template <class T>
00081 class fcn_arg_elem : public elem
00082 {
00083 public:
00084 fcn_arg_elem (void (*fcn) (T), T arg)
00085 : e_fcn (fcn), e_arg (arg) { }
00086
00087 void run (void) { e_fcn (e_arg); }
00088
00089 private:
00090
00091
00092
00093 fcn_arg_elem (const fcn_arg_elem&);
00094
00095 fcn_arg_elem& operator = (const fcn_arg_elem&);
00096
00097 void (*e_fcn) (T);
00098 T e_arg;
00099 };
00100
00101
00102
00103
00104 template <class T>
00105 class fcn_crefarg_elem : public elem
00106 {
00107 public:
00108 fcn_crefarg_elem (void (*fcn) (const T&), T arg)
00109 : e_fcn (fcn), e_arg (arg) { }
00110
00111 void run (void) { e_fcn (e_arg); }
00112
00113 private:
00114 void (*e_fcn) (const T&);
00115 T e_arg;
00116 };
00117
00118
00119
00120 template <class T>
00121 class method_elem : public elem
00122 {
00123 public:
00124 method_elem (T *obj, void (T::*method) (void))
00125 : e_obj (obj), e_method (method) { }
00126
00127 void run (void) { (e_obj->*e_method) (); }
00128
00129 private:
00130
00131 T *e_obj;
00132 void (T::*e_method) (void);
00133
00134
00135
00136 method_elem (const method_elem&);
00137
00138 method_elem operator = (const method_elem&);
00139 };
00140
00141
00142
00143 template <class T>
00144 class restore_var_elem : public elem
00145 {
00146 public:
00147 restore_var_elem (T& ref, const T& val)
00148 : e_ptr (&ref), e_val (val) { }
00149
00150 void run (void) { *e_ptr = e_val; }
00151
00152 private:
00153
00154
00155
00156 restore_var_elem (const restore_var_elem&);
00157
00158 restore_var_elem& operator = (const restore_var_elem&);
00159
00160 T *e_ptr, e_val;
00161 };
00162
00163
00164
00165 template <class T>
00166 class delete_ptr_elem : public elem
00167 {
00168 public:
00169 delete_ptr_elem (T *ptr)
00170 : e_ptr (ptr) { }
00171
00172 void run (void) { delete e_ptr; }
00173
00174 private:
00175
00176 T *e_ptr;
00177
00178
00179
00180 delete_ptr_elem (const delete_ptr_elem&);
00181
00182 delete_ptr_elem operator = (const delete_ptr_elem&);
00183 };
00184
00185 unwind_protect (void) : head () { }
00186
00187 void add (elem *new_elem)
00188 {
00189 new_elem->next = head;
00190 head = new_elem;
00191 }
00192
00193
00194 void add (void (*fcn) (void *), void *ptr = 0)
00195 {
00196 add (new fcn_arg_elem<void *> (fcn, ptr));
00197 }
00198
00199
00200 void add_fcn (void (*fcn) (void))
00201 {
00202 add (new fcn_elem (fcn));
00203 }
00204
00205
00206 template <class T>
00207 void add_fcn (void (*action) (T), T val)
00208 {
00209 add (new fcn_arg_elem<T> (action, val));
00210 }
00211
00212
00213 template <class T>
00214 void add_fcn (void (*action) (const T&), T val)
00215 {
00216 add (new fcn_crefarg_elem<T> (action, val));
00217 }
00218
00219
00220 template <class T>
00221 void add_method (T *obj, void (T::*method) (void))
00222 {
00223 add (new method_elem<T> (obj, method));
00224 }
00225
00226
00227
00228 template <class T>
00229 void add_delete (T *obj)
00230 {
00231 add (new delete_ptr_elem<T> (obj));
00232 }
00233
00234
00235 template <class T>
00236 void protect_var (T& var)
00237 {
00238 add (new restore_var_elem<T> (var, var));
00239 }
00240
00241
00242 template <class T>
00243 void protect_var (T& var, const T& val)
00244 {
00245 add (new restore_var_elem<T> (var, val));
00246 }
00247
00248 operator bool (void) const
00249 {
00250 return head != 0;
00251 }
00252
00253 void run_top (void)
00254 {
00255 if (head)
00256 {
00257
00258 std::auto_ptr<elem> ptr (head);
00259 head = ptr->next;
00260 ptr->run ();
00261 }
00262 }
00263
00264 void run_top (int num)
00265 {
00266 while (num-- > 0)
00267 run_top ();
00268 }
00269
00270 void discard_top (void)
00271 {
00272 if (head)
00273 {
00274 elem *ptr = head;
00275 head = ptr->next;
00276 delete ptr;
00277 }
00278 }
00279
00280 void discard_top (int num)
00281 {
00282 while (num-- > 0)
00283 discard_top ();
00284 }
00285
00286 void run (void)
00287 {
00288 while (head)
00289 run_top ();
00290 }
00291
00292 void discard (void)
00293 {
00294 while (head)
00295 discard_top ();
00296 }
00297
00298
00299
00300
00301 ~unwind_protect (void)
00302 {
00303 run ();
00304 }
00305
00306 private:
00307
00308 elem *head;
00309
00310
00311
00312 unwind_protect (const unwind_protect&);
00313
00314 unwind_protect& operator = (const unwind_protect&);
00315 };
00316
00317
00318
00319
00320
00321 class
00322 OCTINTERP_API
00323 unwind_protect_safe : public unwind_protect
00324 {
00325 static void gripe_exception (void);
00326
00327 public:
00328 ~unwind_protect_safe (void)
00329 {
00330 while (*this)
00331 {
00332 try
00333 {
00334 run_top ();
00335 }
00336 catch (...)
00337 {
00338 gripe_exception ();
00339 }
00340 }
00341 }
00342 };
00343
00344 #endif