Doc. no. | P0914r0 |
Date: | 2018-02-08 at 14:25:00 UTC |
Reference: | ISO/IEC TS 22277, C++ Extensions for Coroutines |
Audience: | EWG |
Reply to: | Gor Nishanov <gorn@microsoft.com> |
Users of C++ coroutines have long been requesting an ability to access coroutine parameters
in the constructor of the coroutine promise. Current workaround is to override
operator new
of the coroutine promise that does allow observing of
coroutine parameters, then extract the value of the desired parameter and store it in
a thread_local
variable and later extract the value
from the thread_local
in the coroutine promise default constructor and
store the value in the coroutine promise.
The workaround used is not reliable as compiler is allowed to elide heap allocation for the coroutine
state and elide invocation of operator new
. Coroutines need direct and reliable way of
expressing the desired behavior.
Suggestion is to give a coroutine promise an ability to look at the coroutine parameters.
Before:
struct my_promise_type { static thread_local cancellation_token saved_tok; cancellation_token tok; template <typename... Whatever> void* operator new(size_t sz, cancellation_token tok, Whatever const&...) { // BROKEN: May not get called if heap allocation is elided. saved_tok = tok; return ::operator new(sz); } my_promise_type() : tok(saved_tok) {} ... };
After:
struct my_promise_type { cancellation_token tok; template <typename... Whatever> my_promise_type(cancellation_token tok, Whatever const&) : tok(tok) {} ... };
[Proposed wording is relative to N4680 (ISO/IEC TS 22277)].
Modify paragraph 8.4.4/3 as follows:
{ P p promise-constructor-argumentsopt; co_await p.initial_suspend(); // initial suspend point try { F } catch(...) { p.unhandled_exception(); } final_suspend: co_await p.final_suspend(); // final suspend point }where an object denoted as p is the promise object of the coroutine,andits type P is the promise type of the coroutine, and promise-constructor-argumentsopt is determined as follows: Overload resolution is performed on a promise constructor call created by assembling an argument list with lvalues p1 ... pn. If matching constructor is found, then promise-constructor-argumentsopt is(p1 ... pn)
, otherwise promise-constructor-argumentsopt is nothing.
Add underlined text to 8.4.4/11:
When a coroutine is invoked, a copy is created for each coroutine parameter. Each such copy is an object with automatic storage duration that is direct-initialized from an lvalue referring to 11 the corresponding parameter if the parameter is an lvalue reference, and from an xvalue referring to it otherwise. A reference to a parameter in the function-body of the coroutine and in the call to coroutine promise constructor is replaced by a reference to its copy.