我有一个容器(C++),我需要从不同的线程以两种方式进行操作:1)添加和删除元素,2)遍历其成员。显然,在迭代发生时删除元素 = 灾难。代码看起来像这样:
class A
{
public:
...
void AddItem(const T& item, int index) { /*Put item into my_stuff at index*/ }
void RemoveItem(const T& item) { /*Take item out of m_stuff*/ }
const list<T>& MyStuff() { return my_stuff; } //*Hate* this, but see class C
private:
Mutex mutex; //Goes in the *Item methods, but is largely worthless in MyStuff()
list<T> my_stuff; //Just as well a vector or deque
};
extern A a; //defined in the .cpp file
class B
{
...
void SomeFunction() { ... a.RemoveItem(item); }
};
class C
{
...
void IterateOverStuff()
{
const list<T>& my_stuff(a.MyStuff());
for (list<T>::const_iterator it=my_stuff.begin(); it!=my_stuff.end(); ++it)
{
...
}
}
};
Again, B::SomeFunction()
and C::IterateOverStuff()
被异步调用。我可以使用什么数据结构来确保在迭代期间,my_stuff
是否受到添加或删除操作的“保护”?
听起来像读/写锁是需要的。基本上,这个想法是你可能有 1 个或多个读者OR一个作家。永远不能同时拥有读锁和写锁。
EDIT:我认为适合您的设计的一个使用示例包括进行一些小的更改。将“迭代”函数添加到拥有列表的类中并使其模板化,以便您可以传递函数/函子来定义每个节点要执行的操作。像这样的东西(快速而肮脏的伪代码,但你明白了......):
class A {
public:
...
void AddItem(const T& item, int index) {
rwlock.lock_write();
// add the item
rwlock.unlock_write();
}
void RemoveItem(const T& item) {
rwlock.lock_write();
// remove the item
rwlock.unlock_write();
}
template <class P>
void iterate_list(P pred) {
rwlock.lock_read();
std::for_each(my_stuff.begin(), my_stuff.end(), pred);
rwlock.unlock_read();
}
private:
rwlock_t rwlock;
list<T> my_stuff; //Just as well a vector or deque
};
extern A a; //defined in the .cpp file
class B {
...
void SomeFunction() { ... a.RemoveItem(item); }
};
class C {
...
void read_node(const T &element) { ... }
void IterateOverStuff() {
a.iterate_list(boost::bind(&C::read_node, this));
}
};
另外一个选择将使读取器/写入器锁可公开访问,并让调用者负责正确使用该锁。但这样更容易出错。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)