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.73 2010/12/08 17:37:37 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 informatin (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 Retrun 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_DO_PUSH(x, e)
00765  * \brief Call a function or method \b x, if error, push error code \b e on the stack and return.
00766  *
00767  * This macro is like \ref #W_DO(x), but it adds an error code \b e to 
00768  * the stack trace before returning.
00769  */
00770 #define W_DO_PUSH(x, e)                    \
00771 do {                            \
00772     w_rc_t __e = (x);                    \
00773     if (W_EXPECT_NOT(__e.is_error()))  { return RC_PUSH(__e, e); }    \
00774 } while (0)
00775 
00776 /**\def  W_DO_PUSH_MSG(x, e, m)
00777  * \brief Call a function or method \b x, if error, push error code \b e on the stack and return.
00778  *
00779  * This macro is like \ref #W_DO_PUSH(x, e), but it adds an additional
00780  * information message \b m to
00781  * the stack trace before returning.
00782  */
00783 #define W_DO_PUSH_MSG(x, e, m)                \
00784 do {                            \
00785     w_rc_t __e = (x);                    \
00786     if (W_EXPECT_NOT(__e.is_error()))  {                \
00787         RC_PUSH(__e, e);                \
00788         RC_APPEND_MSG(__e, m);                \
00789     return __e;                    \
00790     }                            \
00791 } while (0)
00792 
00793 /**\def  W_COERCE(x)
00794  * \brief Call a function or method \b x, fail catastrophically if error is returned.
00795  *
00796  * This macro is like \ref #W_DO(x), but instead of returning in the error
00797  * case, it fails catastrophically.
00798  * It is used in cases such as these:
00799  * - Temporary place-holder where the coder hasn't written 
00800  *   the failure-handling code
00801  * - The calling function or method API has no means to return 
00802  *   error information, and this case hasn't yet been accommodated.
00803  * - The called \b x should never return an error 
00804  *   in this case, and doing so would indicate a programming error.
00805  * - The called \b x never returns an error at the time the calling code 
00806  *   is written, and should the called code \b x change, 
00807  *   the calling code should probably be adjusted to handle any new error.
00808  *
00809  *   The call to __e.fatal() prints the stack trace and additional information
00810  *   associated with the w_rc_t before it croaks.
00811  */
00812 #define W_COERCE(x)                      \
00813 do {                            \
00814     w_rc_t __e = (x);                    \
00815     if (W_EXPECT_NOT(__e.is_error()))  {                \
00816     RC_AUGMENT(__e);                \
00817     __e.fatal();                    \
00818     }                            \
00819 } while (0)
00820 
00821 /**\def  W_COERCE_MSG(x, m)
00822  * \brief Same as \ref #W_COERCE(x) but adds a string message before croaking. 
00823  */
00824 #define W_COERCE_MSG(x, m)                \
00825 do {                            \
00826     w_rc_t __em = (x);                    \
00827     if (W_EXPECT_NOT(__em.is_error()))  {                \
00828     RC_APPEND_MSG(__em, m);                \
00829     W_COERCE(__em);                    \
00830     }                            \
00831 } while (0)
00832 
00833 /**\def  W_FATAL(e)
00834  * \brief Croak with the error code \b e.
00835  */
00836 #define W_FATAL(e)           W_COERCE(RC(e))
00837 
00838 /**\def  W_FATAL_RC(rc)
00839  * \brief Croak with the return code \b rc.
00840  */
00841 #define W_FATAL_RC(rc)        W_COERCE(rc)
00842 
00843 /**\def  W_FATAL_MSG(e, m)
00844  * \brief Croak with the error code \b e and message \b m.
00845  */
00846 #define W_FATAL_MSG(e, m)    W_COERCE_MSG(RC(e), m)
00847 
00848 /**\def  W_IGNORE(x, m)
00849  * \brief Invoke \b x and ignore its result.
00850  */
00851 #define W_IGNORE(x)    ((void) x.is_error())
00852 
00853 /*<std-footer incl-file-exclusion='W_RC_H'>  -- do not edit anything below this line -- */
00854 
00855 #endif          /*</std-footer>*/

Generated on Thu Dec 9 08:42:27 2010 for Shore Storage Manager by  doxygen 1.4.7