最終更新日時:
が更新

履歴 編集

function template
<mutex>

std::try_lock(C++11)

namespace std {
  template <class L1, class L2, class... L3>
  int try_lock(L1&, L2&, L3&...);
}

概要

複数のミューテックスオブジェクトに対してtry_lock操作を行う

要件

テンプレートパラメータの型がlock()unlock()try_lock()メンバ関数をサポートしていること

効果

各ミューテックスオブジェクトに、引数の順にtry_lock()メンバ関数を呼び出す。

いずれかのtry_lock()falseを返すか、もしくは例外を送出した場合、以降のtry_lock()呼び出しを行わず、それ以前にロック取得したミューテックスオブジェクトに対してunlock()メンバ関数を呼び出す。

戻り値

全てのミューテックスオブジェクトへのtry_lock()が成功した場合、-1を返す。

いずれかのtry_lock()が失敗して終了した場合、失敗した最初のミューテックスオブジェクトへの0から始まるインデックスを返す。

#include <cassert>
#include <mutex>

int main()
{
  std::mutex mtx1;
  std::recursive_mutex mtx2;

  // 複数のミューテックスオブジェクトに対してtry_lock()を呼び出す
  {
    int result = std::try_lock(mtx1, mtx2);

    assert(result == -1); // 全てのtry_lock()呼び出しが成功

    mtx1.unlock();
    mtx2.unlock();
  }

  // unique_lockに対してtry_lock()を呼び出す
  {
    std::unique_lock<std::mutex> lk1(mtx1, std::defer_lock);
    std::unique_lock<std::recursive_mutex> lk2(mtx2, std::defer_lock);

    int result = std::try_lock(lk1, lk2);

    assert(result == -1); // 全てのtry_lock()呼び出しが成功
  }

  // 一部のtry_lock()が失敗する場合
  {
    // mtx2をロックしておく。
    std::lock_guard<std::recursive_mutex> lk2_main_thread(mtx2);

    std::thread th([&]
    {
      std::unique_lock<std::mutex> lk1(mtx1, std::defer_lock);
      std::unique_lock<std::recursive_mutex> lk2(mtx2, std::defer_lock);

      // 他のスレッドでmtx2をロックしているため、lk2のロックに失敗する。
      int result = std::try_lock(lk1, lk2);

      // lk2が失敗したので第2引数を示す1が返る(0始まり)
      assert(result == 1);

      // lk2が失敗したので、std::try_lock()内でlk2より前にtry_lock()が
      // 成功した全てのミューテックスオブジェクトがunlock()される
      assert(!lk1.owns_lock());
    });
    th.join();
  }
}

出力

バージョン

言語

  • C++11

処理系

参照