00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #ifndef W_ERROR_H
00054 #define W_ERROR_H
00055
00056 #include "w_defines.h"
00057
00058
00059
00060
00061 #ifdef __GNUG__
00062 #pragma interface
00063 #endif
00064
00065 #include "fc_error_enum_gen.h"
00066 #include "tls.h"
00067 #include "w_base.h"
00068
00069 #define USE_BLOCK_ALLOC_FOR_W_ERROR_T 1
00070 #if USE_BLOCK_ALLOC_FOR_W_ERROR_T
00071 DECLARE_TLS_SCHWARZ(w_error_alloc);
00072 #endif
00073
00074
00075
00076
00077
00078 struct w_error_info_t {
00079 w_base_t::uint4_t err_num;
00080 const char *errstr;
00081 };
00082
00083
00084
00085
00086
00087
00088 class w_error_t : public w_base_t {
00089 public:
00090 typedef w_error_info_t info_t;
00091
00092
00093
00094
00095
00096
00097
00098 typedef uint4_t err_num_t;
00099
00100
00101 const err_num_t err_num;
00102
00103 const char* const file;
00104 const uint4_t line;
00105 const int4_t sys_err_num;
00106
00107 w_error_t* next() { return _next; }
00108 w_error_t const* next() const { return _next; }
00109
00110 w_error_t& add_trace_info(
00111 const char* const filename,
00112 uint4_t line_num);
00113
00114 w_error_t& clear_more_info_msg();
00115 w_error_t& append_more_info_msg(const char* more_info);
00116 const char* get_more_info_msg() const;
00117 void claim();
00118 void verify_owner() const;
00119
00120 ostream &print_error(ostream &o) const;
00121
00122 #if USE_BLOCK_ALLOC_FOR_W_ERROR_T
00123 void operator delete(void* p);
00124
00125
00126
00127
00128
00129 #if W_DEBUG_LEVEL > 1
00130 #define DEBUG_BLOCK_ALLOC_MARK_FOR_DELETION(p) if(p) (p)->debug_mark_for_deletion();
00131 #define CHECK_DEBUG_BLOCK_ALLOC_MARKED_FOR_DELETION(p) \
00132 if(p && p != no_error) {w_assert0((p)->debug_is_marked_for_deletion() ); }
00133 private:
00134 bool marked;
00135 void debug_mark_for_deletion() { marked = true; }
00136 bool debug_is_marked_for_deletion() const { return marked == true; }
00137 public:
00138 #else
00139 #define DEBUG_BLOCK_ALLOC_MARK_FOR_DELETION(p)
00140 #define CHECK_DEBUG_BLOCK_ALLOC_MARKED_FOR_DELETION(p)
00141 #endif
00142 #else
00143 #define CHECK_DEBUG_BLOCK_ALLOC_MARKED_FOR_DELETION(p)
00144 #endif
00145
00146 static w_error_t* make(
00147 const char* const filename,
00148 uint4_t line_num,
00149 err_num_t err_num,
00150 w_error_t* list = 0,
00151 const char* more_info = 0);
00152 static w_error_t* make(
00153 const char* const filename,
00154 uint4_t line_num,
00155 err_num_t err_num,
00156 uint4_t sys_err,
00157 w_error_t* list = 0,
00158 const char* more_info = 0);
00159
00160 static bool insert(
00161 const char *modulename,
00162 const info_t info[],
00163 uint4_t count);
00164
00165 static const w_error_t no_error_instance;
00166 static w_error_t* const no_error;
00167 static const char* error_string(err_num_t err_num);
00168 static const char* module_name(err_num_t err_num);
00169
00170 NORET ~w_error_t();
00171
00172 private:
00173 enum { max_range = 10, max_trace = 10 };
00174
00175
00176 private:
00177 const char* more_info_msg;
00178
00179 friend class w_rc_t;
00180
00181 uint4_t _trace_cnt;
00182 w_error_t* _next;
00183 const char* _trace_file[max_trace];
00184 uint4_t _trace_line[max_trace];
00185 #ifdef SM_THREAD_SAFE_ERRORS
00186 pthread_t _owner;
00187 #endif
00188
00189 NORET w_error_t(
00190 const char* const filename,
00191 uint4_t line_num,
00192 err_num_t err_num,
00193 w_error_t* list,
00194 const char* more_info);
00195 NORET w_error_t(
00196 const char* const filename,
00197 uint4_t line_num,
00198 err_num_t err_num,
00199 uint4_t sys_err,
00200 w_error_t* list,
00201 const char* more_info);
00202
00203
00204 NORET w_error_t(const w_error_t&);
00205 w_error_t& operator=(const w_error_t&);
00206
00207 static const info_t* _range_start[max_range];
00208 static uint4_t _range_cnt[max_range];
00209 static const char * _range_name[max_range];
00210 static uint4_t _nreg;
00211
00212 static inline uint4_t classify(int err_num);
00213 public:
00214
00215 static const info_t error_info[];
00216 static ostream & print(ostream &out);
00217 private:
00218
00219 static void init_errorcodes();
00220
00221 };
00222
00223 extern ostream &operator<<(ostream &o, const w_error_t &obj);
00224
00225 #ifdef SM_THREAD_SAFE_ERRORS
00226 #include <pthread.h>
00227 #include <stdlib.h>
00228 inline void w_error_t::claim() {
00229 #if USE_BLOCK_ALLOC_FOR_W_ERROR_T
00230 marked = false;
00231 #endif
00232 _owner = pthread_self();
00233 }
00234 inline void w_error_t::verify_owner() const {
00235 w_assert1(pthread_equal(_owner, pthread_self()));
00236 }
00237 #else
00238 inline void w_error_t::claim() { }
00239 inline void w_error_t::verify_owner() const { }
00240 #endif
00241
00242 #if W_DEBUG_LEVEL > 1
00243 #define CHECKIT do {\
00244 w_error_t* my = _next; \
00245 w_error_t* p = my; \
00246 while(p) { \
00247 if (p == p->_next || my == p->_next) { \
00248 cerr << "Recursive error detected:" << endl << *this << endl;\
00249 w_assert0(0); \
00250 } \
00251 p = p->_next; \
00252 } \
00253 } while(0)
00254
00255 #else
00256 #define CHECKIT
00257 #endif
00258
00259
00260 inline NORET
00261 w_error_t::~w_error_t()
00262 {
00263
00264 CHECK_DEBUG_BLOCK_ALLOC_MARKED_FOR_DELETION((w_error_t *)this)
00265 delete[] more_info_msg;
00266 more_info_msg = NULL;
00267 #if USE_BLOCK_ALLOC_FOR_W_ERROR_T
00268 w_error_t::operator delete(_next);
00269 #else
00270 delete _next;
00271 #endif
00272 _next = NULL;
00273 }
00274
00275
00276
00277 #endif