我有concurrent_unordered_map
。我使用insert
函数(并且没有其他)尝试同时插入地图。但是,很多时候,这个函数在内部函数中崩溃很深。这里是一些代码:使用concurrent_unordered_map崩溃
class ModuleBase {
public:
virtual Wide::Parser::AST* GetAST() = 0;
virtual ~ModuleBase() {}
};
struct ModuleContents {
ModuleContents() {}
ModuleContents(ModuleContents&& other)
: access(other.access)
, base(std::move(other.base)) {}
Accessibility access;
std::unique_ptr<ModuleBase> base;
};
class Module : public ModuleBase {
public:
// Follows Single Static Assignment form. Once it's been written, do not write again.
Concurrency::samples::concurrent_unordered_map<Unicode::String, ModuleContents> contents;
Wide::Parser::AST* GetAST() { return AST; }
Wide::Parser::NamespaceAST* AST;
};
这是我用来实际插入到地图中的函数。有更多但它不会触及地图,只使用返回值insert
。
void CollateModule(Parser::NamespaceAST* module, Module& root, Accessibility access_level) {
// Build the new module, then try to insert it. If it comes back as existing, then we discard. Else, it was inserted and we can process.
Module* new_module = nullptr;
ModuleContents m;
{
if (module->dynamic) {
auto dyn_mod = MakeUnique<DynamicModule>();
dyn_mod->libname = module->libname->contents;
new_module = dyn_mod.get();
m.base = std::move(dyn_mod);
} else {
auto mod = MakeUnique<Module>();
new_module = mod.get();
m.base = std::move(mod);
}
new_module->AST = module;
m.access = access_level;
}
auto result = root.contents.insert(std::make_pair(module->name->name, std::move(m)));
这是根函数。它是从不同输入上的许多线程并行调用的,但具有相同的root
。
void Collater::Context::operator()(Wide::Parser::NamespaceAST* input, Module& root) {
std::for_each(input->contents.begin(), input->contents.end(), [&](Wide::Parser::AST* ptr) {
if (auto mod_ptr = dynamic_cast<Wide::Parser::NamespaceAST*>(ptr)) {
CollateModule(mod_ptr, root, Accessibility::Public);
}
});
}
我不完全确定wtf正在发生。我有一个共享状态,我只能以原子方式访问它,所以为什么我的代码会死?
编辑:这实际上完全是我自己的错。崩溃发生在insert
行,我认为这是问题 - 但它不是。它与并发无关。我测试的result
返回值的走错了路周围 - 即true
为value existed
,false
为value did not exist
,而标准定义为true
insertion succeeded
- 即value did not exist
。这大大地破坏了内存管理,导致了崩溃 - 尽管它究竟是如何导致unordered_map
代码崩溃的,我不知道。一旦我插入正确的否定,它完美无缺地工作。这是因为我没有在跳过并发fence之前正确测试单线程版本。
关于缺少const正确性的观点是一个很好的观点。但是,只有'concurrent_unordered_map'实际上是* mutable *。 – Puppy 2011-12-28 21:08:58
为什么不添加所有你认为是真的const修饰符,看看它是否编译。另外,确保你没有任何对这些const对象的可变引用。 – 2011-12-30 03:51:38
我这样做是为了真正验证我的假设,并且它是有效的。但是,我确实发现了实际问题。查看我的编辑解决方案。 – Puppy 2011-12-30 20:39:01