Зачем нам нужно использовать boost:: asio:: io_service:: work?

Существует пример использования boost:: asio.

  • Почему в этом примере используется boost:: asio:: io_service:: work?
  • И почему srv.run (); не вызывается для выполнения задач в потоках?
int main()
{
    boost::asio::io_service srv;
    boost::asio::io_service::work work(srv);
    boost::thread_group thr_grp;
    thr_grp.create_thread(boost::bind(&boost::asio::io_service::run, &srv));
    thr_grp.create_thread(boost::bind(&boost::asio::io_service::run, &srv));

    srv.post(boost::bind(f1, 123));
    srv.post(boost::bind(f1, 321));
    //sync

    srv.post(boost::bind(f2, 456));
    srv.post(boost::bind(f2, 654));
    //sync

    srv.stop();
    thr_grp.join();
}

Update: В чем разница между опросом и запуском, когда io_service используется без io_service:: work?

int main()
{
    boost::asio::io_service srv;
    //boost::asio::io_service::work work(srv);
    std::vector<boost::thread> thr_grp;

    srv.post(boost::bind(f1, 123));
    srv.post(boost::bind(f1, 321));
    //sync

    srv.post(boost::bind(f2, 456));
    srv.post(boost::bind(f2, 654));
    //sync

    // What is the difference between the poll and run, when io_service without work?
    thr_grp.emplace_back(boost::bind(&boost::asio::io_service::poll, &srv));// poll or run?
    thr_grp.emplace_back(boost::bind(&boost::asio::io_service::run, &srv));// poll or run? 

    srv.stop();
    for(auto &i : thr_grp) i.join();

    int b;
    std::cin >> b;

    return 0;
}

Ответ 1

Когда метод io_service:: run вызывается без рабочего объекта, он немедленно вернется. Как правило, это не то поведение, которое ищет большинство разработчиков. Конечно, есть некоторые исключения, но большинство разработчиков хотят указать поток для обработки всей асинхронной обработки и не хотят, чтобы этот поток выходил, пока не сказал об этом. Это то, что делает ваш пример кода.

Метод io_service:: run указан в качестве указателя делегата или функции в методах create_thread. Итак, когда поток создается из метода create_thread, он вызывает метод io_service:: run и передает объект io_service в качестве аргумента. Обычно один объект io_service может использоваться с несколькими объектами сокета.

Метод остановки обычно вызывается при выключении приложения или когда связь между всеми клиентами/серверами больше не требуется, и не ожидается, что какие-либо новые подключения необходимо будет инициировать.