I am getting acquainted with boost thread and signals. I am thus implementing this simple example, I only post the cpp file of an example class implementing a thread capable of executing a method when a Signal1 is fired. The signal is defined within a Package1Signals singleton (excuse me for these names, they have been generated from a model)
Class1.hpp
#ifndef CLASS1_HEADER
#define CLASS1_HEADER
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/udp.hpp>
#include <boost/asio/signal_set.hpp>
#include "Package1.hpp"
#include <boost/thread.hpp>
class Class1{
private:
boost::asio::io_service service;
public:
boost::thread thread;
Class1();
void classifierBehavior();
void Reception1(Signal1 signal1);
void Reception1Behavior();
};
#endif
Class1.cpp
#include "Class1.hpp"
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
#include "Package1.hpp"
#include "Package2.hpp"
#include "Package1.hpp"
Class1::Class1(){
//boost::thread thread(boost::bind(&Class1::classifierBehavior,boost::ref(*this)));
//thread.join();
thread = boost::thread(&Class1::classifierBehavior,this);
};
void Class1::classifierBehavior(){
Package1Signals::getInstance()->signal1.connect(boost::bind(&Class1::Reception1,
this,_1));
service.run();
};
void Class1::Reception1(Signal1 signal1){
std::cout<<"Signal received\n";
service.post(boost::bind(&Class1::Reception1Behavior, this));
}
void Class1::Reception1Behavior(){
std::cout<<"Behavior executed\n";
}
Package1.hpp
#ifndef PACKAGE1_HEADER
#define PACKAGE1_HEADER
#include <boost/signal.hpp>
struct Signal1{ };
class Package1Signals{
private:
Package1Signals();
static Package1Signals * instance;
public:
boost::signal<void(Signal1)> signal1;
static Package1Signals * getInstance();
};
#endif
Package1.cpp
#include "Package1.hpp"
Package1Signals * Package1Signals::instance = NULL;
Package1Signals::Package1Signals(){}
Package1Signals * Package1Signals::getInstance(){
if(!instance){
instance = new Package1Signals();
}
return instance;
}
here is the code which executes it
int main() {
Class1 test;
Package1Signals::getInstance()->signal1();
test.thread.join();
int k =0;
std::cin>>k;
return 0;
}
I can see the thread runs, the signal is intercepted but the posted handler is not executed. What am I doing wrong?
Are you sure? I don’t think the signal is event sent.
Your constructor creates a new thread, then waits for it to finish, so the constructor doesn’t return until the new thread exits. That means this line in
mainwon’t execute until the receiver thread exits:Maybe you want the
boost::threadto be a member of your class, so it has the same lifetime as your class, instead of being a local variable in the constructor.For style considerations, you don’t need to use
boost::ref(*this)you can just passthis, and you don’t need to useboost:bindto create the thread, read the docs which tell you that constructing athreadwith multiple arguments is equivalent to passing those arguments tobindand constructing the thread with the result i.e. you can just sayWhich is much simpler and easier to read!
Update: Now you’ve fixed the constructor so it doesn’t block you have a race condition between connecting the receiver to the signal, which happens in the new thread, and publishing the signal, which happens in the main thread, as soon as the constructor finishes. If the new thread takes a few milliseconds to start executing then it will be too late and miss the signal, because in the main thread the constructor will have finished and the signal will have been emitted already.
Try connecting the receiver before starting the new thread:
This way the receiver is connected before the signal is emitted.
I think the
io_servicewill still get the event even if the event gets posted before the service is running, but you might want to check that, otherwise there’s another race condition there.