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();
}
}
52
std::unique_lock<std::recursive_mutex> lk2(mtx2, std::defer_lock);
#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();
}
出力
バージョン
言語
- C++11
処理系
- Clang: ??
- GCC: 4.7.0 ✅
- ICC: ??
- Visual C++: 2012 ✅, 2013 ✅, 2015 ✅