この設計上の決定の根拠は、N2406に記載されています。
ブーストとは異なり、mutex には lock()、unlock() などのパブリック メンバー関数があります。これは、主要な目標の 1 つをサポートするために必要です: ユーザー定義の mutex は、標準定義のロックで使用できます。ユーザー定義のミューテックスを実装するためのインターフェイスがなければ、標準定義のロックがユーザー定義のミューテックスと通信する方法はありません。
これが書かれた時点では、boost::mutex は boost::scoped_lock でのみロックおよびロック解除できました。
これで、 を書くことができます。メンバとmy::mutexを提供する限り、あなたは と同じくらい一流の市民です。あなたのクライアントは、何が何なのかわからなくても、 を使うのと同じくらい簡単に を使うことができます。lock()unlock()my::mutexstd::mutexstd::unique_lock<my::mutex>std::unique_lock<std::mutex>std::unique_lockmy::mutex
の動機付けとなる実際の例は、C++1y (y == 4 であることが望ましい)ドラフト標準my::mutexで現在提案されているです。 にはメンバーがあり、排他モードのロックおよびロック解除用です。そして、クライアントが期待どおりに使用するときに相互作用します。std::shared_mutexstd::shared_mutexlock()unlock()std::unique_lockstd::unique_lock<std::shared_mutex>
そしてshared_mutex、この汎用インターフェイスを利用できる他の唯一の動機ミューテックスであると思われるかもしれない場合に備えて、別の実際の例を次に示します: :-)
template <class L0, class L1>
void
lock(L0& l0, L1& l1)
{
while (true)
{
{
unique_lock<L0> u0(l0);
if (l1.try_lock())
{
u0.release();
break;
}
}
this_thread::yield();
{
unique_lock<L1> u1(l1);
if (l0.try_lock())
{
u1.release();
break;
}
}
this_thread::yield();
}
}
これは、デッドロックの危険なしに、2 つの BasicLockables を同時に (例外的に安全な方法で) ロックする方法の基本的なコードです。反対の多くの批判にもかかわらず、このコードは非常に 効率的です。
上記のコードの行に注意してください。
unique_lock<L0> u0(l0);
このアルゴリズムでは、型が何であるかはわかりませんL0。lock()しかし、それがサポートしている限りunlock()(もちろんtry_lock()そうです)、すべてがクールです。 、おそらくまたはさらに、またはおそらくさらにL0の別のインスタンス化でさえあるかもしれません。unique_lockunique_lock<my::mutex>unique_lock<std::shared_mutex>std::shared_lock<std::shared_mutex>
それはすべてうまくいきます。そしてすべては、合意された と のパブリック インターフェイスを除いて、とstd::unique_lockの間に親密な関係がないためです。std::mutexlock()unlock()