fiber
Loading...
Searching...
No Matches
Exceptions and Assertions

fiber uses fiber::Exception, which is the base class for all exceptions in Fiber. This design choice has been made to allow multiple different raw-strings to be passed to exceptions to generate error messages without heap memory allocation.

Philosophy

Exceptions in Fiber are used only to signal programmer-caused setup errors, such as invalid arguments, null pointers, or memory exhaustion. They are never used for runtime control flow, task switching, or peripheral errors during ISR.

This design ensures deterministic behavior and simplifies safety analysis.

Further no exceptions allocate memory or use the heap.

Customisation

Assertion Levels

Assertions will - per default - throw exceptions if they fail.

Assertions can be customised based on the expected performance hit. For that fiber suports 4 different levels. The user can just add the corresponding define option their compilation.

  • FIBER_DISABLE_ASSERTIONS: Disables all assertions
  • FIBER_ASSERTION_LEVEL_CRITICAL: (default) Tests that will not use more than ~5% of the performance and are difficult to reason about, like memory allocation errors.
  • FIBER_ASSERTION_LEVEL_O1: Tests that will complete in O[1] time but use more than 5% of performance. E.g: range bound checks at every access of a container.
  • FIBER_ASSERTION_LEVEL_FULL: Tests that will use more than O[1] time. E.g.: checking if the list is sorted befor doing a binary search. Basically turns your project into a test suit.

Turning Assertions into Optimisations

You can turn unused assertions into optimisations. If your code is tested and you know for a fact that FIBER_ASSERTION_LEVEL_O1 assertions will not fail, then you can switch to FIBER_ASSERTION_LEVEL_CRITICAL and also define:

FIBER_ASSERTS_AS_ASSUME

This will turn all unused assertions (higher layer or all if disabled) into assume statements for the compiler that can be used to further optimize the code.

But Be Careful!

If the assertion is not actually true at runtime, this may result in undefined behavior

How to use Assertion Levels

  • FIBER_ASSERT_CRITICAL(condition == true): Use this for an assert that uses less than ~5% of the time compared to the rest of the function.
  • FIBER_ASSERT_O1(condition == true): Use this if an assert can be done in O[1] time but would take a considerable amount of time compared to the rest of the function. (50% performance hit)
  • FIBER_ASSERT_INTERNAL(condition == true): Internal assertions for error states that should be fully handled by the library. The user should not be able to trigger them.

    note that if exceptions are disabled the assertions will trap execution*

Redirect assertions from exceptions to callbacks

If

you can set the following definition:

FIBER_USE_EXCEPTION_CALLBACKS

which will make all assertions call the function-pointer

fiber::exception_callback(const Exception& e)

instead of throwing the exception. The user can overload this function pointer with his own implementation. The default implementation of exception_callback will print the exception to fiber::cerr and then trapps in a while loop.

Disable all checks and assertions

If you want no error checking and are 100% sure that nothing will go wrong and you need that extra bit of performance, then you can define the following option in your compilation to disable and remove all exceptions

Defining Custom Exceptions

You can define your own exception like this:

class MyException : public Exception {
public:
constexpr MyException(...) : ... {...}
void print(OStream& stream) override {stream << "[MyException] " << ... << fiber::endl;}
};
void endl(OStream &stream)
Writes a new line character to the stream followed by a call to OStream::flush()
Definition OStream.hpp:198
See also
fiber::Exception
fiber::AssertionFailure
fiber::AssertionFailureCritical
fiber::AssertionFailureO1
fiber::AssertionFailureFull