Hook result

We now tell Outcome that for every instance of our localised result<T>, that on failure construction only, we want custom code to be run which increments the current slot in TLS storage and writes the current stack backtrace into it.


namespace error_code_extended
{
  // Specialise the result construction hook for our localised result
  // We hook any non-copy, non-move, non-inplace construction, capturing a stack backtrace
  // if the result is errored.
  template <class T, class U> inline void hook_result_construction(result<T> *res, U && /*unused*/) noexcept
  {
    if(res->has_error())
    {
      // Grab the next extended info slot in the TLS
      extended_error_info &eei = mythreadlocaldata().next();

      // Write the index just grabbed into the spare uint16_t
      OUTCOME_V2_NAMESPACE::hooks::set_spare_storage(res, mythreadlocaldata().current - 1);

      // Capture a backtrace into my claimed extended info slot in the TLS
      eei.items = ::backtrace(eei.backtrace.data(), eei.backtrace.size());
    }
  }
}
View this code on Github

The only non-obvious part above is the call to hooks::set_spare_storage() . Both result and outcome keep their internal state metadata in a uint32_t, half of which is not used by Outcome. As it can be very useful to keep a small unique number attached to any particular result or outcome instance, we permit user code to set those sixteen bits to anything they feel like. The corresponding function to retrieve those sixteen bits is hooks::spare_storage() .