c++协程生命期

<型名 T>构 承诺;<型名 T>[[未丢弃]]任务{
  用 承诺类型=承诺<T>;
  任务()=默认;
  ~任务()=默认;

  T&&取结果(){
    中 承诺->取结果();
  }

  任务(承诺<T>*承诺):承诺{承诺}{}:
  承诺<T>*承诺=空针;
};<型名 T>
构 承诺{
  ~承诺(){输出<<"d构造器承诺";}
  任务<T>取中对象()无异{{};}
  从不挂起 初始挂起()无异{{};}
  总是挂起 止挂起()无异{{};}<型名 U>
  空 返回值(U&&){
    结果.元 原位<1>(前向<U>());
  }

  空 未处理异常(){
    结果.元 原位<2>(当前异常());
  }

  极 是准备好()常 无异{中 结果.索引()!=0;}
  T&&取结果(){(结果.索引()==2)
      再抛异常(<2>(结果));
    中 移动(<1>(结果));
  }

  变量<单态,T,异常针>结果;
};

任务<>(){
  输出<<"福():将中";
  协中 42;
}

整 主(){
  动 t=();
  动 r=t.取结果();
  断定(t==42);0;
}

测试代码可输出协程返回值,但是协程泄漏了,没有析构承诺,释放协程帧时析构承诺,协程泄漏原因是什么?
因为终挂起返回的总是挂起不是永不挂起,因此不会自动释放协程帧,需要手动释放,代码中无手动释放协程帧的逻辑.那为什么不把它的返回类型设置为永不挂起呢?
如果设置为永不挂起,协程在终挂起后就自动释放了,这时,任务里面的承诺指针也失效了,外面再取协程返回值就会出错.
只要在任务的析构器中去释放协程帧就行了:

~任务(){
    协程句柄<承诺类型>::从承诺(*承诺).消灭();
  }//释放了

这个休息在协程挂起休息了1秒,然后恢复,代码从co_await后继续执行,所以这个休息的协程在await_ready()返回false的时候暂停,在await_suspend时恢复.

构 休息{
  极 准备好协()常 无异{
    中 时长==时长.();
  }
  空 挂起协(协程句柄<>协程){
    本线程::休息(时长);
    协程();
  }
  空 恢复协()常 无异{}

  时间::毫秒 时长;
};

任务<>休息(){
  输出<<"休息():将休息";
  协待 休息{时间::{1}};
  输出<<"休息():将中";
  协中 0;
}

整 主(){
  动 任务=休息();0;
}

如果注释掉await_suspend中恢复协程的代码coro()会怎么样?
休息co_await那一行代码之后的代码都不会执行,因为这个协程已挂起,没有谁去恢复它.然后就析构了这个任务协程帧.问题是可释放挂起协程吗?答案是.

posted @ 2022-03-28 13:13  zjh6  阅读(12)  评论(0)    收藏  举报  来源