【发布时间】:2015-05-26 21:43:49
【问题描述】:
我有可以使用以下模板访问的类集合:
template <typename T> using RegistryMap = std::unordered_map <std::string, T *>;
template <typename T> class Registry {
static RegistryMap<T> registry;
public:
static T* get(const std::string& name) {
auto it = registry.find(name);
return it == registry.end() ? nullptr : it->second;
}
static const RegistryMap<T>& getAll() {
return registry;
}
static bool add(const std::string &name, T *object) {
T* &store = registry[name];
if (store)
return false;
else {
store = object;
return true;
}
}
static bool remove(const std::string &name) {
auto it = registry.find(name);
if (it == registry.end())
return false
else {
registry.erase(it);
return true;
}
}
};
此注册表中的许多类都定义了一个名为 run 的方法,线程线程将调用该方法的紧密循环。发生这种情况时,其他线程可能会使用上述方法从地图中添加/删除元素。
void workerThread() {
examples = Registry<ExampleClass>::getAll();
auto it = examples.begin();
while (true) {
if (it != examples.end())
it++->second->run();
else
it = examples.begin();
}
}
有没有办法让这个模板线程安全?我可以向 Registry 模板类添加一个静态锁,并在 add 或 remove 方法中获取它。但是我该如何处理紧环线呢?特别是在注册表变得非常大的情况下。如有必要,可以替换 unordered_map 并损失线性查找时间。
【问题讨论】:
-
为什么不简单地使用循环链表呢?这样你根本不需要锁定,只需要确保你以正确的顺序进行插入/删除......
-
@Amit 链表在某些情况下可能是完美的,但它不允许 O(1) (或接近它)访问某些命名条目。据推测,OP 想要这样的东西。
-
@AmiTavory - 引用:如有必要,可以替换 unordered_map 并失去线性查找时间。不仅如此,如果 O(1) 很重要,则可以使用映射将键链接到列表中的链接以便直接访问。
-
@Amit 你是对的 - 错过了。 OP 有可能(或不可能)更愿意 保留 O(1) 访问权限,尽管他愿意 失去它。尽管如此,您上面的两个 cmets 是正确的。
-
@AmiTavory - 你说服我添加这个作为答案:-)
标签: c++ multithreading templates stl