4

私は継続、具体的にはコルーチンのライブラリを書いてきました。これは 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を使用しています)

4

1 に答える 1

1

C ++標準には、例外を除いてスタックの巻き戻しを許可するものはありません。コルーチン(またはコルーチンのサポート)は、C ++ 11以降に提案される可能性があります(Going Native会議で話し合われました)。

OS固有のC呼び出しを使用する必要があります(存在する場合、私はそうは思いません)が、ほとんどの場合、ASMを自分で使用しています。サンプルソリューションについては、boost.contextライブラリをご覧ください。

于 2012-02-15T04:11:24.520 に答える