Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
|
Go to the source code of this file.
Classes | |
struct | StatusDefinition |
struct | StatusDefinitionBucket |
Namespaces | |
namespace | INFO |
namespace | ERR |
Macros | |
#define | STATUS_ADD_DEFINITIONS(definitions) static StatusDefinitionBucket definitions##_bucket = { definitions, ARRAY_SIZE(definitions), StatusAddDefinitions(&definitions##_bucket) } |
add a module's array of StatusDefinition to the list. More... | |
#define | WARN_RETURN(status) |
#define | WARN_IF_ERR(expression) |
#define | RETURN_STATUS_IF_ERR(expression) |
#define | WARN_RETURN_STATUS_IF_ERR(expression) |
#define | WARN_THROW(status) |
#define | THROW_STATUS_IF_ERR(expression) |
#define | WARN_THROW_STATUS_IF_ERR(expression) |
#define | RETURN_STATUS_FROM_CALLBACK(expression) |
#define | RETURN_0_IF_ERR(expression) |
#define | WARN_IF_FALSE(expression) |
#define | WARN_RETURN_0_IF_FALSE(expression) |
Typedefs | |
typedef i64 | Status |
Error handling system. More... | |
Functions | |
StatusDefinitionBucket * | StatusAddDefinitions (StatusDefinitionBucket *bucket) |
(called via STATUS_ADD_DEFINITIONS) More... | |
wchar_t * | StatusDescription (Status status, wchar_t *buf, size_t max_chars) |
generate textual description of a Status. More... | |
int | ErrnoFromStatus (Status status) |
Status | StatusFromErrno () |
Variables | |
const Status | INFO::OK = 0 |
const Status | INFO::SKIPPED = +100001 |
const Status | INFO::CANNOT_HANDLE = +100002 |
const Status | INFO::ALL_COMPLETE = +100003 |
const Status | ERR::FAIL = -1 |
const Status | ERR::LOGIC = -100010 |
const Status | ERR::EXCEPTION = -100011 |
const Status | ERR::TIMED_OUT = -100012 |
const Status | ERR::REENTERED = -100013 |
const Status | ERR::CORRUPTED = -100014 |
const Status | ERR::ABORTED = -100015 |
const Status | ERR::INVALID_ALIGNMENT = -100020 |
const Status | ERR::INVALID_OFFSET = -100021 |
const Status | ERR::INVALID_HANDLE = -100022 |
const Status | ERR::INVALID_POINTER = -100023 |
const Status | ERR::INVALID_SIZE = -100024 |
const Status | ERR::INVALID_FLAG = -100025 |
const Status | ERR::INVALID_PARAM = -100026 |
const Status | ERR::INVALID_VERSION = -100027 |
const Status | ERR::AGAIN = -100030 |
const Status | ERR::LIMIT = -100031 |
const Status | ERR::NOT_SUPPORTED = -100032 |
const Status | ERR::NO_MEM = -100033 |
const Status | ERR::_1 = -100101 |
const Status | ERR::_2 = -100102 |
const Status | ERR::_3 = -100103 |
const Status | ERR::_4 = -100104 |
const Status | ERR::_5 = -100105 |
const Status | ERR::_6 = -100106 |
const Status | ERR::_7 = -100107 |
const Status | ERR::_8 = -100108 |
const Status | ERR::_9 = -100109 |
const Status | ERR::_11 = -100111 |
const Status | ERR::_12 = -100112 |
const Status | ERR::_13 = -100113 |
const Status | ERR::_14 = -100114 |
const Status | ERR::_15 = -100115 |
const Status | ERR::_16 = -100116 |
const Status | ERR::_17 = -100117 |
const Status | ERR::_18 = -100118 |
const Status | ERR::_19 = -100119 |
const Status | ERR::_21 = -100121 |
const Status | ERR::_22 = -100122 |
const Status | ERR::_23 = -100123 |
const Status | ERR::_24 = -100124 |
const Status | ERR::_25 = -100125 |
const Status | ERR::_26 = -100126 |
const Status | ERR::_27 = -100127 |
const Status | ERR::_28 = -100128 |
const Status | ERR::_29 = -100129 |
#define RETURN_0_IF_ERR | ( | expression | ) |
#define RETURN_STATUS_FROM_CALLBACK | ( | expression | ) |
#define RETURN_STATUS_IF_ERR | ( | expression | ) |
#define STATUS_ADD_DEFINITIONS | ( | definitions | ) | static StatusDefinitionBucket definitions##_bucket = { definitions, ARRAY_SIZE(definitions), StatusAddDefinitions(&definitions##_bucket) } |
add a module's array of StatusDefinition to the list.
typically invoked at file scope.
definitions | name (identifier) of the array |
#define THROW_STATUS_IF_ERR | ( | expression | ) |
#define WARN_IF_ERR | ( | expression | ) |
#define WARN_IF_FALSE | ( | expression | ) |
#define WARN_RETURN | ( | status | ) |
#define WARN_RETURN_0_IF_FALSE | ( | expression | ) |
#define WARN_RETURN_STATUS_IF_ERR | ( | expression | ) |
#define WARN_THROW | ( | status | ) |
#define WARN_THROW_STATUS_IF_ERR | ( | expression | ) |
Error handling system.
To convey information about what failed, the alternatives are unique integral codes and direct pointers to descriptive text. Both occupy the same amount of space, but codes are easier to internationalize.
When a low-level function has failed, this must be conveyed to the higher-level application logic across several functions on the call stack. There are two alternatives: 1) check at each call site whether a function failed; if so, return to the caller. 2) throw an exception.
We will discuss the advantages and disadvantages of exceptions, which are the opposites of call site checking.
Both have their place. Our recommendation is to throw error code exceptions when checking call sites and propagating errors becomes tedious. However, inter-module boundaries should always return error codes for interoperability with other languages.
As mentioned above, this approach requires discipline. We provide "enforcer" macros to simplify this task by propagating errors to the calling function.
Consider the following example: Status status = doWork(); if(status != INFO::OK) return status; This can be replaced by: RETURN_STATUS_IF_ERR(doWork());
This provides a visible sign that the code handles errors but reduces clutter.
When a function fails, there are 2 places we can raise a warning: as soon as the error condition is known, or higher on the call stack.
We prefer the former because it is easier to ensure that all possible return paths have been covered: search for all "return ERR::*" or "return StatusFrom*" that are not followed by a "// NOWARN" comment. The latter approach also risks multiple warnings along the call stack for the same error.
Note the special case of "validator" functions that e.g. verify the state of an object: we now discuss pros/cons of just returning errors without warning, and having their callers take care of that.
Each module header defines its own error codes to avoid a full rebuild whenever a new code is added.
Error codes start at -100000 (warnings are positive, but the corresponding negative value should not be used to avoid confusion). This scheme avoids collisions with all other known error codes.
Each header gets 100 possible values; the tens value may be used to denote groups within that header.
The subsystem is denoted by the ten-thousands digit: 0 general 1 file 2 res (resource management) 3 sysdep (system-dependent) 4 win (Windows-specific)
To summarize: +/-1SHHCC (S=subsystem, HH=header, CC=code number)
10 general 00CC misc 03CC path 04CC debug 05CC debug_stl 06CC secure_crt 07CC wchar
11 file 01CC vfs 03CC file 04CC archive
12 res 00CC h_mgr 01CC tex
13 sysdep 00CC cpu 01CC os_cpu
14 win 00CC whrt
int ErrnoFromStatus | ( | Status | status | ) |
used in wposix - underlying functions return Status but must be translated to errno at e.g. the mmap interface level. higher-level code that calls mmap will in turn convert back to Status.
StatusDefinitionBucket * StatusAddDefinitions | ( | StatusDefinitionBucket * | bucket | ) |
(called via STATUS_ADD_DEFINITIONS)
bucket | is being added; its definitions and numDefinitions must already be initialized. |
(this function must be callable as a static initializer; initializing next avoids the need for a separate dummy variable)
wchar_t * StatusDescription | ( | Status | status, |
wchar_t * | buf, | ||
size_t | max_chars | ||
) |
generate textual description of a Status.
buf | destination buffer (allows generating strings with the code's numerical value if no definition is found) |
max_chars | size of buffer [characters] |