Boost::Asio : io_service.run() vs poll() or how do I integrate boost::asio in mainloop
Asked Answered
S

3

38

I am currently trying to use boost::asio for some simple tcp networking for the first time, and I allready came across something I am not really sure how to deal with. As far as I understand io_service.run() method is basically a loop which runs until there is nothing more left to do, which means it will run until I release my little server object. Since I allready got some sort of mainloop set up, I would rather like to update the networking loop manually from there just for the sake of simplicity, and I think io_service.poll() would do what I want, sort of like this:

void myApplication::update()
{
     myIoService.poll();
     //do other stuff
}

This seems to work, but I am still wondering if there is a drawback from this method since that does not seem to be the common way to deal with boost::asios io services. Is this a valid approach or should I rather use io_service.run() in a non blocking extra thread?

Schlosser answered 16/1, 2011 at 12:46 Comment(0)
P
45

Using io_service::poll instead of io_service::run is perfectly acceptable. The difference is explained in the documentation

The poll() function may also be used to dispatch ready handlers, but without blocking.

Note that io_service::run will block if there's any work left in the queue

The work class is used to inform the io_service when work starts and finishes. This ensures that the io_service object's run() function will not exit while work is underway, and that it does exit when there is no unfinished work remaining.

whereas io_service::poll does not exhibit this behavior, it just invokes ready handlers. Also note that you will need to invoke io_service::reset on any subsequent invocation to io_service:run or io_service::poll.

Purpura answered 16/1, 2011 at 13:8 Comment(3)
io_service is not necessarily stopped after io_service::poll returned. Why need io_service::reset before subsequent io_service::run or io_service:poll?Ia
1+ for io_service::reset. If run doesn't find any work, _stopped is set to true which prevents any future added tasks to be handled. reset sets _stopped back to false.Fourchette
Yeah io_service::reset was referring to io_service::run in particularTwelvetone
F
4

A drawback is that you'll make a busy loop.

while(true) {
    myIoService.poll()
}

will use 100% cpu. myIoService.run() will use 0% cpu.

myIoService.run_one() might do what you want but it will block if there is nothing for it to do.

Foxworth answered 9/9, 2014 at 2:13 Comment(1)
you would indeed prefer run in this simplistic case but in the situation where an event loop already exists (say it's doing background rendering or other things in spare cycles) then poll would be preferred as you don't want the game coming to a halt every time run() blocks.Diablerie
N
1

A loop like this lets you poll, doesn't busy-wait, and resets as needed. (I'm using the more recent io_context that replaced io_service.)

while (!exitCondition) {
    if (ioContext.stopped()) {
        ioContext.restart();
    }
    if (!ioContext.poll()) {
        if (stuffToDo) {
            doYourStuff();
        } else {
            std::this_thread::sleep_for(std::chrono::milliseconds(3));
        }
    }
}
Neoimpressionism answered 15/9, 2020 at 15:38 Comment(1)
It is hard to adjust granularity here. You picked 3 milliseconds here, but maybe that is not the right value for my application. So, this is not an universal solution.Fairground

© 2022 - 2024 — McMap. All rights reserved.