考虑一个系统,其中一堆线程等待某些事务完成(请注意,多个线程可以等待单个事务)。为了完成事务,其中一个线程必须运行一个分派循环。一旦当前正在运行调度循环的线程等待事务完成,其他线程之一必须接管该作业。
在Windows上,这很容易实现:对于每个事务,都会在事务完成时设置手动重置事件。此外,还有一个自动复位事件,在调度循环退出时设置。每个线程同时等待两个事件。事务事件首先发出信号 - 在这种情况下线程退出 - 或循环事件 - 在这种情况下线程运行调度循环。
如何在Linux上实现这一点(或者更好的是,Posix)?目前,我用bool
变量替换了上面的事件,我有一个条件变量来表示其中一个变化。然而,在这种安排中,线程虚假地唤醒(每当一个事务完成时,所有线程都被唤醒)。有没有办法更好地实现这个?
答案 0 :(得分:4)
我可能没有完全清楚您的场景,但我认为您可以为每个事务使用一个条件变量(但仍然只有一个互斥锁)。
当事务结束时,会发出相应的条件变量信号;当调度循环退出时,所有条件变量都会发出信号。
答案 1 :(得分:0)
我可能误解了你的要求。我会为事件创建一个抽象,并有一个事件队列。派生事件将被排队,并且线程正在等待队列非空的条件。 enqueue会在条件变量上产生信号。
struct AnEvent {
int type_;
union {
//...
};
};
struct EventQ {
std::mutex m_;
std::condition_variable c_;
std::list<AnEvent> q_;
void enq (const AnEvent &e) {
std::lock_guard<std::mutex> g(m_);
bool was_empty = q_.empty();
q_.push_back(e);
if (was_empty) c_.notify_one();
};
void deq (AnEvent &e) {
std::lock_guard<std::mutex> g(m_);
while (q_.empty()) c_.wait(m_);
e = q_.top();
q_.pop_front();
if (!q_.empty()) c_.notify_one();
}