source: branches/alilink/TEMPLATES/arb_error.h

Last change on this file was 16768, checked in by westram, 7 years ago
File size: 5.8 KB
Line 
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
54class 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
61public:
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
99class ARB_ERROR {
100#if defined(CHECK_ERROR_DROP)
101    mutable SmartPtr<ARB_undropable_error> error;
102    GB_ERROR look() const { return error->look(); }
103public:
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; }
111public:
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:
119private:
120    bool occurred() const { return look(); }
121
122public:
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
150class Validity {
151    // basically a bool telling whether sth is valid
152    // (if invalid -> knows why)
153    const char *why_invalid;
154public:
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
Note: See TracBrowser for help on using the repository browser.