Tech/LxEngine/Error Handling
From Athile
Contents |
Assertions
lx::core::assert( precondition, [const char* format, ...] )
Reserved for catching programmer preventable conditions. This obviously is not a strict definition, as it is not possible for all such conditions to be foreseen in advance, and may instead result instead from unforeseen runtime conditions. asserts are not compiled into production code.
With the rare exception of very high-performance inner-loop code, asserts should be accompanied with production code for issuing and error or warning along with the assert.
Examples
- Method/Function pre-conditions & post-conditions
Suggestions
- Overuse rather than under-use asserts during development of new code. It is better to have to remove an assert for an unexpected, but possible condition than maintain incorrect expectations about
- asserts are another form of documentation. Since there is not runtime penalty to production code, using asserts as a form of commentary on the expected behavior and data conditions is highly encouraged.
Fatal Errors
lx::core::fatal( const char* format, ...)
Reserved for non-recoverable errors where the application should save critical data, but otherwise shutdown as soon as possible. Will throw an lx::fatal_exception exception. During 'normal' operations, a fatal error should never occur.
An application should catch a lx::fatal_exception only to save any critical data then re-throw the exception to allow higher-level systems an opportunity to likewise save critical data.
Examples
- Memory corruption detected
- Unrecoverable internal data integrity corruption error
- Unrecoverable out-of-memory or other hardware resource problems
Questions
- What is the mechanism by which other threads are notified of a lx::fatal_exception?
Errors
lx::core::error( const char* format, ... )
Reserved for potentially recoverable error where the application should save critical data, but otherwise shutdown as soon as possible. Will throw an lx::error_exception exception.
An application may catch and consume an lx::error_exception, but should do so only with the error condition is fully understood to be correctable.
Examples
- TBD
Warnings
lx::core::warn ( const char* format, ... )
Reserved for ignorable or locally recoverable conditions that indicate an inefficiency.
Examples
Log Messages
lx::core::log ( const char* subsystem, const char* format, ...)
Reserved for messages logged in production code noting significant events that will be useful in reproducing or analyzing the before of a customer application instantiation.
Examples
- Initialization & shutdown of a major subsystem
- Initialization & shutdown of a plug-in
- Any significant data save or check-pointing operation
Debug Messages
lx::core::debug ( const char* channelId, const char* format, ...)
Reserved for debug-only messages that produce verbose output for in-development code. Due to the intentional verbosity, the debug messages are each associated with a channelId. Each channel is disabled by default, with the intention that a developer would enable only the channel or channels within which he or she is debugging or developing.
Examples
- Minor events at too granular a level to belong as a
log()call - Basic statistics on the code being run
Suggestions
- How to use
debug()effectively is unfortunately difficult to generalize. It requires a careful balance of providing detailed information about the subsystem or code area, but not so much data as to drown-out the most poignant data. - A useful strategy is to use
debug()to display data that is difficult directlyassert()against. The programmer may be able to use to textual output of the debugging information to determine if a condition holds in a specific case where it could have been too difficult to assert() in all cases.