トリプルロックを確認しましたか?
-
24-09-2019 - |
質問
であるように、その間に我々はダブルチェックロックを知っているが、C ++での仕事、少なくともないポータブルな方法でません。
私はちょうど私が私が地形レイトレーサのために使用することレイジー四分木で脆弱な実装を持って実現しました。だから、私は四重メモリ使用量と実装されたアルゴリズムの再オーダーの大部分たくないとして、まだ、安全な方法で遅延初期化を使用する方法を見つけることを試みます。
このトラバーサルは C ++の12ページのパターンに触発し、ダブルチェックの危険されますにロックが、それを行うにしようとは安くます:
(pseudo code!)
struct Foo {
bool childCreated[4];
Mutex mutex[4];
Foo child[4];
void traverse (...) {
...
if (!childCreated[c]) {
// get updated view
#pragma flush childCreated[c]
if (!childCreated[c]) {
ScopedLock sl (mutex[c]);
if (!childCreated[c]) {
create (c);
#pragma flush childCreated[c]
childCreated[c] = true;
}
}
}
}
}
これは#pragma flush
もコンパイラとプロセッサがそれらを横切って再注文操作が許可されないであろうハードシーケンス点として役立つであろうと想定される。
どの問題あなたが見ていますか?
の編集のバージョン2、(第3フラッシュを紹介)口座Vladsに答えを取るしようとしています:
(pseudo code!)
struct Foo {
bool childCreated[4];
Mutex mutex[4];
Foo child[4];
void traverse (...) {
...
if (!childCreated[c]) {
// get updated view
#pragma flush childCreated[c]
if (!childCreated[c]) {
ScopedLock sl (mutex[c]);
#pragma flush childCreated[c]
if (!childCreated[c]) {
create (c);
#pragma flush childCreated[c]
childCreated[c] = true;
}
}
}
}
}
の編集:私は基本的に作成する間にメモリバリアに頼って、有効性を確認するために、子供そのものではなく、原始的なフラグを使用していないので、のバージョン3、私は何とか、バージョン2には、このかなり同等のを見つけますそのフラグの子と書き込みます。
(pseudo code!)
struct Foo {
bool childCreated[4];
Mutex mutex[4];
Foo child[4];
void traverse (...) {
...
if (!childCreated[c]) {
ScopedLock sl (mutex[c]);
#pragma flush childCreated[c]
if (!childCreated[c]) {
create (c);
#pragma flush childCreated[c]
childCreated[c] = true;
}
}
}
}
解決
あなたのパターンが正しくないようです。最初#pragma flush
後まで、#1が実行するスレッド場合を考えてみましょう。コントロールが上になり、c
を作成し、スレッド#2、に切り替わりその後、制御はちょうど二#pragma flush
前に戻って取られます。今、最初のスレッドが起動し、新たに子を作成します。
編集:申し訳ありませんが、間違っている:ロックを取ることができません。
編集2:いいえ、まだ正しい、値がスレッド#1
にフラッシュされないことになるので、