Mercurial > hg > octave-lyh
diff src/unwind-prot.cc @ 1:78fd87e624cb
[project @ 1993-08-08 01:13:40 by jwe]
Initial revision
author | jwe |
---|---|
date | Sun, 08 Aug 1993 01:13:40 +0000 |
parents | |
children | a99f28f5e351 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/src/unwind-prot.cc @@ -0,0 +1,334 @@ +// unwind-prot.cc -*- C++ -*- +/* + +Copyright (C) 1992, 1993 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include <stddef.h> + +#include "SLStack.h" + +#include "Matrix.h" + +#include "unwind-prot.h" +#include "error.h" +#include "utils.h" + +class unwind_elem +{ + public: + unwind_elem (void); + unwind_elem (char *t); + unwind_elem (cleanup_func f, void *p); + unwind_elem (const unwind_elem& el); + ~unwind_elem (void); + + unwind_elem& operator = (const unwind_elem& el); + + char *tag (void); + cleanup_func fptr (void); + void *ptr (void); + + private: + char *_tag; + cleanup_func _fptr; + void *_ptr; +}; + +unwind_elem::unwind_elem (void) +{ + _tag = (char *) NULL; + _fptr = (cleanup_func) NULL; + _ptr = (void *) NULL; +} + +unwind_elem::unwind_elem (char *t) +{ + _tag = strsave (t); + _fptr = (cleanup_func) NULL; + _ptr = (void *) NULL; +} + +unwind_elem::unwind_elem (cleanup_func f, void *p) +{ + _tag = (char *) NULL; + _fptr = f; + _ptr = p; +} + +unwind_elem::unwind_elem (const unwind_elem& el) +{ + _tag = strsave (el._tag); + _fptr = el._fptr; + _ptr = el._ptr; +} + +unwind_elem::~unwind_elem (void) +{ + delete [] _tag; +} + +unwind_elem& +unwind_elem::operator = (const unwind_elem& el) +{ + _tag = strsave (el._tag); + _fptr = el._fptr; + _ptr = el._ptr; + + return *this; +} + +char * +unwind_elem::tag (void) +{ + return _tag; +} + +cleanup_func +unwind_elem::fptr (void) +{ + return _fptr; +} + +void * +unwind_elem::ptr (void) +{ + return _ptr; +} + +static SLStack <unwind_elem> unwind_protect_list; + +void +add_unwind_protect (cleanup_func fptr, void *ptr) +{ + unwind_elem el (fptr, ptr); + unwind_protect_list.push (el); +} + +void +run_unwind_protect (void) +{ + unwind_elem el = unwind_protect_list.pop (); + + cleanup_func f = el.fptr (); + if (f != (cleanup_func) NULL) + f (el.ptr ()); +} + +void +discard_unwind_protect (void) +{ + unwind_protect_list.pop (); +} + +void +begin_unwind_frame (char *tag) +{ + unwind_elem elem (tag); + unwind_protect_list.push (elem); +} + +void +run_unwind_frame (char *tag) +{ + while (! unwind_protect_list.empty ()) + { + unwind_elem el = unwind_protect_list.pop (); + + cleanup_func f = el.fptr (); + if (f != (cleanup_func) NULL) + f (el.ptr ()); + + char *t = el.tag (); + if (t != (char *) NULL && strcmp (t, tag) == 0) + break; + } +} + +void +discard_unwind_frame (char *tag) +{ + while (! unwind_protect_list.empty ()) + { + unwind_elem el = unwind_protect_list.pop (); + char *t = el.tag (); + if (t != (char *) NULL && strcmp (t, tag) == 0) + break; + } +} + +void +run_all_unwind_protects (void) +{ + while (! unwind_protect_list.empty ()) + { + unwind_elem el = unwind_protect_list.pop (); + + cleanup_func f = el.fptr (); + if (f != (cleanup_func) NULL) + f (el.ptr ()); + } +} + +void +discard_all_unwind_protects (void) +{ + unwind_protect_list.clear (); +} + +void +matrix_cleanup (void *m) +{ + delete [] (double *) m; +} + +void +complex_matrix_cleanup (void *cm) +{ + delete [] (ComplexMatrix *) cm; +} + +class saved_variable +{ + public: + enum var_type { integer, generic_ptr, generic }; + + saved_variable (void); + saved_variable (int *p, int v); + saved_variable (void **p, void *v); + saved_variable (void *p, void *v, size_t sz); + ~saved_variable (void); + + void restore_value (void); + + private: + union + { + int *ptr_to_int; + void *gen_ptr; + void **ptr_to_gen_ptr; + }; + + union + { + int int_value; + void *gen_ptr_value; + }; + + var_type type_tag; + size_t size; +}; + +saved_variable::saved_variable (void) +{ + gen_ptr = (void *) NULL; + gen_ptr_value = (void *) NULL; + type_tag = generic; + size = 0; +} + +saved_variable::saved_variable (int *p, int v) +{ + type_tag = integer; + ptr_to_int = p; + int_value = v; + size = sizeof (int); +} + +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 *p, void *v, size_t sz) +{ + gen_ptr = v; + gen_ptr_value = new char [sz]; + memcpy (gen_ptr_value, v, sz); + size = sz; +} + +saved_variable::~saved_variable (void) +{ + if (type_tag == generic) + delete [] gen_ptr_value; +} + +void +saved_variable::restore_value (void) +{ + switch (type_tag) + { + case integer: + *ptr_to_int = int_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 (); + } +} + +static void +restore_saved_variable (void *s) +{ + saved_variable *sv = (saved_variable *) s; + sv->restore_value (); + delete sv; +} + +void +unwind_protect_int_internal (int *ptr, int value) +{ + saved_variable *s = new saved_variable (ptr, value); + add_unwind_protect (restore_saved_variable, (void *) s); +} + +void +unwind_protect_ptr_internal (void **ptr, void *value) +{ + saved_variable *s = new saved_variable (ptr, value); + add_unwind_protect (restore_saved_variable, (void *) s); +} + +void +unwind_protect_var_internal (void *ptr, void *value, size_t size) +{ + saved_variable *s = new saved_variable (ptr, value, size); + add_unwind_protect (restore_saved_variable, (void *) s); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; page-delimiter: "^/\\*" *** +;;; End: *** +*/