Zero  0.1.0
Public Member Functions | Private Attributes | List of all members
w_rc_t Class Reference

Return code for most functions and methods. More...

#include <w_rc.h>

Public Member Functions

 w_rc_t ()
 
 w_rc_t (w_error_codes error_code)
 Instantiate a return code without a custom error message nor stacktrace. More...
 
 w_rc_t (const char *filename, uint32_t linenum, w_error_codes error_code, const char *custom_message=nullptr)
 Instantiate a return code with stacktrace and optionally a custom error message. More...
 
 w_rc_t (const w_rc_t &other)
 
 w_rc_t (const w_rc_t &other, const char *filename, uint32_t linenum, const char *more_custom_message=nullptr)
 
w_rc_toperator= (w_rc_t const &other)
 
 ~w_rc_t ()
 
bool is_error () const
 True if this return code is not RCOK or equivalent. This must be called for every w_rc_t before destruction. The idiomatic macros W_DO and its companions do that check for you, and should be used most of the time. More...
 
w_error_codes err_num () const
 
const char * get_message () const
 
const char * get_custom_message () const
 
void append_custom_message (const char *more_custom_message)
 
uint16_t get_stack_depth () const
 
uint16_t get_linenum (uint16_t stack_index) const
 
const char * get_filename (uint16_t stack_index) const
 
void verify () const
 
void fatal () const
 Fail catastrophically after describing the error. This is called from W_COERCE to handle an unexpected error. More...
 

Private Attributes

const char * _filenames [MAX_RCT_STACK_DEPTH]
 Filenames of stacktraces. This is deep-first, so _filenames[0] is where the w_rc_t was initially instantiated. When we reach MAX_RCT_STACK_DEPTH, we don't store any more stacktraces and just say ".. more" in the output. We do NOT deep-copy the strings, assuming the file name string is const and permanent. We only copy the pointers when passing around. As far as we use "__FILE__" macro to get file name, this is the always case. More...
 
uint16_t _linenums [MAX_RCT_STACK_DEPTH]
 Line numbers of stacktraces. More...
 
const char * _custom_message
 Optional custom error message. We deep-copy this string if it's non-NULL. The reason why we don't use auto_ptr etc for this is that they are also expensive and will screw things up if someone misuse our class. Custom error message should be rare, anyways. More...
 
w_error_codes _error_code
 Integer error code. More...
 
uint16_t _stack_depth
 Current stack depth. Value 0 implies that we don't pass around stacktrace for this return code, bypassing stacktrace collection. More...
 
bool _checked
 Whether someone already checked the error code of this object. More...
 

Detailed Description

Return code for most functions and methods.

Maximum stack trace depth

When the return code is an error code, we propagate back the stack trace for easier debugging. Original Shore-MT had a linked-list for this and, to ameriolate allocate/delete cost for it, had a TLS object pool. Unfortunately, it caused issues in some environments and was not readable/maintainable. Instead, Foster-BTree limits the depth of stacktraces stored in w_rc_t to a reasonable number enough for debugging; MAX_RCT_STACK_DEPTH. We then store just line numbers and const pointers to file names. No heap allocation. The only thing that has to be allocated on heap is a custom error message. However, there are not many places that use custom error messages, so the cost usually doesn't happen.

Forced return code checking

An error code must be checked by some code, else it will report an "error-not-checked" warning in stderr (NOT fatal errors). This is costly but useful for checking that code copes with errors. Of course, it does not do a static analysis; rather it is a dynamic check and so it cannot catch all code that ignores return codes.

Constructor & Destructor Documentation

§ w_rc_t() [1/5]

w_rc_t::w_rc_t ( )
inline

Empty constructor. This is same as duplicating RCOK.

§ w_rc_t() [2/5]

w_rc_t::w_rc_t ( w_error_codes  error_code)
inlineexplicit

Instantiate a return code without a custom error message nor stacktrace.

Parameters
[in]error_codeError code, either OK or real errors.

This is the most (next to RCOK) light-weight way to create/propagate a return code. Use this one if you do not need a detail information to debug the error (eg, error whose cause is obvious, an expected error that is immediately caught, etc).

§ w_rc_t() [3/5]

