我有以下的情況下(簡體):有沒有可能找到或創建沒有鎖定或提供未來?
/* Register objects living
and retrieve them on demand if the object is still alive on request.
The interface have to be concurrency-safe.
*/
class Registry
{
public:
void add(const std::shared_ptr<Thing>& thing)
{ m_index.emplace_back(thing);
std::shared_ptr<Thing> find(ThingId id)
{
auto find_it = m_index.id(id);
if(find_it != end(m_index))
{
// we can't remove the index safely (see http://software.intel.com/sites/products/documentation/doclib/tbb_sa/help/index.htm)
return find_it->second.lock(); // null if the object don't exist anymore
}
return nullptr;
}
private:
tbb::concurrent_unordered_map< ThingId, std::weak_ptr<Thing> > m_index;
};
// Concurrency safe too.
class Workspace
{
Registry m_registry;
std::unique_ptr<Thing> make_new_thing(ThingId id); // not important
public:
std::shared_ptr<Thing> find(ThingId id) { return m_registry.find(id); }
/* The goal here is to either retrieve the existing object,
or to create it.
*/
std::shared_ptr<Thing> find_or_create(ThingId id)
{
// HERE IS THE PROBLEM!!!
if(auto thing = m_registry.find(id))
return thing;
return make_new_thing();
}
};
// Concurrency-safe too.
class Editor
{
Workspace& m_workspace;
tbb::concurrent_unordered_set<std::shared_ptr<Thing>> m_things;
public:
void add_target(ThingId id)
{
m_things.push(m_workspace.find_or_create(id));
}
};
的背景是重要的,但讓我們專注於這一部分:
std::shared_ptr<Thing> find_or_create(ThingId id)
{
if(auto thing = m_registry.find(id))
return thing;
return make_new_thing();
}
這裏,如果同時呼叫是爲這個功能製作,同時呼叫到make_new_thing ()可能會發生,如果Thing不具有相同的id,則這是有效的,但如果不具有相同的id,則不會發生。 由於concurrent_unordered_map實現,我們無法從註冊表中刪除id,所以我們無法檢查是否正在創建對象。
這一切都表明,在這種情況下,需要同步機制。然而,如果我使用類似於工作隊列的東西,那麼我將不得不提供一個當前正在鎖定的未來,但即使使用future.then(),調用者可能會等待很長時間。
我想要的是避免鎖定(使用互斥鎖),如果可能的話,沒有未來(在這種情況下)。
你看到有沒有鎖定的方法嗎?
沒關係,我想我只能在調用find_or_create()時鎖定,而不是在其他情況下。 – Klaim
如果有更好的解決方案,我會放棄此操作。 – Klaim