using Poco 1.9.0-1 from MSYS2 under Windows 7 (64 bits).
I have one thread, signaling a Poco:Condition for three times, with a sleep of 300ms.
I have two threads using two diferent classes EvListenerA and EvListenerB, that extends from Poco::Runnable, and they are waiting the same Poco::Condition to show a message with std::cout.
With the first and second signals, there are no problems, but when third signal is launched, only the thread EvListenerA capture it correctly.
This is the code:
/*
* main.cpp
*
* Created on: 6 jun. 2019
* Author: ccortiz
*/
#include <Poco/Thread.h>
#include <Poco/Runnable.h>
#include <Poco/Condition.h>
#include <iostream>
using namespace std;
Poco::Condition condicion;
Poco::Mutex mutex;
class GenEvents:public Poco::Runnable{
public:
void run(){
cout << "Launching GenEvents!" << endl;
for (Poco::UInt32 i=0; i<3; i++){
cout << "[GenEvents] Event_" << i << endl;
condicion.broadcast();
Poco::Thread::sleep(300); //Wait 300ms.
}
cout << "Ending GenEvents!" << endl;
}
};
class EvListenerA:public Poco::Runnable{
public:
void run(){
cout << "Launching EvListenerA!" << endl;
for (Poco::UInt32 i=0; i<3; i++){
condicion.wait(mutex);
cout << " [EvListenerA] Receiving Event_" << i << endl;
}
cout << "Ending EvListenerA!" << endl;
}
};
class EvListenerB:public Poco::Runnable{
public:
void run(){
cout << "Launching EvListenerB!" << endl;
for (Poco::UInt32 i=0; i<3; i++){
condicion.wait(mutex);
cout << " [EvListenerB] Receiving Event_" << i << endl;
}
cout << "Ending EvListenerB!" << endl;
}
};
int main(void){
Poco::Thread th1; //Hilo que genera 3 eventos.
Poco::Thread th2; //Hilo que espera 3 eventos.
Poco::Thread th3; //Hilo que espera 3 eventos.
GenEvents genEvents; //Objeto que implementa el hilo generador de eventos.
EvListenerA evListenerA; //Objeto que implementa el hilo receptor de eventos.
EvListenerB evListenerB; //Objeto que implementa el hilo receptor de eventos.
th2.start(evListenerA);
th3.start(evListenerB);
Poco::Thread::sleep(500); //Espera de medio segundo.
th1.start(genEvents);
th1.join();
th2.join();
th3.join();
}
This is the program output:
Launching EvListenerB!
Launching EvListenerA!
Launching GenEvents!
[GenEvents] Event_0
[EvListenerB] Receiving Event_0
[EvListenerA] Receiving Event_0
[GenEvents] Event_1
[EvListenerA] Receiving Event_1
[EvListenerB] Receiving Event_1
[GenEvents] Event_2
[EvListenerA] Receiving Event_2
Ending EvListenerA!
Ending GenEvents!
Why I don't have my "[EvListenerB] Receiving Event_2" in the output?
What happens with EvListenerB and Event_2?
Any idea? Thanks
Hmm, for me this is undefined behaviour. Reference states clearly that Condition
is used together with Mutex
or FastMutex
. When wait
is called mutex
must be locked! - it is missing in your code.
Quotes from reference:
A Condition object is always used in conjunction with a Mutex (or FastMutex) object.
and
Unlocks the mutex (which must be locked upon calling wait()) and waits for the given time until the Condition is signalled.
The given mutex will be locked again upon successfully leaving the function, even in case of an exception.
So if you want to see descired output you have to call lock/unlock onto mutex:
for (Poco::UInt32 i=0; i<3; i++)
{
mutex.lock(); // <--- lock mutex
condicion.wait(mutex);
cout << " [EvListenerA] Receiving Event_" << i << endl;
mutex.unlock(); // <--- unlock
}
do the same change for EvListenerA
and EvListenerB
classes.
First you are locking mutex. Then wait
is called, it unlocks mutex
and we are waiting until condition
is signaled, then wait
returns and mutex is locked again (before returning from wait
). Before leaving out of scope of for loop iteration unlock
is called.