samedi 27 juillet 2019

Two threads running the same io_service

https://youtu.be/rwOv_tw2eA4?t=1030

This example has one io_service and two threads running on it.

  • the io_service has two tasks attached to it: timer1 and timer2

  • two threads are created to run the io_service

void timer_expired( std:: string id )
{
    std::cout << timestamp() << ": " << id << ": begin\n";
    std::this_thread::sleep_for( std::chrono::seconds(3) );
    std::cout << timestamp() << ": " << id << ": end\n";
}

int main()
{
    boost::asio::io_service io_service;

    boost::asio::deadline_timer timer1( io_service, boost::posix_time::seconds(5) );
    boost::asio::deadline_timer timer2( io_service, boost::posix_time::seconds(5) );

    timer1.async_wait( []( auto ... ){ timer_expired("timer1"); });
    timer2.async_wait( []( auto ... ){ timer_expired("timer2"); });


    std::cout << timestamp() << ": calling io_service run\n";

    std::thread thread1( [&](){ io_service.run(); } );
    std::thread thread2( [&](){ io_service.run(); } );

    thread1.join();
    thread2.join();

    std::cout << timestamp() << ": done\n";

    return 0;
}

Every time I run this sample the output looks ok, in that:

  • the two timers started at the same time

  • the two timers expired at the same time (after 5s, they were async)

  • the callbacks were invoked at the same time (after 3s)

The author stated that this code has race in there andshould not work (garage output).

What's not very clear is that we have two threads, each can serve one completion handler (here the timer callback). So why race? And the fact that I ran this code several times and unable to produce any garbage output as what the author presented.

The output looks as expected, here's a sample:

2019-07-28 11:27:44: calling io_service run
2019-07-28 11:27:49: timer1: begin
2019-07-28 11:27:49: timer2: begin
2019-07-28 11:27:52: timer1: end
2019-07-28 11:27:52: timer2: end
2019-07-28 11:27:52: done

Aucun commentaire:

Enregistrer un commentaire