00001 /* -*- mode:C++; c-basic-offset:4 -*- 00002 Shore-MT -- Multi-threaded port of the SHORE storage manager 00003 00004 Copyright (c) 2007-2009 00005 Data Intensive Applications and Systems Labaratory (DIAS) 00006 Ecole Polytechnique Federale de Lausanne 00007 00008 All Rights Reserved. 00009 00010 Permission to use, copy, modify and distribute this software and 00011 its documentation is hereby granted, provided that both the 00012 copyright notice and this permission notice appear in all copies of 00013 the software, derivative works or modified versions, and any 00014 portions thereof, and that both notices appear in supporting 00015 documentation. 00016 00017 This code is distributed in the hope that it will be useful, but 00018 WITHOUT ANY WARRANTY; without even the implied warranty of 00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS 00020 DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER 00021 RESULTING FROM THE USE OF THIS SOFTWARE. 00022 */ 00023 00024 /*<std-header orig-src='shore' incl-file-exclusion='W_RC_H'> 00025 00026 $Id: w_rc.h,v 1.68 2010/06/24 17:08:08 nhall Exp $ 00027 00028 SHORE -- Scalable Heterogeneous Object REpository 00029 00030 Copyright (c) 1994-99 Computer Sciences Department, University of 00031 Wisconsin -- Madison 00032 All Rights Reserved. 00033 00034 Permission to use, copy, modify and distribute this software and its 00035 documentation is hereby granted, provided that both the copyright 00036 notice and this permission notice appear in all copies of the 00037 software, derivative works or modified versions, and any portions 00038 thereof, and that both notices appear in supporting documentation. 00039 00040 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY 00041 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS 00042 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND 00043 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 00044 00045 This software was developed with support by the Advanced Research 00046 Project Agency, ARPA order number 018 (formerly 8230), monitored by 00047 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518. 00048 Further funding for this work was provided by DARPA through 00049 Rome Research Laboratory Contract No. F30602-97-2-0247. 00050 00051 */ 00052 00053 #ifndef W_RC_H 00054 #define W_RC_H 00055 00056 #include "w_defines.h" 00057 00058 /* -- do not edit anything above this line -- </std-header>*/ 00059 00060 #ifdef __GNUG__ 00061 #pragma interface 00062 #endif 00063 00064 #include "w_error.h" 00065 00066 00067 /**\file w_rc.h 00068 *\ingroup MACROS 00069 */ 00070 00071 /**\addtogroup MACROS 00072 * 00073 * Not all macros are included here. 00074 * 00075 */ 00076 00077 /**\addtogroup IDIOMS 00078 * \details 00079 * 00080 * The storage manager is written with programming idioms that make sure 00081 * all return codes are checked, and users of the storage manager are 00082 * strongly encouraged to use these idioms. 00083 * 00084 * 00085 * The macros support writing and reading of methods and functions that 00086 * return an w_rc_t (return code), which are defined in w_rc.h. Return 00087 * codes are described in some detail \ref ERRNUM. There you may also 00088 * see how to create your own return codes for server modules. 00089 * \code 00090 w_rc_t 00091 method(args...) 00092 { 00093 W_DO(ss_m::create_file(...)); 00094 return RCOK; 00095 } 00096 \endcode 00097 * 00098 * The W_DO macro returns whatever the called function returns if 00099 * that return code was an error code, otherwise, it falls through 00100 * to the code below the macro call. This is the most-often used 00101 * idiom. 00102 * 00103 * The RC_* macros let you construct a return code for a return value 00104 * from a function. The normal, non-error return code is RCOK. 00105 * 00106 * See the examples as well as \ref MACROS in w_rc.h. 00107 * 00108 */ 00109 class w_rc_i; // forward 00110 00111 /**\brief Return code for most functions and methods. 00112 * 00113 * \note 00114 * w_error_t::errcode_t sometimes used deep in storage manager rather 00115 * than w_rc_t for one or more of these reasons: 00116 * - w_rc_t is costly 00117 * - The w_error_t's are allocated off a heap and if that is a 00118 * per-thread heap, we don't want them to cross thread boundaries. 00119 * 00120 * An error code must be checked by some code, else it will report an 00121 * "error-not-checked" when the system is built with 00122 * \code 00123 * configure --enable-checkrc 00124 * \endcode 00125 * This is costly but useful for checking that code copes with 00126 * errors. Of course, it does not do a static analysis; rather it 00127 * is a dynamic check and so it cannot catch all code 00128 * that ignores return codes. 00129 */ 00130 class w_rc_t 00131 { 00132 friend class w_rc_i; 00133 public: 00134 /**\brief 00135 * w_error_t::errcode_t sometimes used deep in storage manager rather 00136 * than w_rc_t. See detailed description, above. 00137 */ 00138 typedef w_error_t::err_num_t errcode_t; 00139 /// Static const return code meaning "no error" 00140 static const w_rc_t rc_ok; 00141 00142 /// Default constructor: "no error" 00143 NORET w_rc_t(); 00144 00145 /// Copy constructor: does a deep copy 00146 explicit NORET w_rc_t(w_error_t* e); 00147 00148 /// Construct a return code with the given info. For use by macros. 00149 explicit NORET w_rc_t( 00150 const char* const filename, 00151 w_base_t::uint4_t line_num, 00152 errcode_t err_num); 00153 00154 /// Construct a return code with the given info. For use by macros. 00155 explicit NORET w_rc_t( 00156 const char* const filename, 00157 w_base_t::uint4_t line_num, 00158 errcode_t err_num, 00159 w_base_t::int4_t sys_err); 00160 00161 /// Copy constructor: does a deep copy, does not delegate. 00162 w_rc_t(const w_rc_t &other) : _err(other.clone()) { 00163 set_unchecked(); 00164 } 00165 00166 /// Copy operator: does a deep copy; does not delegate 00167 w_rc_t &operator=(w_rc_t const &other) { 00168 return (this == &other)? *this : _assign(other.clone()); } 00169 00170 /// Will croak if is_error() has not been called (configure --enable-checkrc) 00171 NORET ~w_rc_t(); 00172 00173 /// Not for general use. Used by configure --enable-checkrc. 00174 static void set_return_check(bool on_off, bool fatal); 00175 00176 /**\brief True if this return code is not rc_ok or equivalent. 00177 * 00178 * This \b must be called for every w_rc_t before destruction. 00179 * The idiomatic macros W_DO and its companions do that check for you, and 00180 * should be used most of the time. 00181 * 00182 * See also the following macros: 00183 * - #W_DO(x) 00184 * - #W_DO_MSG(x,m) 00185 */ 00186 bool is_error() const; 00187 00188 /// return the integer error code, as found in the Perl-generated *_gen* header files 00189 errcode_t err_num() const; 00190 00191 /// return the (optional) system error code, if there is one 00192 w_base_t::int4_t sys_err_num() const; 00193 00194 /// Re-initialize this return code to rc_ok equivalence. 00195 w_rc_t& reset(); 00196 00197 /// Add tracing info on the stack for the top error number. Used by macros. 00198 w_rc_t& add_trace_info( 00199 const char* const filename, 00200 w_base_t::uint4_t line_num); 00201 00202 /// Push another error number onto the stack. Used by macros. 00203 w_rc_t& push( 00204 const char* const filename, 00205 w_base_t::uint4_t line_num, 00206 errcode_t err_num); 00207 00208 void verify(); 00209 00210 /// Issue error when a return code leaves scope without being checked. 00211 void error_not_checked(); 00212 00213 /// Choke. 00214 void fatal(); 00215 00216 w_error_t const* operator->() const { return ptr(); } 00217 00218 /// non-const needed for rc->append_more_info in the RC_APPEND macros 00219 w_error_t* operator->() { return ptr(); } 00220 00221 /// public so that sm code and be explicit about delegating if need be 00222 w_error_t* delegate(); 00223 private: 00224 w_error_t &operator*() { return *ptr(); } 00225 w_error_t const &operator*() const { return *ptr(); } 00226 00227 w_error_t* clone() const { 00228 return (ptr() == w_error_t::no_error ) ? 00229 w_error_t::no_error: _clone(); 00230 } 00231 w_error_t* _clone() const; 00232 00233 /* 00234 * streams 00235 */ 00236 friend ostream& operator<<( 00237 ostream& o, 00238 const w_rc_t& obj); 00239 00240 private: 00241 mutable w_error_t* _err; 00242 static bool do_check; 00243 static bool unchecked_is_fatal; 00244 00245 // W_DEBUG_RC is defined as 0 or 1 by --enable-checkrc 00246 // It tracks whether return codes get checked. 00247 #if W_DEBUG_RC 00248 static ptrdiff_t get_flag() { return 0x1; } 00249 #else 00250 static ptrdiff_t get_flag() { return 0x0; } 00251 #endif 00252 00253 /* 00254 Access to the w_error_t pointer 00255 ************************************************************************ 00256 */ 00257 void set_unchecked() { 00258 if(_err == w_error_t::no_error || !get_flag()) 00259 return; 00260 union {w_error_t* e; long n; } u={_err}; 00261 u.n |= get_flag(); 00262 _err = u.e; 00263 } 00264 00265 public: 00266 /// turned public for testing 00267 bool is_unchecked() { 00268 union {w_error_t* e; long n; } u={_err}; 00269 return u.n & get_flag(); 00270 } 00271 private: 00272 w_error_t* ptr() { return get(); } 00273 w_error_t const* ptr() const { return get(); } 00274 00275 // return the error and mark it checked 00276 w_error_t* get() const { 00277 union {w_error_t* e; long n; } u={_err}; 00278 if(get_flag()) { 00279 u.n &= ~get_flag(); // remove the flag so we don't seg fault 00280 _err=u.e; 00281 } 00282 return _err; 00283 } 00284 00285 private: 00286 00287 // delete my current error (if any) and take ownership of a new one 00288 // other had better not belong to any other rc. 00289 w_rc_t &_assign(w_error_t* other) { 00290 w_assert2(other); 00291 verify(); 00292 w_error_t* err = ptr(); 00293 if((const w_error_t *)err != w_error_t::no_error) 00294 delete err; 00295 _err = other; 00296 return reset(); 00297 } 00298 00299 }; 00300 00301 00302 /**\brief Iterator over w_error_t list : helper for w_rc_t. 00303 * 00304 * Allows you to iterate over the w_error_t structures hanging off a 00305 * w_rc_t. 00306 * 00307 * Not generally used by server writers; used by w_rc_t implementation. 00308 */ 00309 class w_rc_i { 00310 w_error_t const *_next; 00311 public: 00312 w_rc_i(w_rc_t const &x) : _next(x.ptr()) {}; 00313 00314 w_base_t::int4_t next_errnum() { 00315 w_rc_t::errcode_t temp = 0; 00316 if(_next) { 00317 temp = _next->err_num; 00318 _next = _next->next(); 00319 } 00320 return temp; 00321 } 00322 w_error_t const *next() { 00323 w_error_t const *temp = _next; 00324 if(_next) { 00325 _next = _next->next(); 00326 } 00327 return temp; 00328 } 00329 private: 00330 // disabled 00331 w_rc_i(const w_rc_i &x); 00332 // : _rc( w_rc_t(w_error_t::no_error)), 00333 // _next(w_error_t::no_error) {}; 00334 }; 00335 00336 00337 00338 /********************************************************************* 00339 * 00340 * w_rc_t::w_rc_t() 00341 * 00342 * Create an rc with no error. Mark as checked. 00343 * 00344 *********************************************************************/ 00345 inline NORET 00346 w_rc_t::w_rc_t() 00347 : _err(w_error_t::no_error) 00348 { 00349 } 00350 00351 00352 /********************************************************************* 00353 * 00354 * w_rc_t::w_rc_t(e) 00355 * 00356 * Create an rc for error e. Rc is not checked. 00357 * 00358 *********************************************************************/ 00359 inline NORET 00360 w_rc_t::w_rc_t(w_error_t* e) 00361 : _err(e) 00362 { 00363 set_unchecked(); 00364 } 00365 00366 00367 /********************************************************************* 00368 * 00369 * w_rc_t::reset() 00370 * 00371 * Mark rc as not checked. 00372 * 00373 *********************************************************************/ 00374 inline w_rc_t& 00375 w_rc_t::reset() 00376 { 00377 set_unchecked(); 00378 return *this; 00379 } 00380 00381 00382 /********************************************************************* 00383 * 00384 * w_rc_t::verify() 00385 * 00386 * Verify that rc has been checked. If not, call error_not_checked(). 00387 * 00388 *********************************************************************/ 00389 inline void 00390 w_rc_t::verify() 00391 { 00392 // W_DEBUG_RC is defined as 0 or 1 by --enable-checkrc 00393 // It tracks whether return codes get checked. 00394 #if W_DEBUG_RC 00395 if (do_check && is_unchecked()) 00396 error_not_checked(); 00397 #endif 00398 #if W_DEBUG_LEVEL > 2 00399 w_rc_i it(*this); 00400 while(w_error_t const* e = it.next()) { 00401 (void) e->get_more_info_msg(); // Just for assertion checking 00402 } 00403 #endif 00404 } 00405 00406 00407 /********************************************************************* 00408 * 00409 * w_rc_t::delegate() 00410 * 00411 * Give up my error code. Set self as checked. 00412 * 00413 *********************************************************************/ 00414 inline w_error_t* 00415 w_rc_t::delegate() 00416 { 00417 w_error_t* t = ptr(); 00418 _err = w_error_t::no_error; 00419 return t; 00420 } 00421 00422 /********************************************************************* 00423 * 00424 * w_rc_t::~w_rc_t() 00425 * 00426 * Destructor. Verify status. 00427 * 00428 *********************************************************************/ 00429 inline NORET 00430 w_rc_t::~w_rc_t() 00431 { 00432 _assign(w_error_t::no_error); 00433 } 00434 00435 00436 /********************************************************************* 00437 * 00438 * w_rc_t::is_error() 00439 * 00440 * Return true if pointing to an error. Set self as checked. 00441 * 00442 *********************************************************************/ 00443 inline bool 00444 w_rc_t::is_error() const 00445 { 00446 // strongly encourage the user to use no_error when they mean "no error" 00447 return ptr() != w_error_t::no_error; 00448 } 00449 00450 00451 /********************************************************************* 00452 * 00453 * w_rc_t::err_num() 00454 * 00455 * Return the error code in rc. 00456 * 00457 *********************************************************************/ 00458 inline w_rc_t::errcode_t 00459 w_rc_t::err_num() const 00460 { 00461 return ptr()->err_num; 00462 } 00463 00464 00465 /********************************************************************* 00466 * 00467 * w_rc_t::sys_err_num() 00468 * 00469 * Return the system error code in rc. 00470 * 00471 *********************************************************************/ 00472 inline w_base_t::int4_t 00473 w_rc_t::sys_err_num() const 00474 { 00475 return ptr()->sys_err_num; 00476 } 00477 00478 00479 00480 /********************************************************************* 00481 * 00482 * Basic macros for using rc. 00483 * 00484 * RC(e) : create an rc for error code e. 00485 * 00486 * RC2(e,s) : create an rc for error code e, sys err num s 00487 * 00488 * RCOK : create an rc for no error. 00489 * 00490 * MAKERC(bool, x): create an rc if true, else RCOK 00491 * 00492 * e.g. if (eof) 00493 * return RC(eENDOFFILE); 00494 * else 00495 * return RCOK; 00496 * With MAKERC, this can be converted to 00497 * return MAKERC(eof, eENDOFFILE); 00498 * 00499 *********************************************************************/ 00500 /**\def RC(e) 00501 * \brief Normal error-case return. 00502 * 00503 * Create a return code with the current file, line, and error code x. 00504 * This is the normal way to return from a method or function. 00505 */ 00506 #define RC(e) w_rc_t(__FILE__, __LINE__, e) 00507 00508 /**\def RC2(e,s) 00509 * \brief Normal error-case return with sys_error. 00510 * 00511 * Create a return code with the current file, line, and error code e, 00512 * and system error number s. 00513 * This is the normal way to return an 00514 * error indication from a method or function that encountered a system error. 00515 * The value \b s allows the user to convey an ::errno value in the return code. 00516 */ 00517 #define RC2(e,s) \ 00518 w_rc_t(__FILE__, __LINE__, e, s) 00519 00520 // This, at least, avoids one constructor call 00521 /**\def RCOK 00522 * \brief Normal return value for no-error case. 00523 * 00524 * Const return code that indicates no error. 00525 * This is the normal way to return from a method or function. 00526 */ 00527 #define RCOK w_rc_t::rc_ok 00528 00529 /**\def MAKERC(condition,e) 00530 * \brief Return error \b e if \b condition is false. 00531 * 00532 * Create a return code that indicates an error iff the condition is false, 00533 * otherwise return with no-error indication. 00534 */ 00535 #define MAKERC(condition,e) ((condition) ? RC(e) : RCOK) 00536 00537 00538 00539 /******************************************************************** 00540 * 00541 * More Macros for using rc. 00542 * 00543 * RC_AUGMENT(rc) : add file and line number to the rc 00544 * RC_PUSH(rc, e) : add a new error code to rc 00545 * 00546 * e.g. 00547 * w_rc_t rc = create_file(f); 00548 * if (rc) return RC_AUGMENT(rc); 00549 * rc = close_file(f); 00550 * if (rc) return RC_PUSH(rc, eCANNOTCLOSE) 00551 * 00552 *********************************************************************/ 00553 00554 #ifdef __GNUC__ 00555 /**\def W_EXPECT(rc) 00556 * \brief Give the compiler a hint that we expect to take the branch 00557 * 00558 * This macro is meaningful only with the GNU C++ compiler. 00559 */ 00560 #define W_EXPECT(rc) __builtin_expect(rc,1) 00561 /**\def W_EXPECT_NOT(rc) 00562 * \brief Give the compiler a hint that we expect not to take the branch 00563 * 00564 * This macro is meaningful only with the GNU C++ compiler. 00565 */ 00566 #define W_EXPECT_NOT(rc) __builtin_expect(rc,0) 00567 #else 00568 /**\def W_EXPECT(rc) 00569 * \brief Give the compiler a hint that we expect to take the branch 00570 * 00571 * This macro is meaningful only with the GNU C++ compiler. 00572 */ 00573 #define W_EXPECT(rc) rc 00574 /**\def W_EXPECT_NOT(rc) 00575 * \brief Give the compiler a hint that we expect not to take the branch 00576 * 00577 * This macro is meaningful only with the GNU C++ compiler. 00578 */ 00579 #define W_EXPECT_NOT(rc) rc 00580 #endif 00581 00582 /**\def RC_AUGMENT(rc) 00583 * \brief Augment stack trace. 00584 * 00585 * Add stack trace information (file, line) to a return code. 00586 * This is the normal way to return from a method or function upon 00587 * receiving an error from a method or function that it called. 00588 * Used by \ref #W_DO(x), \ref #W_DO_MSG(x,m), \ref #W_DO_GOTO(rc,x), 00589 * and \ref #W_COERCE(x) 00590 */ 00591 #define RC_AUGMENT(rc) \ 00592 rc.add_trace_info(__FILE__, __LINE__) 00593 00594 /**\def RC_PUSH(rc, e) 00595 * \brief Augment stack trace with another error code. 00596 * 00597 * Add stack trace informatin (file, line, error) to a return code. 00598 * This is to return from a method or function upon 00599 * receiving an error from a method or function that it called, when 00600 * a what you want to return to your caller is a 00601 * different error code from that returned by the method just called. 00602 * Used by \ref #W_DO_PUSH(x, e) and 00603 * \ref #W_DO_PUSH_MSG(x,e, m) 00604 */ 00605 #define RC_PUSH(rc, e) \ 00606 rc.push(__FILE__, __LINE__, e) 00607 00608 00609 /**\def RC_APPEND_MSG(rc, m) 00610 * \brief Augment stack trace with more arbitrary string information. 00611 * 00612 * Add a char string representing more information to a return code. 00613 * Used by \ref W_RETURN_RC_MSG(e, m), 00614 * \ref W_DO_MSG(x, m), 00615 * \ref W_DO_PUSH_MSG(x, m), and 00616 * \ref W_COERCE_MSG(x, m) 00617 */ 00618 #define RC_APPEND_MSG(rc, m) \ 00619 do { \ 00620 w_ostrstream os; \ 00621 os m << ends; \ 00622 rc->append_more_info_msg(os.c_str()); \ 00623 } while (0) 00624 00625 /**\def W_RETURN_RC_MSG(e, m) 00626 * \brief Retrun with a return code that contains the given error code and additional message. 00627 */ 00628 #define W_RETURN_RC_MSG(e, m) \ 00629 do { \ 00630 w_rc_t __e = RC(e); \ 00631 RC_APPEND_MSG(__e, m); \ 00632 return __e; \ 00633 } while (0) 00634 00635 /**\def W_EDO(x) 00636 * \brief Call a method or function \b x that returns a lightweight error code from a method that returns a w_rc_t. 00637 * 00638 * This macro is used deep in the storage manager to call a 00639 * method or function that returns a (lightweight) error code rather than 00640 * a \ref #w_rc_t. 00641 * It checks the returned code for the error case, and if it finds an 00642 * error, it creates a w_rc_t with the error code returned by the called 00643 * function or method. 00644 */ 00645 #define W_EDO(x) \ 00646 do { \ 00647 w_rc_t::errcode_t __e = (x); \ 00648 if (W_EXPECT_NOT(__e)) return RC(__e); \ 00649 } while (0) 00650 00651 /**\def W_DO(x) 00652 * \brief Call a method or function \b x. 00653 * 00654 * This macro is the normal idiom for calling a method or function. 00655 * Most methods and functions return a w_rc_t. This macro calls \b x 00656 * and checks its returned value. If an error is encountered, it 00657 * immediately returns from the current function or method, augmenting 00658 * the stack trace held by the return code. 00659 */ 00660 #define W_DO(x) \ 00661 do { \ 00662 w_rc_t __e = (x); \ 00663 if (W_EXPECT_NOT(__e.is_error())) return RC_AUGMENT(__e); \ 00664 } while (0) 00665 00666 /**\def W_DO_MSG(x) 00667 * \brief Call a method or function \b x. 00668 * 00669 * Like \ref #W_DO, but any error returned contains 00670 * the additional information message \b m. 00671 */ 00672 #define W_DO_MSG(x, m) \ 00673 do { \ 00674 w_rc_t __e = (x); \ 00675 if (W_EXPECT_NOT(__e.is_error())) { \ 00676 RC_AUGMENT(__e); \ 00677 RC_APPEND_MSG(__e, m); \ 00678 return __e; \ 00679 } \ 00680 } while (0) 00681 00682 /**\def W_DO_GOTO(rc, x) 00683 * \brief Idiom for unusual error-handling before returning. 00684 * 00685 * This macro is used to process errors that require special handling before 00686 * the calling function can return. 00687 * It calls the method or function \b x, and if \b x returns an error, it 00688 * transfers control to the label \b failure. 00689 * 00690 * Like \ref #W_DO, but: 00691 * - rather than defining a local w_rc_t, it uses an elsewhere-defined 00692 * w_rc_t instance; this is because: 00693 * - rather than returning in the error case, it branches to the label 00694 * \b failure. 00695 * 00696 * \note: the label \b failure must exist in the the calling function, and 00697 * the argument \b rc must have been declared in the calling scope. 00698 * Presumably the argument \b rc is declared in the scope of \b failure: 00699 * as well, so that it can process the error. 00700 */ 00701 // W_DO_GOTO assumes the rc was already declared 00702 #define W_DO_GOTO(rc/*w_rc_t*/, x) \ 00703 do { \ 00704 (rc) = (x); \ 00705 if (W_EXPECT_NOT(rc.is_error())) { \ 00706 RC_AUGMENT(rc); \ 00707 goto failure; \ 00708 } \ 00709 } while (0) 00710 00711 /**\def W_DO_PUSH(x, e) 00712 * \brief Call a function or method \b x, if error, push error code \b e on the stack and return. 00713 * 00714 * This macro is like \ref #W_DO(x), but it adds an error code \b e to 00715 * the stack trace before returning. 00716 */ 00717 #define W_DO_PUSH(x, e) \ 00718 do { \ 00719 w_rc_t __e = (x); \ 00720 if (W_EXPECT_NOT(__e.is_error())) { return RC_PUSH(__e, e); } \ 00721 } while (0) 00722 00723 /**\def W_DO_PUSH_MSG(x, e, m) 00724 * \brief Call a function or method \b x, if error, push error code \b e on the stack and return. 00725 * 00726 * This macro is like \ref #W_DO_PUSH(x, e), but it adds an additional 00727 * information message \b m to 00728 * the stack trace before returning. 00729 */ 00730 #define W_DO_PUSH_MSG(x, e, m) \ 00731 do { \ 00732 w_rc_t __e = (x); \ 00733 if (W_EXPECT_NOT(__e.is_error())) { \ 00734 RC_PUSH(__e, e); \ 00735 RC_APPEND_MSG(__e, m); \ 00736 return __e; \ 00737 } \ 00738 } while (0) 00739 00740 /**\def W_COERCE(x) 00741 * \brief Call a function or method \b x, fail catastrophically if error is returned. 00742 * 00743 * This macro is like \ref #W_DO(x), but instead of returning in the error 00744 * case, it fails catastrophically. 00745 * It is used in cases such as these: 00746 * - Temporary place-holder where the coder hasn't written 00747 * the failure-handling code 00748 * - The calling function or method API has no means to return 00749 * error information, and this case hasn't yet been accommodated. 00750 * - The called \b x should never return an error 00751 * in this case, and doing so would indicate a programming error. 00752 * - The called \b x never returns an error at the time the calling code 00753 * is written, and should the called code \b x change, 00754 * the calling code should probably be adjusted to handle any new error. 00755 * 00756 * The call to __e.fatal() prints the stack trace and additional information 00757 * associated with the w_rc_t before it croaks. 00758 */ 00759 #define W_COERCE(x) \ 00760 do { \ 00761 w_rc_t __e = (x); \ 00762 if (W_EXPECT_NOT(__e.is_error())) { \ 00763 RC_AUGMENT(__e); \ 00764 __e.fatal(); \ 00765 } \ 00766 } while (0) 00767 00768 /**\def W_COERCE_MSG(x, m) 00769 * \brief Same as \ref #W_COERCE(x) but adds a string message before croaking. 00770 */ 00771 #define W_COERCE_MSG(x, m) \ 00772 do { \ 00773 w_rc_t __em = (x); \ 00774 if (W_EXPECT_NOT(__em.is_error())) { \ 00775 RC_APPEND_MSG(__em, m); \ 00776 W_COERCE(__em); \ 00777 } \ 00778 } while (0) 00779 00780 /**\def W_FATAL(e) 00781 * \brief Croak with the error code \b e. 00782 */ 00783 #define W_FATAL(e) W_COERCE(RC(e)) 00784 00785 /**\def W_FATAL_RC(rc) 00786 * \brief Croak with the return code \b rc. 00787 */ 00788 #define W_FATAL_RC(rc) W_COERCE(rc) 00789 00790 /**\def W_FATAL_MSG(e, m) 00791 * \brief Croak with the error code \b e and message \b m. 00792 */ 00793 #define W_FATAL_MSG(e, m) W_COERCE_MSG(RC(e), m) 00794 00795 /**\def W_IGNORE(x, m) 00796 * \brief Invoke \b x and ignore its result. 00797 */ 00798 #define W_IGNORE(x) ((void) x.is_error()) 00799 00800 /*<std-footer incl-file-exclusion='W_RC_H'> -- do not edit anything below this line -- */ 00801 00802 #endif /*</std-footer>*/