Splash
Splash

Reputation: 1288

Elegantly stop the thread for blocking or non-blocking when accept or receive using asio and C++11

I am using asio for tcp server and I plan to use C++11 std for thread as well. My final goal is to have this application on Linux but I am testing it on Windows first using Visual Studio 2015.

First I am using blocking so I found there were discussion on how to stop a thread waiting on accept. There were pre-C++11 solutions such as pipe, and select. I am looking for the asio way.

    asio::io_service io_service;
    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 13));
    backAcceptor = &acceptor;
    tcp::socket socket(io_service);

    asio::error_code ec;
    acceptor.accept(socket, &ec);

Second way is to use asynchronous, but I prefer to use the asio header only. The compile complained that the asio::placeholder doesn't have this member but according to the comment, the solution is applied:

    asio::async_write(socket_, asio::buffer(message_),
        std::bind(&tcp_connection::handle_write, shared_from_this(),
            std::placeholders::_1,
            std::placeholders::_2
            ));

run() still block there. And I am looking for method to resume this thread from main.

    asio::io_service io_service;
    tcp_server server(io_service);
    io_service.run();

The third way is, to set a timeout here. But it doesn't stop my accept. Plus, the answer was in 2012. I hope there is new was to solve this by now.

Update

To test the scenarios, I first have a thread to either blocks at synchronous accept() or at asynchronous run(). When the thread is running, the main then waits for 2 seconds, and tries to stop the thread. Then I wait for the thread to complete using join.

For the first method "Synchronous", I tried to use acceptor.cancel() and the thread arrived at the join. Is this the correct way?

Second method "Async", although I am still not clear how to stop this thread officially, I succeeded using io_service.stop() to actually cancel it.

Please let me know whether my solutions is correct and I will continue to try different solutions.

Upvotes: 1

Views: 951

Answers (1)

sehe
sehe

Reputation: 393064

I happen to have played around with a non-typical approach with run_one and no threading, that specifically allows you timeout individual "non-asynch" operations:

In fact, you do post the asynch operations, but then you call await_operation with a timeout:

async_connect(socket, ip::tcp::resolver(ioservice).resolve({address, port}), raise());
await_socket(std::chrono::seconds(6));

This is the equivalent of doing a synchronous connect but with the possibility to timeout. No threads, blocking run() or other puppies were harmed.

See the linked answer for demos


PS. Use deadline_timer with posix_time if you don't want the high_resolution_timer which works nicely with std::chrono

Upvotes: 1

Related Questions