w_rc.h

Go to the documentation of this file.
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>*/

Generated on Wed Jul 7 17:22:32 2010 for Shore Storage Manager by  doxygen 1.4.7