| Doc. no. | P0664R3 | 
| Revises | P0664R2 | 
| Date: | Revised 2018-05-05 | 
| Project: | Programming Language C++ | 
| Reference: | ISO/IEC TS 22277, C++ Extensions for Coroutines | 
| Audience: | EWG, CWG, LEWG | 
| Reply to: | Gor Nishanov <gorn@microsoft.com> | 
All proposed resolutions wording is relative to N4736.
Previous issue list is P0664R1.
Section: 11.4.4 [dcl.fct.def.coroutine] Status: Active Submitter: Gor Nishanov Opened: 2018-03-08 Last modified: 2018-05-05
Issue:
    Common use of the initial_suspend point in asynchronous coroutines is to suspend the coroutine
    during the initial invocation and post a request to resume the coroutine by a different execution agent. 
    If an execution agent at a later point cannot resume the coroutine, for example, because it is being shutdown, 
    an error will be reported to a coroutine by resuming the coroutine
    and subsequently throwing an exception from await_resume.
    Currently, the invocation of initial_suspend is specified in [dcl.fct.def.coroutine] as:
  {
    P p;
    co_await p.initial_suspend(); // initial suspend point
    try { F } catch(...) { p.unhandled_exception(); }
  final_suspend:
    co_await p.final_suspend(); // final suspend point
  }  
  As specified, an exception from await_resume of initial_suspend will be thrown
  outside of the try-catch and will not be captured by p.unhandled_exception() and
  whoever waits for eventual completion of a coroutine will never learn about its completion.
  This is a specification defect. The intent is to capture an exception thrown by await_resume of
  an awaitable returned by initial_suspend within the try-catch enclosing of 
  the user authored body F.
The correct behavior has been implemented in MSVC staring with version 2015 and in clang trunk.
Proposed resolution:
Add underlying text to paragraph 11.4.4/3 as follows:
      
          {
            P p;
            co_await p.initial_suspend(); // initial suspend point
            try {
              F 
            } catch(...) { p.unhandled_exception(); }
          final_suspend:
            co_await p.final_suspend(); // final suspend point
          }  
        
        except that any exception thrown after the initial suspend point 
          and before the flow of execution reaches F also results in 
          entering the handler of the try-block and,
          where an object denoted as p is the promise object of the coroutine 
          and its type P is the promise type of the coroutine, ...
        
Section: 11.4.4 [dcl.fct.def.coroutine] Status: Active Submitter: Eric Niebler Opened: 2018-03-10 Last modified: 2018-05-05
Issue:
Currently, an unhandled exception can never escape the user-authored body of the coroutine with triggering undefined behavior.
        
            {
              P p;
              co_await p.initial_suspend(); // initial suspend point
              try {
                F  // user authored body
              } catch(...) { p.unhandled_exception(); }
            final_suspend:
              co_await p.final_suspend(); // final suspend point
            }  
          
    
    
  
  An exception from F is captured by the try-catch and
  a customization point unhandled_exception is called,
  where, typically, an exception_ptr is created and propagated to
  the consumer awaiting on async task, or, in case of a generator,
  will be delivered to the user
  when they dereference the iterator.
  
  Though the current behavior is perfectly reasonable for asynchronous
  scenarios, it is sub-optimal  
  for synchronous generators. Capturing an exception, storing it in an 
  exception_ptr and then rethrowing the exception during,
  say, iterator's operator* is a needless work if the desired
  behavior is to let the exception propagate to the caller
  whenever it asks for the next value.
   
  
Background information:
  When a coroutine is first invoked, any exception thrown before entering
  the user-authored body (for example allocation failure, promise constructor failure,
  failure to copy parameters, etc) propagates into the caller as with any 
  normal function call. However, when the coroutine suspends and subsequently resumed, 
  if an exception is thrown by an evaluation of 
  p.unhandled_exception() or 
  an evaluation of co_await p.final_suspend()
  the behavior is undefined. Note that a coroutine can be only resumed or destroyed
  when suspended at a particular suspend point. An exception leaving the coroutine
  at arbitrary point of the execution leaves the coroutine in the undefined state.
  
