Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what if notify() is called before wait()?

Tags:

I have a situation where a notify() 'can' be called before a wait().

I am trying to make a simulator to schedule its next event when I 'notify' him by sending him messages. So I have devised a wait->notify->scedule chain

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();     } } 

the problem here is that: there can be situations that a notify() is called before its wait() is called.

Is there a solution for such situation? thank you

like image 593
rahman Avatar asked Jul 10 '13 05:07

rahman


People also ask

What happens if Notify is called before wait in Java?

Nothing stops you calling notify on an object that's not being wait ed by another thread.

What happens if notify () is called and no thread is in waiting state?

In other words, if the notify() method is called when no other thread is waiting, notify() simply returns and the notification is lost. A thread that later executes the wait() method has to wait for another notification to occur.

Can we use wait and notify without synchronized?

If you need to call wait(), notify(), or notifyAll() from within a non-synchronized method, then you must first obtain a lock on the object's monitor. If you don't, an exception will be generated when an attempt is made to call the method in question.

Is it important to acquire object lock before calling wait () notify () and notify all ()?

If no threads are waiting in the waiting queue, then notify() and notifyAll() have no effect. Before calling the notify() or notifyAll() method of an object, a thread must own the lock of the object. Hence it must be in one of the object's synchronizedmethods or synchronized block.


2 Answers

Condition variables can hardly be used alone, if only because, as you noticed, they only wake the currently waiting threads. There's also the matter of spurious wake-ups (ie. the condition variable can sometimes wake up a thread without any corresponding notify having been called). To work properly, condition variables usually need another variable to maintain a more reliable state.

To solve both those problems, in your case you just need to add a boolean flag:

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(); 
like image 131
syam Avatar answered Oct 14 '22 09:10

syam


I think that syam's answer is fine in general but in your specific case where you seem to be using ns-3, I would suggest instead that you restructure your code to use the right primitives in ns-3:

  1. I suspect that you use one of the ns-3 realtime simulator implementations. Good.
  2. Schedule a keeplive event for the 0.1s to make sure that the simulator keeps running (it will top running when there are no events left).
  3. Optionally, use a boolean in this keepalive event to check if you should reschedule the keepalive event or call Simulator::Stop.
  4. Create a thread to run the simulator mainloop with Simulator::Run(). The simulator will sleep until the next scheduled event is supposed to expire or until a new event is externally scheduled
  5. Use Simulator::ScheduleWithContext to schedule an event externally from another thread.

Keep in mind that the ns-3 API is not thread safe in general. The only ns-3 API that is thread-safe is ns3::Simulator::ScheduleWithContext. I can't stress out how important it is to not use any other API available in the ns-3:: namespace from a thread that is not the main thread.

like image 37
mathieu Avatar answered Oct 14 '22 07:10

mathieu