ぷろみん

プログラミング的な内容を扱ってます

C++のローカルスコープとオブジェクト寿命

モチベーション

一定区間の開始、終了関数やフラグ変数の問題を改善します。

クリティカルセクション

英語wikipedia
http://en.wikipedia.org/wiki/Critical_section

pthread_mutex_lock( &cs_mutex );
// マルチスレッド処理
pthread_mutex_unlock( &cs_mutex );

マルチスレッドの排他制御の基本はこの様に関数で挟む形で実現されます。

しかし、C++11のthreadでは

cpprefjp
https://sites.google.com/site/cpprefjp/reference/mutex/mutex

std::lock_guard<std::mutex> lock(mtx_);

という様にロックするオブジェクトとして表現されます。

開始と終了で挟む形の方が直感的で分かりやすいし、2行を1行にするためだけに新しいクラスを作成するのは良いと感じないかもしれません。

スコープ

実用的な場面を想定し、Balkingパターンを例として考えてみます。関数思考で考えると以下の様になります。

pthread_mutex_lock( &cs_mutex );
if( is_busy_ ) {
    pthread_mutex_unlock( &cs_mutex );
    return;
}
is_busy_ = true;
pthread_mutex_unlock( &cs_mutex );
    
Execute();
is_busy_ = false;

直感的に感じられた開始と終了で挟む形が急に見辛く感じられます。しかもreturnの直前のunlock等はいかにも忘れそうです。

次はオブジェクト思考の例です。

{
    std::lock_guard<std::mutex> lock(mtx_);
    if( is_busy_ ) {
        return;
    }
    is_busy_ = true;
}
// バインドした変数をスコープを抜けたらfalseにするオブジェクト
FalseObject local( &is_busy_ );
Execute();

途中でのreturnによる問題は解決しました。
スコープ制御の為の{ }が出てきてしまう問題は機会があれば考えてみたいと思います。