The proposed resolution is to eliminate the undefined behavior in the following manner:
p.unhandled_exception()
        and, in that case, consider the coroutine to be at the final suspend point. Reminder: when
        a coroutine is at the final suspend point, the coroutine can only be
        destroyed and a call to member function done() of the 
        coroutine handle associated with that coroutine returns true.
      co_await p.final_suspend()
        by stating that final_suspend member function of
        the coroutine promise and await_resume, await_ready,
        and await_suspend members of the object returned from 
        final_suspend shall have non-throwing exception specification.
      
    This resolution allows generator implementations to define unhandled_exception
    as follows:
    
  void unhandled_exception() { throw; } 
    With this implementation, if a user of the generator pulls the next value,
    and during computation of the next value an exception will occur in the 
    user authored body it will be propagate back to the user and the coroutine
    will be put into a final suspend state and ready to be destroyed when
    generator destructors is run.
  
  Proposed Wording:
In subclause 11.4.4, add two new paragraph after paragraph 11.
p.unhandled_exception()
      exits via an exception, the coroutine is considered suspended at the final suspend point.
     final_suspend, 
      await_resume, await_ready,
      await_suspend and operator co_await (if any)
      used in evaluation of co_await p.final_suspend() shall 
      have non-throwing exception specification.
await_suspend Section: 8.3.8 [expr.await] Status: Active Submitter: Gor Nishanov Opened: 2018-03-10 Last modified: 2018-03-10
Issue:
  One of the implementation strategies for coroutines is to chop
  original function into as many functions (parts) as there are suspend points.
  In that case, it is possible for a compiler create a unique
  per suspend per function coroutine_handle which 
  resume
  and destroy members can be direct calls to corresponding
  parts of the function.
Though no compiler is doing it now, we can allow implementors
  to experiment with this approach by relaxing the requirement
  on the coroutine_handle passed 
  to await_suspend.
Proposed wording:
Add underlined text to 8.3.8/3.5:(3.5) — h is an object of type convertible to std::experimental::coroutine_handle<P> referring to the enclosing coroutine.
static and thread_local local variables ill-formedSection: 8.3.8/2 [expr.await] Status: Active Submitter: Richard Smith Opened: 2018-03-25 Last modified: 2018-03-25
Proposed wording:
Add underlined text to 8.3.8/2:An await-expression shall appear only in a potentially-evaluated expression within the compound-statement of a function-body outside of a handler (Clause 18). In a declaration-statement or in the simple-declaration (if any) of a for-init-statement, an await-expression shall appear only in an initializer of that declaration-statement or simple-declaration unless it is used to initialize a block-scope variable with static or thread storage duration.
Section: 11.4.4 [dcl.fct.def.coroutine] Status: Active Submitter: Gor Nishanov Opened: 2018-03-10 Last modified: 2018-03-10
Proposed wording:
[const 
  on coroutine_handle::resume() makes lambdas verboseSection: 21.11.2 [coroutine.handle] Status: Active Submitter: (Many) Opened: 2018-03-08 Last modified: 2018-03-08
Issue:
    During LEWG/LWG review of Coroutine TS, const on coroutine_handle::resume()
    was removed. While it does follow LEWG/LWG convention of only putting coroutine_handle more verbose. 
  used to write: [h]{ h.resume();}
  now have to write: [h] () mutable { h.resume();}
Customers complained and I have recorded this as an issue.
task and generator
types are available Section: 10.1.7.4 [coroutine.handle] Status: Not ready Submitter: Gor Nishanov Opened: 2018-05-05 Last modified: 2018-05-05
Issue:
We stripped out automatic return type deduction for coroutines from N4499 in 2015. Put back the wording to do it once the appropriate types are available in the standard library.