2012-02-15 8 views
4

私は継続的なコルーチンのライブラリを書いています。これはstd :: threadと似ています(ただし、協調的です)。各実行コンテキストは、継続オブジェクトで表されます。C++でスタックフレームを全面的に巻き戻す方法はありますか? (例外を除いて)

問題は継続オブジェクトの破棄です。実行コンテキストが正常に終了していない間に継続オブジェクトの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); 
    } 
} 

しかし、私はいくつかの重大な欠陥を発見しました。以下のように「例外を取り除く」というユーザコードは、協調スケジューリングの前提を完全に破ります。

だから、スタックアンワインド(または他の方法でスタック内のスタックオブジェクトを破壊する)を呼び出すには、別の方法を見つける必要があります。標準の準拠方法はいいですが、継続実装自体はプラットフォーム固有のAPIに依存しているため、移植性のない方法でも問題ありません。 (私はwin32を使用しています)

+1

Windowsで協調スケジューリングが必要な場合は、[Win32ファイバ](http://msdn.microsoft.com/en-us/library/windows/desktop/ms682661.aspx)を使用してください。 –

+0

AndréCaron //スケジューリング自体の実装に問題はありません。質問の私の意図は文脈破壊に焦点を当てている。 – summerlight

+0

あなた自身のスケジューリングを実装していない場合、これは起こりますか? –

答えて

1

例外を除いてスタックの巻き戻しを許可するものはありません。コルーチン(またはコルーチンのサポート)はC++ 11以降で提案されるかもしれません(Going Nativeカンファレンスで話しました)。

OS固有のCコールを使用する必要があります(存在する場合はそうだと思いますが、そうは思わない)が、おそらくASMを使用している可能性があります。サンプル・ソリューションのためのboost.contextライブラリーを見ているかもしれません。

+0

あなたは 'ucontext'関数(' getcontext'/'setcontext'/etc)を見ることができます。 – Hugh