我刚刚意识到我在一个懒惰的四叉树中有一个脆弱的实现,我将它用于地形光线跟踪器。因此,我试图找到一种方法,仍然以安全的方式使用延迟初始化,因为我不想将内存使用率提高四倍,并重新排序大部分已实现的算法。
此遍历的灵感来源于第12页的模式
C++ and the Perils of Double-Checked Locking
,但尝试更便宜:
(pseudo code!)
struct Foo {
bool childCreated[4];
Mutex mutex[4];
Foo child[4];
void traverse (...) {
...
if (!childCreated[c]) {
#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
也将作为一个硬序列点,编译器和处理器将不被允许跨它们重新排序操作。
编辑:
(pseudo code!)
struct Foo {
bool childCreated[4];
Mutex mutex[4];
Foo child[4];
void traverse (...) {
...
if (!childCreated[c]) {
#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;
}
}
}
}