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 #if defined(CHECK_ERROR_DROP)
101  mutable SmartPtr<ARB_undropable_error> error;
102  GB_ERROR look() const { return error->look(); }
103 public:
104  explicit ARB_ERROR() : error(new ARB_undropable_error(NULp)) {}
105  ARB_ERROR(GB_ERROR gberr) : error(new ARB_undropable_error(gberr)) {}
106  GB_ERROR deliver() const { return error->deliver(); }
107  ARB_ERROR& operator = (GB_ERROR gberr) { error->Set(gberr); return *this; }
108 #else
109  GB_ERROR error;
110  GB_ERROR look() const { return error; }
111 public:
112  explicit ARB_ERROR() : error(NULp) {}
113  ARB_ERROR(GB_ERROR gberr) : error(gberr) {}
114  GB_ERROR deliver() const { return error; }
115  ARB_ERROR& operator = (GB_ERROR gberr) { error = gberr; return *this; }
116 #endif // CHECK_ERROR_DROP
117 
118  // common for both ARB_ERROR flavors:
119 private:
120  bool occurred() const { return look(); }
121 
122 public:
123  ARB_ERROR(const ARB_ERROR& err) : error(err.error) {}
124  ARB_ERROR& operator = (const ARB_ERROR& err) { // assigning an error to a new error
125  if (error != err.error) *this = err.deliver(); // delivers the error
126  return *this;
127  }
128 
129  operator bool() const { return occurred(); } // needed for 'if (!error)' and similar
130 
131  void set_handled() const {
132  arb_assert(occurred()); // oops - tried to handle an error that did not occur
133  deliver(); // deliver and drop
134  }
135 
136  void expect_no_error() const {
137  arb_assert(!occurred()); // oops - no error expected here
138  deliver(); // mark impossible errors as "used"
139  }
140 
141  GB_ERROR preserve() const { return look(); } // look, but do not deliver
142 
143 #if defined(DEBUG)
144  void dump() const {
145  printf("ARB_ERROR='%s'\n", look());
146  }
147 #endif // DEBUG
148 };
149 
150 class Validity {
151  // basically a bool telling whether sth is valid
152  // (if invalid -> knows why)
153  const char *why_invalid;
154 public:
155  Validity() : why_invalid(NULp) {}
156  Validity(bool valid, const char *why_invalid_)
157  : why_invalid(valid ? NULp : why_invalid_)
158  {}
159  Validity(const Validity& other) : why_invalid(other.why_invalid) {}
160  Validity& operator = (const Validity& other) {
161 #if defined(ASSERTION_USED)
162  arb_assert(!why_invalid); // attempt to overwrite invalidity!
163 #endif
164  why_invalid = other.why_invalid;
165  return *this;
166  }
167 
168  operator bool() const { return !why_invalid; }
169  const char *why_not() const { return why_invalid; }
170 
171  void assert_is_valid() const {
172 #if defined(ASSERTION_USED)
173  if (why_invalid) {
174  fprintf(stderr, "Invalid: %s\n", why_invalid);
175  arb_assert(0);
176  }
177 #endif
178  }
179 };
180 
181 #else
182 #error arb_error.h included twice
183 #endif // ARB_ERROR_H
#define arb_assert(cond)
Definition: arb_assert.h:245
ARB_ERROR(const ARB_ERROR &err)
Definition: arb_error.h:123
const char * GB_ERROR
Definition: arb_core.h:25
GB_ERROR preserve() const
Definition: arb_error.h:141
const char * why_not() const
Definition: arb_error.h:169
Validity(const Validity &other)
Definition: arb_error.h:159
GB_ERROR deliver() const
Definition: arb_error.h:114
Validity(bool valid, const char *why_invalid_)
Definition: arb_error.h:156
Validity & operator=(const Validity &other)
Definition: arb_error.h:160
Generic smart pointer.
Definition: smartptr.h:149
#define false
Definition: ureadseq.h:13
void set_handled() const
Definition: arb_error.h:131
void expect_no_error() const
Definition: arb_error.h:136
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:166
ARB_ERROR & operator=(GB_ERROR gberr)
Definition: arb_error.h:115
CONSTEXPR_INLINE bool valid(SpeciesCreationMode m)
Definition: ed4_class.hxx:2246
ARB_ERROR(GB_ERROR gberr)
Definition: arb_error.h:113
static int line
Definition: arb_a2ps.c:296
#define NULp
Definition: cxxforward.h:97
Validity()
Definition: arb_error.h:155
void assert_is_valid() const
Definition: arb_error.h:171