Jongju  Kim
Jongju Kim

Reputation: 184

How to safely use boost deadline timer in multiple threads?

I use boost deadline_timer like this code:

boost::asio::io_service g_io;
#define DEL(x) {delete x; x = NULL;}

void thr1()
{
    for(;;)
    {

         ...
        boost::asio::deadline_timer *t1 = new boost::asio::deadline_timer(g_io, boost::posix_time::seconds(60));
        t1->async_wait(boost::bind(&callback, boost::asio::placeholders::error, t1));

         ...
    }
}


void thr2()
{
    for(;;)
    {
           ....


        boost::asio::deadline_timer *t2 = new boost::asio::deadline_timer(g_io, boost::posix_time::seconds(60));
        t2->async_wait(boost::bind(&callback, boost::asio::placeholders::error, t2));

            ....
    }
}


void thr3()
{
    for(;;)
    {

         ....

        boost::asio::deadline_timer *t3 = new boost::asio::deadline_timer(g_io, boost::posix_time::seconds(60));
        t3->async_wait(boost::bind(&callback, boost::asio::placeholders::error, t3));

         ....
    }
}


void thr4()
{
    for(;;)
    {
         ....

        boost::asio::deadline_timer *t4 = new boost::asio::deadline_timer(g_io, boost::posix_time::seconds(60));
        t4->async_wait(boost::bind(&callback, boost::asio::placeholders::error, t4));

        ....
    }
}

void io_work()
{
    boost::asio::io_service::work work(g_io);
    g_io.run();
}


int main()
{
    boost::thread thread1(thr1);
    boost::thread thread2(thr2);
    boost::thread thread3(thr3);
    boost::thread thread4(thr4);

    boost::thread service_thread(io_work);

    thread1.join();
    thread2.join();
    thread3.join();
    thread4.join();

    service_thread.join();

    return 0;

}


void callback(const boost::system::error_code& e, boost::asio::deadline_timer *timer)
{
    if(e)
    {
        std::cout << "cancel" << std::endl;
    }
    else
    {
        std::cout << " time out occurred" << std::endl;

        if(timer->expires_at() <= boost::asio::deadline_timer::traits_type::now())
        {  
            if(timer) DEL(timer);
            return;
        }

        timer->expires_at(timer->expires_at()+boost::posix_time::seconds(1));
        timer->async_wait(boost::bind(callback, boost::asio::placeholders::error, timer));
    }
}

Timers are working well. However, when strange bug arise, I always doubted first my asio code because I couldn`t find similar asio code as I wrote.

Without any mutex or synchronization, can I register timer in multiple thread?

Also, if you find any problems in mycode, please advice me.

Thank you for reading.

Upvotes: 1

Views: 4697

Answers (2)

Matthias247
Matthias247

Reputation: 10396

You should notice that your callback function will always be invoked in the thread were io_service.run() is called, which is service_thread in your case. Therefore you access the timer objects on two threads without synchronization, which is not safe without synchronization.

However the exact situation depends on your complete code (what is in the ... sections). If you do it exactly like in your example (only creating and starting the timer in the first thread (which is guaranteed to happen before the callback) and accessing it aftwards only in the io_service thread it should be safe.

Upvotes: 1

sehe
sehe

Reputation: 392989

The deadline timer instances are not threadsafe.

Separate instances are threadsafe. So, either use separate timers, or add synchronization to the access.

Documentation link:

Upvotes: 3

Related Questions