w_rc_t::w_rc_t ( const char *  filename,
uint32_t  linenum,
w_error_codes  error_code,
const char *  custom_message = nullptr 
)
inline

Instantiate a return code with stacktrace and optionally a custom error message.

Parameters
[in]filenamefile name of the current place. It must be a const and permanent string, such as what "__FILE__" returns. Note that we do NOT do deep-copy of the strings.
[in]linenumline number of the current place. Usually "__LINE__".
[in]error_codeError code, must be real errors.
[in]custom_messageOptional custom error message in addition to the default one inferred from error code. If you pass a non-NULL string to this argument, we do deep-copy for each hand-over, so it's EXPENSIVE!

§ w_rc_t() [4/5]

w_rc_t::w_rc_t ( const w_rc_t other)
inline

Copy constructor.

§ w_rc_t() [5/5]

w_rc_t::w_rc_t ( const w_rc_t other,
const char *  filename,
uint32_t  linenum,
const char *  more_custom_message = nullptr 
)
inline

Copy constructor to augment the stacktrace.

§ ~w_rc_t()

w_rc_t::~w_rc_t ( )
inline

Will warn in stderr if the error code is not checked yet.

Member Function Documentation

§ append_custom_message()

void w_rc_t::append_custom_message ( const char *  more_custom_message)
inline

Appends more custom error message at the end.

§ err_num()

w_error_codes w_rc_t::err_num ( ) const
inline

Return the integer error code.

§ fatal()

void w_rc_t::fatal ( ) const
inline

Fail catastrophically after describing the error. This is called from W_COERCE to handle an unexpected error.

§ get_custom_message()

const char * w_rc_t::get_custom_message ( ) const
inline

Returns the custom error message.

§ get_filename()

const char * w_rc_t::get_filename ( uint16_t  stack_index) const
inline

Returns the file name of the given stack position.

§ get_linenum()

uint16_t w_rc_t::get_linenum ( uint16_t  stack_index) const
inline

Returns the line number of the given stack position.

§ get_message()

const char * w_rc_t::get_message ( ) const
inline

Returns the error message inferred by the error code.

§ get_stack_depth()

uint16_t w_rc_t::get_stack_depth ( ) const
inline

Returns the depth of stack this error code has collected.

§ is_error()

bool w_rc_t::is_error ( ) const
inline

True if this return code is not RCOK or equivalent. This must be called for every w_rc_t before destruction. The idiomatic macros W_DO and its companions do that check for you, and should be used most of the time.

See also the following macros:

§ operator=()

w_rc_t & w_rc_t::operator= ( w_rc_t const &  other)
inline

Copy constructor.

§ verify()

void w_rc_t::verify ( ) const
inline

Output a warning to stderr if the error is not checked yet.

Member Data Documentation

§ _checked

bool w_rc_t::_checked
mutableprivate

Whether someone already checked the error code of this object.

§ _custom_message

const char* w_rc_t::_custom_message
private

Optional custom error message. We deep-copy this string if it's non-NULL. The reason why we don't use auto_ptr etc for this is that they are also expensive and will screw things up if someone misuse our class. Custom error message should be rare, anyways.

§ _error_code

w_error_codes w_rc_t::_error_code
private

Integer error code.

Important invariants

If this value is w_error_ok, all other members have no meanings and we might not even bother clearing them for better performance because that's by far the common case. So, all functions in this class should first check if this value is w_error_ok or not to avoid further processing.

§ _filenames

const char* w_rc_t::_filenames[MAX_RCT_STACK_DEPTH]
private

Filenames of stacktraces. This is deep-first, so _filenames[0] is where the w_rc_t was initially instantiated. When we reach MAX_RCT_STACK_DEPTH, we don't store any more stacktraces and just say ".. more" in the output. We do NOT deep-copy the strings, assuming the file name string is const and permanent. We only copy the pointers when passing around. As far as we use "__FILE__" macro to get file name, this is the always case.

§ _linenums

uint16_t w_rc_t::_linenums[MAX_RCT_STACK_DEPTH]
private

Line numbers of stacktraces.

§ _stack_depth

uint16_t w_rc_t::_stack_depth
private

Current stack depth. Value 0 implies that we don't pass around stacktrace for this return code, bypassing stacktrace collection.


The documentation for this class was generated from the following file: