Linuxコンポーネントパッケージ(四)RAII技術を用いてMutexLock自動化ロック解除を実現

2106 ワード

私たちはこのコードを一度も書いたことがありません.
{
    mutex_.lock();
    //XXX
    if(....)
        return;

    //XXX
    mutex_.unlock();
}

明らかに、このコードではロックを解除するのを忘れています.このような状況をどのように防止するかは、スマートポインタと同じ戦略を採用し、ロックとロック解除のプロセスを1つのオブジェクトにカプセル化します.
[オブジェクトライフサイクル](Object Lifespan)が[ロック期間](Lock Period)に等しいことを確認します.
コードは次のとおりです.
class MutexLockGuard : NonCopyable
{
public:
    MutexLockGuard(MutexLock &mutex) :mutex_(mutex)
    { mutex_.lock(); }
    ~MutexLockGuard()
    { mutex_.unlock(); }
private:
    MutexLock &mutex_;
};

このようなリソース取得をコンストラクション関数、リソース解放をコンストラクション関数に入れる方法は、C++のRAI技術であり、「リソース取得は初期化」である.C++のスタックオブジェクトを巧みに解析するので、リソースは必ず解放されます.
このクラスは私たちが優雅なコードを書くのに、メリットは明らかです.例えば、
size_t Buffer::size() const
{
    mutex_.lock();
    int ret = queue_.size();
    mutex_.unlock();
    return queue_.size();
}

このコードは本当に美しいとは言えませんが、MutexLockGuardがあれば、私たちは書くことができます.
size_t Buffer::size() const
{
    MutexLockGuard lock(mutex_);
    return queue_.size();
}

コードの美観性が大幅に向上した.
もちろん、次のような使い方が間違っています.
size_t Buffer::size() const
{
    MutexLockGuard(mutex_);
    return queue_.size();
}

このコードのロック期間はその行に限られています.誤った使用を防ぐために、マクロを追加します.
#define MutexLockGuard(m) "Error MutexLockGuard"

これにより、エラーが使用されると、コンパイルエラーが発生し、問題が早期に発見されます.