私は継続、具体的にはコルーチンのライブラリを書いてきました。これは std::thread に似ています (協調的であることを除いて) - 各実行コンテキストは継続オブジェクトで表されます。
問題は、継続オブジェクトの破棄に関するものです。実行コンテキストが正常に終了していない間に継続オブジェクトの dtor が呼び出された場合、オブジェクトを破棄するコンテキストによって強制的に閉じられる必要があります。
このように、スタック フレーム内のすべての C++ オブジェクトは適切に破棄されません。これは誰にとっても快適な状況ではないかもしれません - そこで私は解決策を見つけることにしました.
最初は例外を使って以下のようにスタックフレームを巻き戻そうと思いました。(以下は欠陥のある疑似コードであることに注意してください。)
coroutine::~coroutine()
{
status = FORCED_EXIT;
switch_to(*this);
}
void coroutine::yield(coroutine& other_coroutine)
{
// switch to other context, halt until invocation by other context
switch_to(other_coroutine);
if (status_ != FORCED_EXIT) {
return; // resume
} else {
throw ContextClosingException;
}
}
void coroutine::entrypoint()
{
try {
entry_function_();
} catch(ContextClosingException& e) {
switch_to(caller_coroutine);
}
}
ただし、いくつかの重大な欠陥を発見しました。以下のように「例外を飲み込む」ユーザー コードは、協調スケジューリングの前提を完全に破ります。
try {
...
} catch(...) { // ContextClosingException
// do nothing, just swallow exception.
}
したがって、スタックの巻き戻しを呼び出す他の方法 (または、継続中のスタック オブジェクトを破棄する他の方法) を見つける必要があります。標準準拠の方法は良いでしょうが、継続の実装自体はプラットフォーム固有の API に依存しているため、移植性のない方法も受け入れられます。(私はwin32を使用しています)