Keeping state - Boost.Outcome documentation

# Keeping state

The first thing we are going to need is somewhere to store the stack backtrace. We could take the easier route and simply store it into an allocated block and keep the pointer as a custom payload in a `result<T, std::pair<error_code, std::unique_ptr<stack_backtrace>>>` (see previous section on Custom payloads). But let us assume that we care so deeply about bounded execution times that ever calling `malloc` is unacceptable.

We therefore are going to need some completely static and trivially typed storage perhaps kept per-thread to avoid the need to keep mutexes.

    /* Outcome's hook mechanism works vis ADL, so we will need a custom namespace
    to ensure the hooks apply only to the types declared in this namespace only
    */
    namespace error_code_extended
    {
      // The extra error information we will keep
      struct extended_error_info
      {
        std::array<void *, 16> backtrace;  // The backtrace
        size_t items;                      // Items in backtrace array which are valid
      };
      struct mythreadlocaldata_t
      {
        // Keep 16 slots of extended error info as a ringbuffer
        extended_error_info slots[16];
        // The current oldest slot
        uint16_t current{0};

        // Return the oldest slot
        extended_error_info &next() { return slots[(current++) % 16]; }

        // Retrieve a previously stored slot, detecting if it is stale
        extended_error_info *get(uint16_t idx)
        {
          // If the idx is stale, return not found
          if(idx - current >= 16)
          {
            return nullptr;
          }
          return slots + (idx % 16);
        }
      };

      // Meyers' singleton returning a thread local data structure for this thread
      inline mythreadlocaldata_t &mythreadlocaldata()
      {
        static thread_local mythreadlocaldata_t v;
        return v;
      }
    }

View this code on Github

The extended error info is kept in a sixteen item long, thread local, ring buffer. We continuously increment the current index pointer which is a 16 bit value which will wrap after 65,535. This lets us detect an attempt to access recycled storage, and thus return item-not-found instead of the wrong extended error info.

Last revised: February 08, 2019 at 22:18:08 UTC