この設計上の決定の根拠は、N2406に記載されています。
ブーストとは異なり、mutex には lock()、unlock() などのパブリック メンバー関数があります。これは、主要な目標の 1 つをサポートするために必要です: ユーザー定義の mutex は、標準定義のロックで使用できます。ユーザー定義のミューテックスを実装するためのインターフェイスがなければ、標準定義のロックがユーザー定義のミューテックスと通信する方法はありません。
これが書かれた時点では、boost::mutex は boost::scoped_lock でのみロックおよびロック解除できました。
これで、 を書くことができます。メンバとmy::mutex
を提供する限り、あなたは と同じくらい一流の市民です。あなたのクライアントは、何が何なのかわからなくても、 を使うのと同じくらい簡単に を使うことができます。lock()
unlock()
my::mutex
std::mutex
std::unique_lock<my::mutex>
std::unique_lock<std::mutex>
std::unique_lock
my::mutex
の動機付けとなる実際の例は、C++1y (y == 4 であることが望ましい)ドラフト標準my::mutex
で現在提案されているです。 にはメンバーがあり、排他モードのロックおよびロック解除用です。そして、クライアントが期待どおりに使用するときに相互作用します。std::shared_mutex
std::shared_mutex
lock()
unlock()
std::unique_lock
std::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_lock
unique_lock<my::mutex>
unique_lock<std::shared_mutex>
std::shared_lock<std::shared_mutex>
それはすべてうまくいきます。そしてすべては、合意された と のパブリック インターフェイスを除いて、とstd::unique_lock
の間に親密な関係がないためです。std::mutex
lock()
unlock()