source: tags/arb-6.0/TEMPLATES/arb_error.h

Last change on this file was 8917, checked in by westram, 12 years ago
  • 'arb_ntree —help' no longer starts up GUI
File size: 4.9 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 NULL)
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     = NULL;
85        delivered = true;
86    }
87
88    void Set(GB_ERROR err) {
89        arb_assert(gberr == NULL);                  // 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(NULL)) {}
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(NULL) {}
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() != NULL; }
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
150#else
151#error arb_error.h included twice
152#endif // ARB_ERROR_H
Note: See TracBrowser for help on using the repository browser.