我正在寻找一种方式来等待多个条件变量。 即。 就像是:
boost::condition_variable cond1;
boost::condition_variable cond2;
void wait_for_data_to_process()
{
boost::unique_lock<boost::mutex> lock(mut);
wait_any(lock, cond1, cond2); //boost only provides cond1.wait(lock);
process_data();
}
是这样的可能与条件变量。 如果不是有没有其他解决办法?
谢谢
我不相信你可以做这样的事与升压::线程。 也许是因为POSIX的条件变量不容许这种类型的构造。 当然,Windows已经WaitForMultipleObjects的为AJ发布,这可能是一个解决方案,如果你愿意限制你的代码到Windows同步原语。
另一种选择是使用更少的条件变量:刚才有你火的时候,什么“有趣”的情况1个条件变量。 然后,你要等待一些时间,你运行一个循环检查,看看如果感兴趣您的具体情况已经上来了,如果没有,回去等待条件变量。 你应该在这样一个循环的条件变量不管怎么说等着,作为条件变量等待受虚假唤醒(从boost ::螺纹文档,重点煤矿):
void wait(boost::unique_lock<boost::mutex>& lock)
...
功效:
原子呼叫lock.unlock()
并阻塞当前线程。 当由调用通知线程将解锁this->notify_one()
或this->notify_all()
或 。 ...
作为Managu已经回答,您可以使用相同的条件变量和检查多在while循环“事件”(布尔变量)。 然而,这些布尔变量的并发访问,必须使用该condvar使用相同的互斥体进行保护。
既然我已经通过输入这个代码示例相关的麻烦去的问题 ,我会在这里贴一次:
boost::condition_variable condvar;
boost::mutex mutex;
bool finished1 = false;
bool finished2 = false;
void longComputation1()
{
{
boost::lock_guard<boost::mutex> lock(mutex);
finished1 = false;
}
// Perform long computation
{
boost::lock_guard<boost::mutex> lock(mutex);
finished1 = true;
}
condvar.notify_one();
}
void longComputation2()
{
{
boost::lock_guard<boost::mutex> lock(mutex);
finished2 = false;
}
// Perform long computation
{
boost::lock_guard<boost::mutex> lock(mutex);
finished2 = true;
}
condvar.notify_one();
}
void somefunction()
{
// Wait for long computations to finish without "spinning"
boost::lock_guard<boost::mutex> lock(mutex);
while(!finished1 && !finished2)
{
condvar.wait(lock);
}
// Computations are finished
}
alternative solutions?
我不知道Boost库,但你可以使用WaitForMultipleObjects的功能来等待多个内核对象。 只是检查是否有所帮助。
作为Managu指出使用多个条件可能不是摆在首位一个很好的解决方案。 你想要做什么应该可以使用信号量来实现。
使用多个事件同一个条件变量技术上的作品,但它不允许封装。 所以我在做支持它一类的尝试。 没有测试过呢! 此外,它不支持notify_one()
因为我还没有制定出如何实现这一点。
#pragma once
#include <condition_variable>
#include <unordered_set>
// This is like a `condition_variable` but you can wait on multiple `multi_condition_variable`s.
// Internally it works by creating a new `condition_variable` for each `wait_any()` and registering
// it with the target `multi_condition_variable`s. When `notify_all()` is called, the main `condition_variable`
// is notified, as well as all the temporary `condition_variable`s created by `wait_any()`.
//
// There are two caveats:
//
// 1. You can't call the destructor if any threads are `wait()`ing. This is difficult to get around but
// it is the same as `std::wait_condition` anyway.
//
// 2. There is no `notify_one()`. You can *almost* implement this, but the only way I could think to do
// it was to add an `atomic_int` that indicates the number of waits(). Unfortunately there is no way
// to atomically increment it, and then wait.
class multi_condition_variable
{
public:
multi_condition_variable()
{
}
// Note that it is only safe to invoke the destructor if no thread is waiting on this condition variable.
~multi_condition_variable()
{
}
// Notify all threads calling wait(), and all wait_any()'s that contain this instance.
void notify_all()
{
_condition.notify_all();
for (auto o : _others)
o->notify_all();
}
// Wait for notify_all to be called, or a spurious wake-up.
void wait(std::unique_lock<std::mutex>& loc)
{
_condition.wait(loc);
}
// Wait for any of the notify_all()'s in `cvs` to be called, or a spurious wakeup.
static void wait_any(std::unique_lock<std::mutex>& loc, std::vector<std::reference_wrapper<multi_condition_variable>> cvs)
{
std::condition_variable c;
for (multi_condition_variable& cv : cvs)
cv.addOther(&c);
c.wait(loc);
for (multi_condition_variable& cv : cvs)
cv.removeOther(&c);
}
private:
void addOther(std::condition_variable* cv)
{
std::lock_guard<std::mutex> lock(_othersMutex);
_others.insert(cv);
}
void removeOther(std::condition_variable* cv)
{
// Note that *this may have been destroyed at this point.
std::lock_guard<std::mutex> lock(_othersMutex);
_others.erase(cv);
}
// The condition variable.
std::condition_variable _condition;
// When notified, also notify these.
std::unordered_set<std::condition_variable*> _others;
// Mutex to protect access to _others.
std::mutex _othersMutex;
};
// Example use:
//
// multi_condition_variable cond1;
// multi_condition_variable cond2;
//
// void wait_for_data_to_process()
// {
// unique_lock<boost::mutex> lock(mut);
//
// multi_condition_variable::wait_any(lock, {cond1, cond2});
//
// process_data();
// }