TooManyCooks icon indicating copy to clipboard operation
TooManyCooks copied to clipboard

`result_share()` / `result_ref()` awaitable customizations

Open tzcnt opened this issue 9 months ago • 0 comments

These customizations should be applicable to any awaitable. They can be exposed as fluent members on known types for convenience, but a free function wrapper should also be available to use with external types.

result_share() takes an awaitable returning T, and transforms it into an awaitable returning shared_ptr<T> that can be awaited any number of times by any number of tasks. This is accomplished by:

  • creates a shared_ptr<T>
  • creates a shared_ptr<control block>
  • rebinds the awaitable's completion customizer to the control block. If the awaitable is unknown, this must be done by a task wrapper.
  • rebinds the awaitable's result pointer to the shared T. If the awaitable is unknown, this must be done by moving the data out of the task wrapper, into the shared_ptr.

// TODO: result_ref()


Support for non-default-constructible types should be implemented using std::optional.

The control block and T are allocated separately so that the control block can be destroyed after the result is ready. This assumes that the result's lifetime should long outlive the control block's lifetime, and thus it is desired to save space by freeing the control block. If this isn't the case, perhaps a template parameter could be exposed that would allow the control block to be combined with the T. However, then the return type is shared_ptr<control block with T> and that type needs to expose operator T&.

tzcnt avatar Apr 09 '25 15:04 tzcnt