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.74 2011/09/08 18:10:55 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 00072 /**\addtogroup IDIOMS 00073 * \details 00074 * 00075 * The storage manager is written with programming idioms to make sure 00076 * all return codes are checked, and as a user of the storage manager, you 00077 * strongly encouraged to use these idioms. 00078 * 00079 * It is especially important that you understand the storage manager's 00080 * \e return \e code type, \ref w_rc_t. 00081 * Most of the storage manager methods return this type. The return code 00082 * type is a dynamically-allocated class instance (except when RCOK, the 00083 * default, non-error code, is returned: this is a static constant). 00084 * Because it is heap-allocated, when the compiler generates code for its 00085 * destruction, certain programming errors are nastier 00086 * than in the case of returning an atomic type (e.g., int). For example, 00087 * if you write a function with a w_rc_t return type and neglect to give 00088 * it a return value, your program will probably fail catastrophically. 00089 * (You can avoid this problem by compiling with compiler warnings enabled.) 00090 * 00091 * The return code from a storage manager method should \e always be checked: 00092 * \code 00093 w_rc_t func(...) 00094 { 00095 ... 00096 w_rc_t rc = ss_m::create_file(...); 00097 if(rc.is_error()) { 00098 ... 00099 } 00100 return RCOK; 00101 } 00102 \endcode 00103 * The act of calling \code rc.is_error() \endcode flags the return code as 00104 * having been checked. 00105 * The destructor for \ref w_rc_t can be made to issue an error if the 00106 * return code was never checked for destruction. The message takes the 00107 * form: 00108 * \code 00109 Error not checked: rc=1. error in j_create_rec.cpp:176 Timed out waiting for resource [0x40000] 00110 * \endcode 00111 * 00112 * (When a return code is sent to an output stream, it prints a 00113 * stack trace. The above message contains a stack trace with one level.) 00114 * 00115 * The error-not-checked checking happens if 00116 * the storage manager is configured and built with 00117 * \code --enable-checkrc \endcode . 00118 * By default this configuration option is off so that it is off 00119 * for a "production", that is, optimized build. When you are 00120 * debugging your code, it is a good idea to configure the storage manager 00121 * with it enabled. 00122 * 00123 * Several macros defined in w_rc.h 00124 * support writing and using methods and functions that 00125 * return a w_rc_t. 00126 * \code 00127 w_rc_t 00128 func(...) 00129 { 00130 W_DO(ss_m::create_file(...)); 00131 return RCOK; 00132 } 00133 \endcode 00134 * 00135 * The \ref W_DO macro returns whatever the called function returns if 00136 * that return code was an error code, otherwise, it falls through 00137 * to the code below the macro call. This is the most-often used 00138 * idiom. 00139 * 00140 * The RC_* macros let you construct a return code for a return value 00141 * from a function. The normal, non-error return code is \ref RCOK. 00142 * 00143 * Return codes are described in some detail \ref ERRNUM. 00144 * There you may also 00145 * see how to create your own return codes for server modules. 00146 * 00147 * See the examples as well as \ref MACROS in w_rc.h. 00148 * 00149 */ 00150 class w_rc_i; // forward 00151 00152 /**\brief Return code for most functions and methods. 00153 * 00154 * \note 00155 * w_error_t::errcode_t sometimes used deep in storage manager rather 00156 * than w_rc_t for one or more of these reasons: 00157 * - w_rc_t is costly 00158 * - The w_error_t's are allocated off a heap and if that is a 00159 * per-thread heap, we don't want them to cross thread boundaries. 00160 * 00161 * An error code must be checked by some code, else it will report an 00162 * "error-not-checked" when the system is built with 00163 * \code 00164 * configure --enable-checkrc 00165 * \endcode 00166 * This is costly but useful for checking that code copes with 00167 * errors. Of course, it does not do a static analysis; rather it 00168 * is a dynamic check and so it cannot catch all code 00169 * that ignores return codes. 00170 */ 00171 class w_rc_t 00172 { 00173 friend class w_rc_i; 00174 public: 00175 /**\brief 00176 * w_error_t::errcode_t sometimes used deep in storage manager rather 00177 * than w_rc_t. See detailed description, above. 00178 */ 00179 typedef w_error_t::err_num_t errcode_t; 00180 /// Static const return code meaning "no error" 00181 static const w_rc_t rc_ok; 00182 00183 /// Default constructor: "no error" 00184 NORET w_rc_t(); 00185 00186 /// Copy constructor: does a deep copy 00187 explicit NORET w_rc_t(w_error_t* e); 00188 00189 /// Construct a return code with the given info. For use by macros. 00190 explicit NORET w_rc_t( 00191 const char* const filename, 00192 w_base_t::uint4_t line_num, 00193 errcode_t err_num); 00194 00195 /// Construct a return code with the given info. For use by macros. 00196 explicit NORET w_rc_t( 00197 const char* const filename, 00198 w_base_t::uint4_t line_num, 00199 errcode_t err_num, 00200 w_base_t::int4_t sys_err); 00201 00202 /// Copy constructor: does a deep copy, does not delegate. 00203 w_rc_t(const w_rc_t &other) : _err(other.clone()) { 00204 set_unchecked(); 00205 } 00206 00207 /// Copy operator: does a deep copy; does not delegate 00208 w_rc_t &operator=(w_rc_t const &other) { 00209 return (this == &other)? *this : _assign(other.clone()); } 00210 00211 /// Will croak if is_error() has not been called (configure --enable-checkrc) 00212 NORET ~w_rc_t(); 00213 00214 /// Not for general use. Used by configure --enable-checkrc. 00215 static void set_return_check(bool on_off, bool fatal); 00216 00217 /**\brief True if this return code is not rc_ok or equivalent. 00218 * 00219 * This \b must be called for every w_rc_t before destruction. 00220 * The idiomatic macros W_DO and its companions do that check for you, and 00221 * should be used most of the time. 00222 * 00223 * See also the following macros: 00224 * - #W_DO(x) 00225 * - #W_DO_MSG(x,m) 00226 */ 00227 bool is_error() const; 00228 00229 /// return the integer error code, as found in the Perl-generated *_gen* header files 00230 errcode_t err_num() const; 00231 00232 /// return the (optional) system error code, if there is one 00233 w_base_t::int4_t sys_err_num() const; 00234 00235 /// Re-initialize this return code to rc_ok equivalence. 00236 w_rc_t& reset(); 00237 00238 /// Add tracing info on the stack for the top error number. Used by macros. 00239 w_rc_t& add_trace_info( 00240 const char* const filename, 00241 w_base_t::uint4_t line_num); 00242 00243 /// Push another error number onto the stack. Used by macros. 00244 w_rc_t& push( 00245 const char* const filename, 00246 w_base_t::uint4_t line_num, 00247 errcode_t err_num); 00248 00249 void verify(); 00250 00251 /// Issue error when a return code leaves scope without being checked. 00252 void error_not_checked(); 00253 00254 /// Choke. 00255 void fatal(); 00256 00257 w_error_t const* operator->() const { return ptr(); } 00258 00259 /// non-const needed for rc->append_more_info in the RC_APPEND macros 00260 w_error_t* operator->() { return ptr(); } 00261 00262 /// public so that sm code and be explicit about delegating if need be 00263 w_error_t* delegate(); 00264 private: 00265 w_error_t &operator*() { return *ptr(); } 00266 w_error_t const &operator*() const { return *ptr(); } 00267 00268 w_error_t* clone() const { 00269 return (ptr() == w_error_t::no_error ) ? 00270 w_error_t::no_error: _clone(); 00271 } 00272 w_error_t* _clone() const; 00273 00274 /* 00275 * streams 00276 */ 00277 friend ostream& operator<<( 00278 ostream& o, 00279 const w_rc_t& obj); 00280 00281 private: 00282 mutable w_error_t* _err; 00283 static bool do_check; 00284 static bool unchecked_is_fatal; 00285 00286 // W_DEBUG_RC is defined as 0 or 1 by --enable-checkrc 00287 // It tracks whether return codes get checked. 00288 #if W_DEBUG_RC 00289 static ptrdiff_t get_flag() { return 0x1; } 00290 #else 00291 static ptrdiff_t get_flag() { return 0x0; } 00292 #endif 00293 00294 /* 00295 Access to the w_error_t pointer 00296 ************************************************************************ 00297 */ 00298 void set_unchecked() { 00299 if(_err == w_error_t::no_error || !get_flag()) 00300 return; 00301 union {w_error_t* e; long n; } u={_err}; 00302 u.n |= get_flag(); 00303 _err = u.e; 00304 } 00305 00306 public: 00307 /// turned public for testing 00308 bool is_unchecked() { 00309 union {w_error_t* e; long n; } u={_err}; 00310 return u.n & get_flag(); 00311 } 00312 private: 00313 w_error_t* ptr() { return get(); } 00314 w_error_t const* ptr() const { return get(); } 00315 00316 // return the error and mark it checked 00317 w_error_t* get() const { 00318 union {w_error_t* e; long n; } u={_err}; 00319 if(get_flag()) { 00320 u.n &= ~get_flag(); // remove the flag so we don't seg fault 00321 _err=u.e; 00322 } 00323 return _err; 00324 } 00325 00326 private: 00327 00328 // delete my current error (if any) and take ownership of a new one 00329 // other had better not belong to any other rc. 00330 w_rc_t &_assign(w_error_t* other) { 00331 w_assert2(other); 00332 verify(); 00333 w_error_t* err = ptr(); 00334 if((const w_error_t *)err != w_error_t::no_error) 00335 #if USE_BLOCK_ALLOC_FOR_W_ERROR_T 00336 w_error_t::operator delete(err); // make sure the right delete is used. 00337 #else 00338 delete err; 00339 #endif 00340 _err = other; 00341 return reset(); 00342 } 00343 00344 }; 00345 00346 00347 /**\brief Iterator over w_error_t list : helper for w_rc_t. 00348 * 00349 * Allows you to iterate over the w_error_t structures hanging off a 00350 * w_rc_t. 00351 * 00352 * Not generally used by server writers; used by w_rc_t implementation. 00353 */ 00354 class w_rc_i { 00355 w_error_t const *_next; 00356 public: 00357 w_rc_i(w_rc_t const &x) : _next(x.ptr()) {}; 00358 00359 w_base_t::int4_t next_errnum() { 00360 w_rc_t::errcode_t temp = 0; 00361 if(_next) { 00362 temp = _next->err_num; 00363 _next = _next->next(); 00364 } 00365 return temp; 00366 } 00367 w_error_t const *next() { 00368 w_error_t const *temp = _next; 00369 if(_next) { 00370 _next = _next->next(); 00371 } 00372 return temp; 00373 } 00374 private: 00375 // disabled 00376 w_rc_i(const w_rc_i &x); 00377 // : _rc( w_rc_t(w_error_t::no_error)), 00378 // _next(w_error_t::no_error) {}; 00379 }; 00380 00381 00382 00383 /********************************************************************* 00384 * 00385 * w_rc_t::w_rc_t() 00386 * 00387 * Create an rc with no error. Mark as checked. 00388 * 00389 *********************************************************************/ 00390 inline NORET 00391 w_rc_t::w_rc_t() 00392 : _err(w_error_t::no_error) 00393 { 00394 } 00395 00396 00397 /********************************************************************* 00398 * 00399 * w_rc_t::w_rc_t(e) 00400 * 00401 * Create an rc for error e. Rc is not checked. 00402 * 00403 *********************************************************************/ 00404 inline NORET 00405 w_rc_t::w_rc_t(w_error_t* e) 00406 : _err(e) 00407 { 00408 set_unchecked(); 00409 } 00410 00411 00412 /********************************************************************* 00413 * 00414 * w_rc_t::reset() 00415 * 00416 * Mark rc as not checked. 00417 * 00418 *********************************************************************/ 00419 inline w_rc_t& 00420 w_rc_t::reset() 00421 { 00422 set_unchecked(); 00423 return *this; 00424 } 00425 00426 00427 /********************************************************************* 00428 * 00429 * w_rc_t::verify() 00430 * 00431 * Verify that rc has been checked. If not, call error_not_checked(). 00432 * 00433 *********************************************************************/ 00434 inline void 00435 w_rc_t::verify() 00436 { 00437 // W_DEBUG_RC is defined as 0 or 1 by --enable-checkrc 00438 // It tracks whether return codes get checked. 00439 #if W_DEBUG_RC 00440 if (do_check && is_unchecked()) 00441 error_not_checked(); 00442 #endif 00443 #if W_DEBUG_LEVEL > 2 00444 w_rc_i it(*this); 00445 while(w_error_t const* e = it.next()) { 00446 (void) e->get_more_info_msg(); // Just for assertion checking 00447 } 00448 #endif 00449 } 00450 00451 00452 /********************************************************************* 00453 * 00454 * w_rc_t::delegate() 00455 * 00456 * Give up my error code. Set self as checked. 00457 * 00458 *********************************************************************/ 00459 inline w_error_t* 00460 w_rc_t::delegate() 00461 { 00462 w_error_t* t = ptr(); 00463 _err = w_error_t::no_error; 00464 return t; 00465 } 00466 00467 /********************************************************************* 00468 * 00469 * w_rc_t::~w_rc_t() 00470 * 00471 * Destructor. Verify status. 00472 * 00473 *********************************************************************/ 00474 inline NORET 00475 w_rc_t::~w_rc_t() 00476 { 00477 _assign(w_error_t::no_error); 00478 } 00479 00480 00481 /********************************************************************* 00482 * 00483 * w_rc_t::is_error() 00484 * 00485 * Return true if pointing to an error. Set self as checked. 00486 * 00487 *********************************************************************/ 00488 inline bool 00489 w_rc_t::is_error() const 00490 { 00491 // strongly encourage the user to use no_error when they mean "no error" 00492 return ptr() != w_error_t::no_error; 00493 } 00494 00495 00496 /********************************************************************* 00497 * 00498 * w_rc_t::err_num() 00499 * 00500 * Return the error code in rc. 00501 * 00502 *********************************************************************/ 00503 inline w_rc_t::errcode_t 00504 w_rc_t::err_num() const 00505 { 00506 return ptr()->err_num; 00507 } 00508 00509 00510 /********************************************************************* 00511 * 00512 * w_rc_t::sys_err_num() 00513 * 00514 * Return the system error code in rc. 00515 * 00516 *********************************************************************/ 00517 inline w_base_t::int4_t 00518 w_rc_t::sys_err_num() const 00519 { 00520 return ptr()->sys_err_num; 00521 } 00522 00523 00524 00525 /********************************************************************* 00526 * 00527 * Basic macros for using rc. 00528 * 00529 * RC(e) : create an rc for error code e. 00530 * 00531 * RC2(e,s) : create an rc for error code e, sys err num s 00532 * 00533 * RCOK : create an rc for no error. 00534 * 00535 * MAKERC(bool, x): create an rc if true, else RCOK 00536 * 00537 * e.g. if (eof) 00538 * return RC(eENDOFFILE); 00539 * else 00540 * return RCOK; 00541 * With MAKERC, this can be converted to 00542 * return MAKERC(eof, eENDOFFILE); 00543 * 00544 *********************************************************************/ 00545 /**\def RC(e) 00546 * \brief Normal error-case return. 00547 * 00548 * Create a return code with the current file, line, and error code x. 00549 * This is the normal way to return from a method or function. 00550 */ 00551 #define RC(e) w_rc_t(__FILE__, __LINE__, e) 00552 00553 /**\def RC2(e,s) 00554 * \brief Normal error-case return with sys_error. 00555 * 00556 * Create a return code with the current file, line, and error code e, 00557 * and system error number s. 00558 * This is the normal way to return an 00559 * error indication from a method or function that encountered a system error. 00560 * The value \b s allows the user to convey an ::errno value in the return code. 00561 */ 00562 #define RC2(e,s) \ 00563 w_rc_t(__FILE__, __LINE__, e, s) 00564 00565 // This, at least, avoids one constructor call 00566 /**\def RCOK 00567 * \brief Normal return value for no-error case. 00568 * 00569 * Const return code that indicates no error. 00570 * This is the normal way to return from a method or function. 00571 */ 00572 #define RCOK w_rc_t::rc_ok 00573 00574 /**\def MAKERC(condition,e) 00575 * \brief Return error \b e if \b condition is false. 00576 * 00577 * Create a return code that indicates an error iff the condition is false, 00578 * otherwise return with no-error indication. 00579 */ 00580 #define MAKERC(condition,e) ((condition) ? RC(e) : RCOK) 00581 00582 00583 00584 /******************************************************************** 00585 * 00586 * More Macros for using rc. 00587 * 00588 * RC_AUGMENT(rc) : add file and line number to the rc 00589 * RC_PUSH(rc, e) : add a new error code to rc 00590 * 00591 * e.g. 00592 * w_rc_t rc = create_file(f); 00593 * if (rc) return RC_AUGMENT(rc); 00594 * rc = close_file(f); 00595 * if (rc) return RC_PUSH(rc, eCANNOTCLOSE) 00596 * 00597 *********************************************************************/ 00598 00599 #ifdef __GNUC__ 00600 /**\def W_EXPECT(rc) 00601 * \brief Give the compiler a hint that we expect to take the branch 00602 * 00603 * This macro is meaningful only with the GNU C++ compiler. 00604 */ 00605 #define W_EXPECT(rc) __builtin_expect(rc,1) 00606 /**\def W_EXPECT_NOT(rc) 00607 * \brief Give the compiler a hint that we expect not to take the branch 00608 * 00609 * This macro is meaningful only with the GNU C++ compiler. 00610 */ 00611 #define W_EXPECT_NOT(rc) __builtin_expect(rc,0) 00612 #else 00613 /**\def W_EXPECT(rc) 00614 * \brief Give the compiler a hint that we expect to take the branch 00615 * 00616 * This macro is meaningful only with the GNU C++ compiler. 00617 */ 00618 #define W_EXPECT(rc) rc 00619 /**\def W_EXPECT_NOT(rc) 00620 * \brief Give the compiler a hint that we expect not to take the branch 00621 * 00622 * This macro is meaningful only with the GNU C++ compiler. 00623 */ 00624 #define W_EXPECT_NOT(rc) rc 00625 #endif 00626 00627 /**\def RC_AUGMENT(rc) 00628 * \brief Augment stack trace. 00629 * 00630 * Add stack trace information (file, line) to a return code. 00631 * This is the normal way to return from a method or function upon 00632 * receiving an error from a method or function that it called. 00633 * Used by \ref #W_DO(x), \ref #W_DO_MSG(x,m), \ref #W_DO_GOTO(rc,x), 00634 * and \ref #W_COERCE(x) 00635 */ 00636 #if defined(DEBUG_DESPERATE) 00637 // This can be useful when you are desperate to see where 00638 // some sequence of event happened, as it prints the rc at each 00639 // augment. 00640 #define RC_AUGMENT(rc) \ 00641 (rc.add_trace_info(__FILE__, __LINE__), (cerr << rc << endl), rc) 00642 #else 00643 #define RC_AUGMENT(rc) \ 00644 rc.add_trace_info(__FILE__, __LINE__) 00645 #endif 00646 00647 /**\def RC_PUSH(rc, e) 00648 * \brief Augment stack trace with another error code. 00649 * 00650 * Add stack trace information (file, line, error) to a return code. 00651 * This is to return from a method or function upon 00652 * receiving an error from a method or function that it called, when 00653 * a what you want to return to your caller is a 00654 * different error code from that returned by the method just called. 00655 * Used by \ref #W_DO_PUSH(x, e) and 00656 * \ref #W_DO_PUSH_MSG(x,e, m) 00657 */ 00658 #define RC_PUSH(rc, e) \ 00659 rc.push(__FILE__, __LINE__, e) 00660 00661 00662 /**\def RC_APPEND_MSG(rc, m) 00663 * \brief Augment stack trace with more arbitrary string information. 00664 * 00665 * Add a char string representing more information to a return code. 00666 * Used by \ref W_RETURN_RC_MSG(e, m), 00667 * \ref W_DO_MSG(x, m), 00668 * \ref W_DO_PUSH_MSG(x, m), and 00669 * \ref W_COERCE_MSG(x, m) 00670 */ 00671 #define RC_APPEND_MSG(rc, m) \ 00672 do { \ 00673 w_ostrstream os; \ 00674 os m << ends; \ 00675 rc->append_more_info_msg(os.c_str()); \ 00676 } while (0) 00677 00678 /**\def W_RETURN_RC_MSG(e, m) 00679 * \brief Return with a return code that contains the given error code and additional message. 00680 */ 00681 #define W_RETURN_RC_MSG(e, m) \ 00682 do { \ 00683 w_rc_t __e = RC(e); \ 00684 RC_APPEND_MSG(__e, m); \ 00685 return __e; \ 00686 } while (0) 00687 00688 /**\def W_EDO(x) 00689 * \brief Call a method or function \b x that returns a lightweight error code from a method that returns a w_rc_t. 00690 * 00691 * This macro is used deep in the storage manager to call a 00692 * method or function that returns a (lightweight) error code rather than 00693 * a \ref #w_rc_t. 00694 * It checks the returned code for the error case, and if it finds an 00695 * error, it creates a w_rc_t with the error code returned by the called 00696 * function or method. 00697 */ 00698 #define W_EDO(x) \ 00699 do { \ 00700 w_rc_t::errcode_t __e = (x); \ 00701 if (W_EXPECT_NOT(__e)) return RC(__e); \ 00702 } while (0) 00703 00704 /**\def W_DO(x) 00705 * \brief Call a method or function \b x. 00706 * 00707 * This macro is the normal idiom for calling a method or function. 00708 * Most methods and functions return a w_rc_t. This macro calls \b x 00709 * and checks its returned value. If an error is encountered, it 00710 * immediately returns from the current function or method, augmenting 00711 * the stack trace held by the return code. 00712 */ 00713 #define W_DO(x) \ 00714 do { \ 00715 w_rc_t __e = (x); \ 00716 if (W_EXPECT_NOT(__e.is_error())) return RC_AUGMENT(__e); \ 00717 } while (0) 00718 00719 /**\def W_DO_MSG(x) 00720 * \brief Call a method or function \b x. 00721 * 00722 * Like \ref #W_DO, but any error returned contains 00723 * the additional information message \b m. 00724 */ 00725 #define W_DO_MSG(x, m) \ 00726 do { \ 00727 w_rc_t __e = (x); \ 00728 if (W_EXPECT_NOT(__e.is_error())) { \ 00729 RC_AUGMENT(__e); \ 00730 RC_APPEND_MSG(__e, m); \ 00731 return __e; \ 00732 } \ 00733 } while (0) 00734 00735 /**\def W_DO_GOTO(rc, x) 00736 * \brief Idiom for unusual error-handling before returning. 00737 * 00738 * This macro is used to process errors that require special handling before 00739 * the calling function can return. 00740 * It calls the method or function \b x, and if \b x returns an error, it 00741 * transfers control to the label \b failure. 00742 * 00743 * Like \ref #W_DO, but: 00744 * - rather than defining a local w_rc_t, it uses an elsewhere-defined 00745 * w_rc_t instance; this is because: 00746 * - rather than returning in the error case, it branches to the label 00747 * \b failure. 00748 * 00749 * \note: the label \b failure must exist in the the calling function, and 00750 * the argument \b rc must have been declared in the calling scope. 00751 * Presumably the argument \b rc is declared in the scope of \b failure: 00752 * as well, so that it can process the error. 00753 */ 00754 // W_DO_GOTO assumes the rc was already declared 00755 #define W_DO_GOTO(rc/*w_rc_t*/, x) \ 00756 do { \ 00757 (rc) = (x); \ 00758 if (W_EXPECT_NOT(rc.is_error())) { \ 00759 RC_AUGMENT(rc); \ 00760 goto failure; \ 00761 } \ 00762 } while (0) 00763 00764 /**\def W_COERCE(x) 00765 * \brief Call a function or method \b x, fail catastrophically if error is returned. 00766 * 00767 * This macro is like \ref #W_DO(x), but instead of returning in the error 00768 * case, it fails catastrophically. 00769 * It is used in cases such as these: 00770 * - Temporary place-holder where the coder hasn't written 00771 * the failure-handling code 00772 * - The calling function or method API has no means to return 00773 * error information, and this case hasn't yet been accommodated. 00774 * - The called \b x should never return an error 00775 * in this case, and doing so would indicate a programming error. 00776 * - The called \b x never returns an error at the time the calling code 00777 * is written, and should the called code \b x change, 00778 * the calling code should probably be adjusted to handle any new error. 00779 * 00780 * The call to __e.fatal() prints the stack trace and additional information 00781 * associated with the w_rc_t before it croaks. 00782 */ 00783 #define W_COERCE(x) \ 00784 do { \ 00785 w_rc_t __e = (x); \ 00786 if (W_EXPECT_NOT(__e.is_error())) { \ 00787 RC_AUGMENT(__e); \ 00788 __e.fatal(); \ 00789 } \ 00790 } while (0) 00791 00792 /**\def W_COERCE_MSG(x, m) 00793 * \brief Same as \ref #W_COERCE(x) but adds a string message before croaking. 00794 */ 00795 #define W_COERCE_MSG(x, m) \ 00796 do { \ 00797 w_rc_t __em = (x); \ 00798 if (W_EXPECT_NOT(__em.is_error())) { \ 00799 RC_APPEND_MSG(__em, m); \ 00800 W_COERCE(__em); \ 00801 } \ 00802 } while (0) 00803 00804 /**\def W_FATAL(e) 00805 * \brief Croak with the error code \b e. 00806 */ 00807 #define W_FATAL(e) W_COERCE(RC(e)) 00808 00809 /**\def W_FATAL_RC(rc) 00810 * \brief Croak with the return code \b rc. 00811 */ 00812 #define W_FATAL_RC(rc) W_COERCE(rc) 00813 00814 /**\def W_FATAL_MSG(e, m) 00815 * \brief Croak with the error code \b e and message \b m. 00816 */ 00817 #define W_FATAL_MSG(e, m) W_COERCE_MSG(RC(e), m) 00818 00819 /**\def W_IGNORE(x, m) 00820 * \brief Invoke \b x and ignore its result. 00821 */ 00822 #define W_IGNORE(x) ((void) x.is_error()) 00823 00824 /*<std-footer incl-file-exclusion='W_RC_H'> -- do not edit anything below this line -- */ 00825 00826 #endif /*</std-footer>*/