我有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