Reputation: 5585
I have a problem where two threads are called like this, one after another.
new boost::thread( &SERVER::start_receive, this);
new boost::thread( &SERVER::run_io_service, this);
Where the first thread calls this function.
void start_receive()
{
udp_socket.async_receive(....);
}
and the second thread calls,
void run_io_service()
{
io_service.run();
}
and sometimes the io_service
thread ends up finishing before the start_receive()
thread and then the server cannot receive packets.
I thought about putting a sleep function between the two threads to wait a while for the start_receive()
to complete and that works but I wondered if there was another sure fire way to make this happen?
Upvotes: 0
Views: 1977
Reputation: 69892
When you call io_service.run()
, the thread will block, dispatching posted handlers until either:
There are no io_service::work
objects associated with the io_service
, or
io_service.stop()
is called.
If either of these happens, the io_service
enters the stopped state and will refuse to dispatch any more handlers in future until its reset()
method is called.
Every time you initiate an asynchronous operation on an io object associated with the io_service, an io_service::work object is embedded in the asynchronous handler.
For this reason, point (1) above cannot happen until the asynchronous handler has run.
this code therefore will guarantee that the async process completes and that the asserts pass:
asio::io_service ios; // ios is not in stopped state
assert(!ios.stopped());
auto obj = some_io_object(ios);
bool completed = false;
obj.async_something(..., [&](auto const& ec) { completed = true; });
// nothing will happen yet. There is now 1 work object associated with ios
assert(!completed);
auto ran = ios.run();
assert(completed);
assert(ran == 1); // only 1 async op waiting for completion.
assert(ios.stopped()); // io_service is exhausted and no work remaining
ios.reset();
assert(!ios.stopped()); // io_service is ready to run again
Upvotes: 3
Reputation: 19032
If you want to keep the io_service
running, create a work
object:
boost::asio::io_service svc;
auto work = std::make_shared<boost::asio::io_service::work>(svc);
svc.run(); // this will block as long as the work object is valid.
The nice thing about this approach is that the work
object above will keep the svc
object "running", but not block any other operations on it.
Upvotes: 2