ARB
arb_error.h
Go to the documentation of this file.
1 // ================================================================ //
2 // //
3 // File : arb_error.h //
4 // Purpose : replacement for GB_ERROR //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in November 2009 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // ================================================================ //
11 
12 #ifndef ARB_ERROR_H
13 #define ARB_ERROR_H
14 
15 // ARB_ERROR is a dropin replacement for GB_ERROR (C++ only)
16 //
17 // If CHECK_ERROR_DROP is undefined (e.g. in NDEBUG version)
18 // there should be nearly no runtime overhead compared with plain GB_ERROR
19 //
20 // If CHECK_ERROR_DROP is defined
21 // the following actions cause an assertion failure:
22 //
23 // * not "using" an error (regardless whether an error occurred or not)
24 // * "using" an error several times (regardless whether an error occurred or not)
25 // * overwriting an error (if error is not NULp)
26 // * declaring errors as global variables
27 //
28 // Code changes needed:
29 // * replace GB_ERROR by ARB_ERROR
30 // * use error.deliver() whereever an existing error is "used"
31 // * rewrite code that uses 'static GB_ERROR' (no longer allowed)
32 //
33 // "Using" an error means e.g.
34 // * display error to user (e.g. aw_message_if())
35 // * construct a new error based on an error (e.g. GB_end_transaction)
36 //
37 // Sometimes an error result is known to be always no error.
38 // In this case use error.expect_no_error() to mark the error as "used"
39 
40 
41 #ifndef SMARTPTR_H
42 #include <smartptr.h>
43 #endif
44 
45 #if defined(DEBUG)
46 #define CHECK_ERROR_DROP
47 #if defined(DEVEL_RALF)
48 // #define EXTRA_ERROR_INFO
49 #endif // DEVEL_RALF
50 #endif // DEBUG
51 
52 #if defined(CHECK_ERROR_DROP)
53 
54 class ARB_undropable_error : virtual Noncopyable {
55  GB_ERROR gberr;
56  bool delivered;
57 #if defined(EXTRA_ERROR_INFO)
58  const char *file;
59  size_t line;
60 #endif // EXTRA_ERROR_INFO
61 public:
62  ARB_undropable_error(GB_ERROR gberr_) : gberr(gberr_), delivered(false)
63 #if defined(EXTRA_ERROR_INFO)
64  , file(__FILE__), line(__LINE__)
65 #endif // EXTRA_ERROR_INFO
66  {}
67  ~ARB_undropable_error() {
68  arb_assert(delivered); // oops - error has been dropped
69 
70  // Note: if this fails from inside exit() a static ARB_ERROR was declared
71  // This is no longer allowed
72  }
73 
74  GB_ERROR deliver() {
75  GB_ERROR err = gberr;
76  drop();
77  return err;
78  }
79 
80  GB_ERROR look() const { return gberr; }
81 
82  void drop() {
83  arb_assert(!delivered); // oops - error delivered/dropped twice
84  gberr = NULp;
85  delivered = true;
86  }
87 
88  void Set(GB_ERROR err) {
89  arb_assert(!gberr); // oops - you are trying to overwrite an existing error
90  gberr = err;
91  delivered = false;
92  }
93 };
94 
95 #endif // CHECK_ERROR_DROP
96 
97 
98 
99 class ARB_ERROR {
100  // unittest at ../SL/HEADERTESTS/arb_error.cxx@TEST_class_ARB_ERROR
101 
102 #if defined(CHECK_ERROR_DROP)
103  mutable SmartPtr<ARB_undropable_error> error;
104  GB_ERROR look() const { return error->look(); }
105 public:
106  explicit ARB_ERROR() : error(new ARB_undropable_error(NULp)) {}
107  ARB_ERROR(GB_ERROR gberr) : error(new ARB_undropable_error(gberr)) {}
108  GB_ERROR deliver() const { return error->deliver(); }
109  ARB_ERROR& operator = (GB_ERROR gberr) { error->Set(gberr); return *this; }
110 #else
111  GB_ERROR error;
112  GB_ERROR look() const { return error; }
113 public:
114  explicit ARB_ERROR() : error(NULp) {}
115  ARB_ERROR(GB_ERROR gberr) : error(gberr) {}
116  GB_ERROR deliver() const { return error; }
117  ARB_ERROR& operator = (GB_ERROR gberr) { error = gberr; return *this; }
118 #endif // CHECK_ERROR_DROP
119 
120  // common for both ARB_ERROR flavors:
121 private:
122  bool occurred() const { return look(); }
123 
124 public:
125  ARB_ERROR(const ARB_ERROR& err) : error(err.error) {}
126  ARB_ERROR& operator = (const ARB_ERROR& err) { // assigning an error to a new error
127  if (error != err.error) *this = err.deliver(); // delivers the error
128  return *this;
129  }
130 
131  operator bool() const { return occurred(); } // needed for 'if (!error)' and similar
132 
133  void set_handled() const {
134  arb_assert(occurred()); // oops - tried to handle an error that did not occur
135  deliver(); // deliver and drop
136  }
137 
138  void expect_no_error() const {
139  arb_assert(!occurred()); // oops - no error expected here
140  deliver(); // mark impossible errors as "used"
141  }
142 
143  GB_ERROR preserve() const { return look(); } // look, but do not deliver
144 
145 #if defined(DEBUG)
146  void dump() const {
147  printf("ARB_ERROR='%s'\n", look());
148  }
149 #endif // DEBUG
150 };
151 
152 class Validity {
153  // basically a bool telling whether sth is valid
154  // (if invalid -> knows why)
155  const char *why_invalid;
156 public:
157  Validity() : why_invalid(NULp) {}
158  Validity(bool valid, const char *why_invalid_)
159  : why_invalid(valid ? NULp : why_invalid_)
160  {}
161  Validity(const Validity& other) : why_invalid(other.why_invalid) {}
162  Validity& operator = (const Validity& other) {
163 #if defined(ASSERTION_USED)
164  arb_assert(!why_invalid); // attempt to overwrite invalidity!
165 #endif
166  why_invalid = other.why_invalid;
167  return *this;
168  }
169 
170  operator bool() const { return !why_invalid; }
171  const char *why_not() const { return why_invalid; }
172 
173  void assert_is_valid() const {
174 #if defined(ASSERTION_USED)
175  if (why_invalid) {
176  fprintf(stderr, "Invalid: %s\n", why_invalid);
177  arb_assert(0);
178  }
179 #endif
180  }
181 };
182 
183 #else
184 #error arb_error.h included twice
185 #endif // ARB_ERROR_H
#define arb_assert(cond)
Definition: arb_assert.h:245
ARB_ERROR(const ARB_ERROR &err)
Definition: arb_error.h:125
const char * GB_ERROR
Definition: arb_core.h:25
GB_ERROR preserve() const
Definition: arb_error.h:143
const char * why_not() const
Definition: arb_error.h:171
Validity(const Validity &other)
Definition: arb_error.h:161
GB_ERROR deliver() const
Definition: arb_error.h:116
Validity(bool valid, const char *why_invalid_)
Definition: arb_error.h:158
Validity & operator=(const Validity &other)
Definition: arb_error.h:162
Generic smart pointer.
Definition: smartptr.h:149
#define false
Definition: ureadseq.h:13
void set_handled() const
Definition: arb_error.h:133
void expect_no_error() const
Definition: arb_error.h:138
GB_write_int const char GB_write_autoconv_string WRITE_SKELETON(write_pointer, GBDATA *,"%p", GB_write_pointer) char *AW_awa if)(!gb_var) return strdup("")
Definition: AW_awar.cxx:163
ARB_ERROR & operator=(GB_ERROR gberr)
Definition: arb_error.h:117
CONSTEXPR_INLINE bool valid(SpeciesCreationMode m)
Definition: ed4_class.hxx:2247
ARB_ERROR(GB_ERROR gberr)
Definition: arb_error.h:115
static int line
Definition: arb_a2ps.c:296
#define NULp
Definition: cxxforward.h:116
Validity()
Definition: arb_error.h:157
void assert_is_valid() const
Definition: arb_error.h:173