2009-03-19 23 views
4

私はC++で32のマルチスレッドを勝つために取り組んでいます。 シナリオ: 私は、複数のスレッドで使用される関数を持っています。 これはクリティカルセクション(またはリソースをロックできる任意の種類のコンストラクト)として機能します。 クリティカルセクションで例外がスローされます。 この時点で、私は例外キャッチブロックでリソースのロックを解除する必要があります。クリティカルセクションでスローされた例外をキャッチする方法は?

他にもこれができますか?つまり、catchブロックでロックを解除することを忘れたくないとしましょう。このエラーの起こりやすいシナリオを回避するためにこの問題を処理する一般的な方法はありますか?

答えて

16

クリティカルセクションを取得してオブジェクトを解放する動作をカプセル化して、オブジェクトを構築することでCSを取得し、オブジェクトを破棄して解放します。

struct CSHolder { 
    explicit CSHolder(CRITICAL_SECTION& cs): lock(cs) { 
     ::EnterCriticalSection(&lock); 
    } 
    ~CSHolder() { ::LeaveCriticalSection(&lock); } 
    CRITICAL_SECTION& lock; 
}; 


CRITICAL_SECTION gLock; 
void foo() { 
    CSHolder lockIt(gLock); 
    // lock is held until lockIt is destroyed 
} 

RAII - リソース獲得は初期化です。現代のC++の非常に一般的なイディオムです。

2

クリティカルセクションをコンストラクタパラメータとして使用するブラケットクラスを記述します。コンストラクタのEnterCriticalSectionとデストラクタのLeaveCriticalSectionを呼び出します。スタックアンワインディングは、C++例外がスローされた場合、残りの処理を行います。

+0

これはboost :: mutex :: lockオブジェクトの動作です。 – greyfade

+0

scoped_lockではなく – greyfade

2

MFCを使用できる場合は、CSingleLockを使用してこれを行うことができます。

void f() 
{ 
    try 
    { 
    CSingleLock lock(&m_criticalSection, TRUE); 

    } 
    catch(/*some exception*/) 
} 

ロックはデストラクタのクリティカルセクションのロックを解除します。 lockは、例外がスローされたときにローカルオブジェクトであるため、スタックのロックが解除され、ロックオブジェクトデストラクタが実行され、クリティカルセクションのロックが解除されます。

3

既存のフレームワークを使用している場合は、これを実行できるRAIIコンテナクラスが既に用意されている可能性があります。 MFCを使用している場合は、CSingleLockをご覧ください。ブーストを使用している場合はscoped_lockです。

誰もが自分のロールを持っていなければならないと思っている(あるいはそうしなければならないと思う)のは残念です。

+0

私は同意します。人々が依然としてboost :: mutexまたは類似のものを使用するのではなく、CRITICAL_SECTIONを直接使用していることは残念です。たぶん正解は、ネイティブCSの上にブーストロック可能な概念を実装するアダプタを書くことです..うーん... –