我有std::deque<std::reference_wrapper<MyType>> mydeque
。我需要一个返回前值的函数(作为普通引用)并从队列中弹出它。由于std::deque
不是线程安全的,因此应该保护访问权限(我正在使用OpenMP)。
我想出了下面的丑陋代码。拥有这样的高级结构然后回到原始指针看起来非常糟糕。
MyType & retrieve() {
MyType* b;
#pragma omp critical(access_mydeque)
{
b = &(mydeque.front().get());
mydeque.pop_front();
}
return *b;
}
问题是我无法在的关键部分内返回,但我也无法在关键部分之前声明引用(_wrapper)(因为它必须分配给某事)...有办法解决这个问题吗?
答案 0 :(得分:2)
我能想到的任何解决方案都涉及使用omp_lock_t
代替critical
构造和管理omp_lock_t
所有权的RAII类:
class LockGuard {
public:
explicit LockGuard(omp_lock_t& lock) : m_lock(lock){
omp_set_lock(&m_lock);
}
~LockGuard() {
omp_unset_lock(&m_lock);
}
private:
omp_lock_t& m_lock;
};
然后你可以将你已经拥有的代码修改为:
MyType & retrieve() {
LockGuard guard(mydeque_lock);
auto b = mydeque.front();
mydeque.pop_front();
return b;
}
或更好,编写自己的线程安全容器来聚合锁和std::deque
:
template<class T>
class MtLifo {
public:
MtLifo() {
omp_init_lock(&m_lock);
}
typename std::deque<T>::reference front_and_pop() {
LockGuard guard(m_lock);
auto b = m_stack.front();
m_stack.pop_front();
return b;
}
void push_front(const T& value) {
LockGuard guard(m_lock);
m_stack.push_front(value);
}
~MtLifo() {
omp_destroy_lock(&m_lock);
}
private:
std::deque<T> m_stack;
omp_lock_t m_lock;
}
答案 1 :(得分:1)
你可以简单地使用TBB的并行数据结构https://software.intel.com/en-us/node/506076(虽然因为没有concurrent_deque它们可能不适合你:-()。
它们不要求您也使用TBB来描述代码的并行性方面,因此可以混合到OpenMP代码中。 (当然,既然你正在使用C ++,你可能会发现TBB的可扩展,可组合,并行的方法比OpenMP更友好,但这是一个可分离的决定。)