w_exception.h

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 class ssm_x {
00546     typedef w_error_t::err_num_t  errcode_t;
00547  private:
00548   const char *_file;
00549   int         _line;
00550   errcode_t   _e;
00551  public:
00552  ssm_x(const char *f, int l, errcode_t e) :
00553   _file(f), _line(l), _e(e) {}
00554  ~ssm_x() {}
00555 };
00556 
00557 extern  w_rc_t throwit(const char *f, int l, errcode_t e, int s=0) ;
00558 
00559 /**\def  RC(e)  
00560  * \brief Normal error-case return. 
00561  *
00562  * Create a return code with the current file, line, and error code x.
00563  * This is the normal way to return from a method or function.
00564  */
00565 #define RC(e)       throwit(__FILE__, __LINE__, e)
00566 
00567 /**\def  RC2(e,s)  
00568  * \brief Normal error-case return with sys_error.
00569  *
00570  * Create a return code with the current file, line, and error code e,
00571  * and system error number s.
00572  * This is the normal way to return an 
00573  * error indication from a method or function that encountered a system error.
00574  * The value \b s allows the user to convey an ::errno value in the return code.
00575  */
00576 #define RC2(e,s)    \
00577     throwit(__FILE__, __LINE__, e, s)
00578 
00579 // This, at least, avoids one constructor call
00580 /**\def  RCOK
00581  * \brief Normal return value for no-error case.
00582  *
00583  * Const return code that indicates no error.
00584  * This is the normal way to return from a method or function.
00585  */
00586 #define RCOK        w_rc_t::rc_ok
00587 
00588 /**\def  MAKERC(condition,e)
00589  * \brief Return error \b e if \b condition is false.
00590  *
00591  * Create a return code that indicates an error iff the condition is false,
00592  * otherwise return with no-error indication.
00593  */
00594 #define MAKERC(condition,e)    ((condition) ? RC(e) : RCOK)
00595 
00596 
00597 
00598 /********************************************************************
00599  *
00600  *  More Macros for using rc.
00601  *
00602  *  RC_AUGMENT(rc)   : add file and line number to the rc
00603  *  RC_PUSH(rc, e)   : add a new error code to rc
00604  *
00605  *  e.g. 
00606  *    w_rc_t rc = create_file(f);
00607  *      if (rc)  return RC_AUGMENT(rc);
00608  *    rc = close_file(f);
00609  *    if (rc)  return RC_PUSH(rc, eCANNOTCLOSE)
00610  *
00611  *********************************************************************/
00612 
00613  
00614 /**\def  RC_AUGMENT(rc)
00615  * \brief Augment stack trace.
00616  *
00617  * Add stack trace information (file, line) to a return code. 
00618  * This is the normal way to return from a method or function upon
00619  * receiving an error from a method or function that it called.
00620  * Used by \ref #W_DO(x), \ref #W_DO_MSG(x,m), \ref #W_DO_GOTO(rc,x),
00621  * and \ref #W_COERCE(x)
00622  */
00623 #define RC_AUGMENT(rc)                    \
00624     rc.add_trace_info(__FILE__, __LINE__)
00625 
00626 /**\def  RC_PUSH(rc, e)
00627  * \brief Augment stack trace with another error code.
00628  *
00629  * Add stack trace information (file, line, error) to a return code.
00630  * This is to return from a method or function upon
00631  * receiving an error from a method or function that it called, when
00632  * a what you want to return to your caller is a
00633  * different error code from that returned by the method just called.
00634  * Used by \ref #W_DO_PUSH(x, e) and
00635  * \ref #W_DO_PUSH_MSG(x,e, m)
00636  */
00637 #define RC_PUSH(rc, e)                    \
00638     rc.push(__FILE__, __LINE__, e)
00639 
00640 
00641 /**\def  RC_APPEND_MSG(rc, m)
00642  * \brief Augment stack trace with more arbitrary string information.
00643  *
00644  * Add a char string representing more information to a return code.
00645  * Used by \ref W_RETURN_RC_MSG(e, m),
00646  * \ref W_DO_MSG(x, m), 
00647  * \ref W_DO_PUSH_MSG(x, m), and
00648  * \ref W_COERCE_MSG(x, m)
00649  */
00650 #define RC_APPEND_MSG(rc, m)                \
00651 do {                            \
00652     w_ostrstream os;                    \
00653     os  m << ends;                    \
00654     rc->append_more_info_msg(os.c_str());        \
00655 } while (0)
00656 
00657 /**\def  W_RETURN_RC_MSG(e, m)
00658  * \brief Return with a return code that contains the given error code and additional message.
00659  */
00660 #define W_RETURN_RC_MSG(e, m)                \
00661 do {                            \
00662     w_rc_t __e = RC(e);                    \
00663     RC_APPEND_MSG(__e, m);                    \
00664     return __e;                        \
00665 } while (0)
00666 
00667 /**\def  W_EDO(x)
00668  * \brief Call a method or function \b x that returns a lightweight error code from a method that returns a w_rc_t.
00669  *
00670  * This macro is used deep in the storage manager to call a 
00671  * method or function that returns a (lightweight) error code rather than
00672  * a \ref #w_rc_t.
00673  * It checks the returned code for the error case, and if it finds an
00674  * error, it creates a w_rc_t with the error code returned by the called
00675  * function or method.
00676  */
00677 #define W_EDO(x)                      \
00678 do {                            \
00679     w_rc_t::errcode_t __e = (x);                    \
00680     if (__e) return RC(__e);        \
00681 } while (0)
00682 
00683 /**\def  W_DO(x)
00684  * \brief Call a method or function \b x. 
00685  *
00686  * This macro is the normal idiom for calling a method or function.
00687  * Most methods and functions return a w_rc_t. This macro calls \b x 
00688  * and checks its returned value.  If an error is encountered, it
00689  * immediately returns from the current function or method, augmenting
00690  * the stack trace held by the return code.
00691  */
00692 #define W_DO(x)                      \
00693 do {                            \
00694     w_rc_t __e = (x);                    \
00695     if (__e.is_error()) return RC_AUGMENT(__e); \
00696 } while (0)
00697 
00698 /**\def  W_DO_MSG(x)
00699  * \brief Call a method or function \b x. 
00700  *
00701  * Like \ref #W_DO, but any error returned contains
00702  * the additional information message \b m.
00703  */
00704 #define W_DO_MSG(x, m)                    \
00705 do {                            \
00706     w_rc_t __e = (x);                    \
00707     if (__e.is_error()) {                \
00708         RC_AUGMENT(__e);                \
00709         RC_APPEND_MSG(__e, m);                \
00710         return __e;                    \
00711     }                            \
00712 } while (0)
00713 
00714 /**\def  W_DO_GOTO(rc, x)
00715  * \brief Idiom for unusual error-handling  before returning.
00716  *
00717  *  This macro is used to process errors that require special handling before
00718  *  the calling function can return.
00719  *  It calls the method or function \b x, and if \b x returns an error, it
00720  *  transfers control to the label \b failure.
00721  *
00722  * Like \ref #W_DO, but: 
00723  * - rather than defining a local w_rc_t, it uses an elsewhere-defined
00724  *   w_rc_t instance; this is because: 
00725  * - rather than returning in the error case, it branches to the label
00726  *   \b failure.
00727  *
00728  * \note: the label \b failure must exist in the the calling function, and
00729  * the argument \b rc must have been declared in the calling scope. 
00730  * Presumably the argument \b rc is declared in the scope of \b failure:
00731  * as well, so that it can process the error.
00732  */
00733 // W_DO_GOTO assumes the rc was already declared 
00734 #define W_DO_GOTO(rc/*w_rc_t*/, x)          \
00735 do {                            \
00736     (rc) = (x);    \
00737     if (rc.is_error()) { \
00738         RC_AUGMENT(rc);              \
00739         goto failure;    \
00740     } \
00741 } while (0)
00742 
00743 /**\def  W_COERCE(x)
00744  * \brief Call a function or method \b x, fail catastrophically if error is returned.
00745  *
00746  * This macro is like \ref #W_DO(x), but instead of returning in the error
00747  * case, it fails catastrophically.
00748  * It is used in cases such as these:
00749  * - Temporary place-holder where the coder hasn't written 
00750  *   the failure-handling code
00751  * - The calling function or method API has no means to return 
00752  *   error information, and this case hasn't yet been accommodated.
00753  * - The called \b x should never return an error 
00754  *   in this case, and doing so would indicate a programming error.
00755  * - The called \b x never returns an error at the time the calling code 
00756  *   is written, and should the called code \b x change, 
00757  *   the calling code should probably be adjusted to handle any new error.
00758  *
00759  *   The call to __e.fatal() prints the stack trace and additional information
00760  *   associated with the w_rc_t before it croaks.
00761  */
00762 #define W_COERCE(x)                      \
00763 do {                            \
00764     w_rc_t __e = (x);                    \
00765     if (__e.is_error())  {                \
00766     RC_AUGMENT(__e);                \
00767     __e.fatal();                    \
00768     }                            \
00769 } while (0)
00770 
00771 /**\def  W_COERCE_MSG(x, m)
00772  * \brief Same as \ref #W_COERCE(x) but adds a string message before croaking. 
00773  */
00774 #define W_COERCE_MSG(x, m)                \
00775 do {                            \
00776     w_rc_t __em = (x);                    \
00777     if (__em.is_error())  {                \
00778     RC_APPEND_MSG(__em, m);                \
00779     W_COERCE(__em);                    \
00780     }                            \
00781 } while (0)
00782 
00783 /**\def  W_FATAL(e)
00784  * \brief Croak with the error code \b e.
00785  */
00786 #define W_FATAL(e)           W_COERCE(RC(e))
00787 
00788 /**\def  W_FATAL_RC(rc)
00789  * \brief Croak with the return code \b rc.
00790  */
00791 #define W_FATAL_RC(rc)        W_COERCE(rc)
00792 
00793 /**\def  W_FATAL_MSG(e, m)
00794  * \brief Croak with the error code \b e and message \b m.
00795  */
00796 #define W_FATAL_MSG(e, m)    W_COERCE_MSG(RC(e), m)
00797 
00798 /**\def  W_IGNORE(x, m)
00799  * \brief Invoke \b x and ignore its result.
00800  */
00801 #define W_IGNORE(x)    ((void) x.is_error())
00802 
00803 /*<std-footer incl-file-exclusion='W_RC_H'>  -- do not edit anything below this line -- */
00804 
00805 #endif          /*</std-footer>*/

Generated on Mon Jan 2 15:13:57 2012 for Shore Storage Manager by  doxygen 1.4.7