Можно ли уничтожить сопрограмму во время оценки выражения внутреннего ожидания? - PullRequest
4 голосов
/ 26 января 2020

Согласно стандарту сопрограмма должна быть уничтожена только тогда, когда она приостановлена ​​ [dcl.fct.def.coroutine]

Если для вызова вызывается сопрограмма, не приостановлено, программа имеет неопределенное поведение.

Во время вычисления выражения ожидания внутри сопрограммы A предположим, что эта последовательность событий соответствует [expr.await] /5.1:

  1. сопрограмма A приостановлена, поскольку готово к ожиданию неверно;
  2. до передачи контроля вызывающей функции сопрограммы A, сопрограмма B является возобновлено;
  3. после того, как B также приостановлено, управляющие потоки возвращаются к вызывающей программе сопрограммы A.

Может ли сопрограмма A быть уничтожена после возобновления сопрограммы B, но до ее приостановки?

Пример кода:

#include <coroutine>

using namespace std;

struct task
    {
    struct promise_type;

    using handle_type = coroutine_handle<promise_type>;

    struct promise_type
        {
        handle_type resumer = nullptr; 
        auto
        get_return_object(){
            return task{handle_type::from_promise(*this)};
            }

        auto 
        initial_suspend(){
            return suspend_always {};
            }

        auto 
        unhandled_exception(){}

        auto
        final_suspend(){
            return suspend_always{};
            }

        void 
        return_void() {}

        };


   handle_type handle;

   void await_resume(){
       handle.resume();
   }

   auto
   await_suspend(handle_type h){
       handle.promise().resumer = h;
       return handle;
   }
   auto
   await_ready(){
       return false;
   }

    };


int main(){

  task coroutine_B = [&coroutine_B]() ->task
            {
            coroutine_B.handle.promise().resumer.destroy();
            co_return;
            }();//coroutine B supended at initial suspend

  task coroutine_A = [&coroutine_B]() ->task 
            {
            co_await coroutine_B;//set coroutine_B resumer to coroutine_A handle
                                 //then resume coroutine_B.
            }();//coroutine A supended at initial suspend.

  coroutine_A.handle.resume();//execute co_await coroutine_B;
                              //is this UB?

}

Как видно здесь , код компилируется и, похоже, работает без проблем.

С другой стороны, это, по-видимому, эквивалентно версия здесь вылетает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...