Есть ли способ явным образом уничтожить все обработчики, ожидающие обработки для данного boost :: asio :: io_context? - PullRequest
0 голосов
/ 03 сентября 2018

Насколько я знаю и насколько я проверял документацию и исходный код boost :: asio, нет способа уничтожить явно все ожидающие обработчики в данном io_context, кроме уничтожения самого контекста?

Мне нужно иметь возможность, если возможно, остановить io_context, уничтожить ожидающие обработчики в io_context, затем сделать некоторые другие вещи и, наконец, уничтожить все объекты io (таймеры, каналы и т. Д.), Связанные с данным io_context и Сам io_context.

Я знаю, что могу использовать work_guard :: reset и разрешить запуск всех ожидающих обработчиков, а затем io_context остановится сам, но проблема в том, что многие обработчики могут создавать (post / defer / etc) новые ожидающие обработчики и т. д., т. е. каждый такой обработчик должен быть защищен чем-то вроде «если остановлен».

Я думаю, что io_context :: shutdown делает именно это, но, кроме наследования, нет способа явно вызвать функцию shutdown, потому что она не является публичной.

Спасибо.

1 Ответ

0 голосов
/ 03 сентября 2018

Проверка вашего предложения с использованием защищенного shutdown приведет к ошибке в моей системе. Я думаю, что это защищено по причине:)

Во всяком случае, похоже, что разумная комбинация restart / stop / reset может сделать эту работу. Странно, что некоторые очереди обработчиков, по-видимому, остаются в стороне, если только не выполняется (пусто) run / run_one. На самом деле, даже poll_one кажется достаточным. Итак, во что бы то ни стало, включите это.

Вот мой код тестового стенда, вы можете найти его полезным:

Live On Coliru

#include <boost/asio.hpp>
#include <iostream>
using namespace std::chrono_literals;

struct Handler {
    void operator()(boost::system::error_code ec) { std::cout << "Handler invoked: " << ec.message() << std::endl; }

    struct Instance { // logging only unique instance to avoid noise of moved handlers
        Instance()  { std::cout << "Created handler instance"   << std::endl; }
        ~Instance() { std::cout << "Destroyed handler instance" << std::endl; }
    };
    std::unique_ptr<Instance> _instance = std::make_unique<Instance>();
};

int main()
{
    struct Hack : boost::asio::io_context { 
        using boost::asio::io_context::shutdown;
    } io;
    auto work = make_work_guard(io);

    std::cout << " -- run" << std::endl;
    auto t = std::thread([&]{ io.run(); });

    {
        boost::asio::high_resolution_timer tim(io, 2s);
        tim.async_wait(Handler{});
        work.reset(); // no longer needed

        std::this_thread::sleep_for(500ms);

#if 1
        io.stop();
#else
        io.shutdown(); // segfaults
#endif
    }

    std::cout << " -- timer destructed" << std::endl;
    std::cout << " -- joining" << std::endl;
    t.join();

    std::cout << " -- empy run to flush handler queue" << std::endl;
    io.reset();
    //io.run();
    //io.run_one();
    io.poll_one();

    std::cout << " -- bye" << std::endl;
}

печать

 -- run
Created handler instance
 -- timer destructed
 -- joining
 -- empy run to flush handler queue
Handler invoked: Operation canceled
Destroyed handler instance
 -- bye

UPDATE

Вот мое лучшее предложение (кроме, я думаю, не делиться io вообще):

Live On Coliru

#include <boost/asio.hpp>
#include <iostream>
using namespace std::chrono_literals;

struct Handler {
    void operator()(boost::system::error_code ec) { std::cout << "Handler invoked: " << ec.message() << std::endl; }

    struct Instance { // logging only unique instance to avoid noise of moved handlers
        Instance()  { std::cout << "Created handler instance"   << std::endl; }
        ~Instance() { std::cout << "Destroyed handler instance" << std::endl; }
    };
    std::unique_ptr<Instance> _instance = std::make_unique<Instance>();
};

int main()
{
    std::unique_ptr<boost::asio::io_context> io;

    int i = 1;
    for (auto delay : { 1500ms, 500ms }) {
        std::cout << " ------------------- reinitialized -------------- \n";
        io = std::make_unique<boost::asio::io_context>();
        boost::asio::high_resolution_timer tim(*io, 1s);

        std::cout << i << " -- run" << std::endl;
        auto t = std::thread([&]{ io->run(); });

        tim.async_wait(Handler{});

        std::this_thread::sleep_for(delay);

        std::cout << i << " -- stop" << std::endl;
        io->stop();

        std::cout << i << " -- joining" << std::endl;
        t.join();

        std::cout << " ------------------- destruct ------------------- \n";
        io.reset();
    }

    std::cout << "Bye" << std::endl;
}

Печать

 ------------------- reinitialized -------------- 
1 -- run
Created handler instance
Handler invoked: Success
Destroyed handler instance
1 -- stop
1 -- joining
 ------------------- destruct ------------------- 
 ------------------- reinitialized -------------- 
1 -- run
Created handler instance
1 -- stop
1 -- joining
 ------------------- destruct ------------------- 
Destroyed handler instance
Bye
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...