如果在wait()之前调用notify()怎么办?

时间:2013-07-10 05:18:20

标签: c++ boost synchronization condition-variable ns-3

我有一种情况,可以在wait()之前调用notify()'。

当我通过向他发送消息通知他时,我正在尝试让模拟器安排下一个事件。所以我设计了一个wait-> notify-> scedule链

void Broker::pause()
{
    boost::unique_lock<boost::mutex> lock(m_pause_mutex);
    {
        std::cout << "pausing the simulation" << std::endl;
        m_cond_cnn.wait(lock);
        std::cout << "Simulation UNpaused" << std::endl;
        // the following line causes the current function to be called at 
        // a later time, and a notify() can happen before the current function
        // is called again
        Simulator::Schedule(MilliSeconds(xxx), &Broker::pause, this);
    }
}

void Broker::messageReceiveCallback(std::string message) {
    boost::unique_lock<boost::mutex> lock(m_pause_mutex);
    {
        m_cond_cnn.notify_one();
    }
}

这里的问题是:可能存在在调用wait()之前调用notify()的情况。

这种情况有解决方案吗? 谢谢

2 个答案:

答案 0 :(得分:13)

条件变量很难单独使用,只是因为,正如您所注意到的那样,它们只唤醒当前正在等待的线程。还有虚假唤醒的问题(即条件变量有时可以唤醒线程而没有任何相应的notify被调用)。为了正常工作,条件变量通常需要另一个变量来维持更可靠的状态。

要解决这两个问题,在你的情况下你只需要添加一个布尔标志:

boost::unique_lock<boost::mutex> lock(m_pause_mutex);
while (!someFlag)
    m_cond_cnn.wait(lock);
someFlag = false;

//...

boost::unique_lock<boost::mutex> lock(m_pause_mutex);
someFlag = true;
m_cond_cnn.notify_one();

答案 1 :(得分:2)

我认为syam的答案一般都很好,但在您似乎使用ns-3的特定情况下,我建议您重新构建代码以在ns-3中使用正确的原语:

  1. 我怀疑您使用的是ns-3实时模拟器实现之一。好。
  2. 为0.1s计划一个keeplive事件,以确保模拟器继续运行(当没有事件时,它将最先运行)。
  3. 或者,在此keepalive事件中使用布尔值来检查是否应重新安排keepalive事件或调用Simulator :: Stop。
  4. 使用Simulator :: Run()创建一个运行模拟器mainloop的线程。模拟器将一直睡眠,直到下一个预定的事件到期或直到新的事件被外部安排
  5. 使用Simulator :: ScheduleWithContext从另一个线程外部安排事件。
  6. 请记住,ns-3 API通常不是线程安全的。唯一的线程安全的ns-3 API是ns3 :: Simulator :: ScheduleWithContext。我不能强调从不是主线程的线程中不使用ns-3 :: namespace中可用的任何其他API的重要性。