2

I am trying to mix boost signals with asio to do a dispatch based handler invocation. when the post method is invoked from a thread the io_service::run exits immediately, the callback handled to post is never invoked, callback is a C++11 lambda routine. I am pasting the code for more analysis.

#include<iostream>
#include<thread>
#include<boost/signals2/signal.hpp>
#include<boost/asio.hpp>

static boost::asio::io_service svc;
static boost::signals2::signal<void(std::string)> textEntered;

static void
handleInputText(std::string text)
{
    std::cout<<"handleInputText()"<<" text provided: "<<text;
    return;
}

static void 
worker()
{
    sleep(2);
    svc.post([](){
            std::cout<<"\nRaising signal.";
            std::string hello("hello world");
            textEntered(hello);
            });
    return;
}

int main(int ac, char **av)
{
    try
    {
        textEntered.connect(&handleInputText);
        std::thread w(std::bind(&worker));
        svc.run();
        w.join();
    }
    catch(std::exception &ex)
    {
        std::cerr<<"main() exited with exception:"<<ex.what();
    }
    return 0;
}
Ravikumar Tulugu
  • 1,702
  • 2
  • 18
  • 40

1 Answers1

3

You don't actually post any work to the service.

You start a thread that may eventually post work, but the main thread has already exited by that time.

Either, run the ioservice on the thread or make sure it has io_service::work

Here's a fix with a dedicated service thread and a work item:

Live On Coliru

#include<boost/asio.hpp>
#include<iostream>
#include<boost/asio.hpp>
#include<boost/signals2.hpp>
#include<boost/thread.hpp>
#include<boost/make_shared.hpp>

static boost::asio::io_service svc;
static boost::shared_ptr<boost::asio::io_service::work> work_lock;

static boost::signals2::signal<void(std::string)> textEntered;

static void
handleInputText(std::string text)
{
    std::cout<<"handleInputText()"<<" text provided: "<<text;
    return;
}

static void 
worker()
{
    sleep(2);
    svc.post([](){
            std::cout<<"\nRaising signal.";
            std::string hello("hello world");
            textEntered(hello);
       });
    return;
}

int main()
{
    try
    {
        work_lock = boost::make_shared<boost::asio::io_service::work>(svc);
        textEntered.connect(&handleInputText);

        boost::thread_group tg;
        tg.create_thread(boost::bind(&boost::asio::io_service::run, &svc));
        tg.create_thread(&worker);

        boost::this_thread::sleep_for(boost::chrono::seconds(3));
        work_lock.reset();

        tg.join_all();
    }
    catch(std::exception &ex)
    {
        std::cerr<<"main() exited with exception:"<<ex.what();
    }
    return 0;
}

Prints:

Raising signal.handleInputText() text provided: hello world
sehe
  • 374,641
  • 47
  • 450
  • 633
  • in the above code, run is supposed to block till the thread does a post. and then a join is there to wait for the thread. in my understanding , the run() should never return. i am just curious why run returns the moment post is called. – Ravikumar Tulugu Dec 17 '14 at 13:29
  • 1
    @RavikumarTulugu no. `run()` is not supposed to block. Read the documentation. And no it doesn't return the moment `post` is called. It returns. Immediately. (There is no reason for it to wait >2 seconds "just in case some work arrives") – sehe Dec 17 '14 at 13:29
  • Added a fixed sample, in case it helps – sehe Dec 17 '14 at 13:38
  • the documentation says , run is the event processing loop of boost io_service object. event processing loop blocks forever until we break the loop. am i missing any thing ? – Ravikumar Tulugu Dec 17 '14 at 13:46
  • Yes. You're missing the part where you break the loop because it runs out of work (or, it never had any). Docs: **[_The `run()` function blocks until all work has finished and there are no more handlers to be dispatched, or until the `io_service` has been stopped_](http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/io_service/run/overload1.html)**. So when you start it, it goes to look in the queue. It notices the queue is empty, so "all work has finished". Done. Did you see the fix in my answer? – sehe Dec 17 '14 at 13:50