有没有办法显式销毁给定 boost::asio::io_context 上所有未决的处理程序?
Is there a way to explicitly destroy all handlers pending on a given boost::asio::io_context?
据我所知,据我检查 boost::asio 文档和源代码,除了销毁上下文本身之外,没有办法显式销毁给定 io_context 上所有挂起的处理程序吗?
如果可能的话,我需要能够停止 io_context,销毁 io_context 上挂起的处理程序,然后做一些其他事情,最后销毁所有 io 对象(计时器、管道等)与给定的 io_context 和 io_context 本身相关联。
我知道我可以使用 work_guard::reset 并让所有挂起的处理程序到 运行 然后 io_context 将自行停止,但问题是许多处理程序可能产生(post/defer/etc)个新的挂起的处理程序等,即每个这样的处理程序都需要用 'if stopped'.
之类的东西来保护
我认为 io_context::shutdown 确实做到了这一点,但除了继承之外,没有办法显式调用关闭函数,因为它不是 public。
谢谢。
使用受保护的 shutdown
尝试您的建议会导致我的系统出现段错误。我认为它受到保护是有原因的:)
无论如何,restart
/stop
/reset
的明智组合似乎可以完成这项工作。奇怪的是,一些处理程序队列显然停留在周围,除非一个人做了一个(空)run
/run_one
。事实上,即使 poll_one
似乎也足够了。所以,无论如何,包括那个。
这是我的测试床代码,您可能会发现它有用:
#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
更新
这是我最好的建议(除了 not sharing io
之外):
#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
据我所知,据我检查 boost::asio 文档和源代码,除了销毁上下文本身之外,没有办法显式销毁给定 io_context 上所有挂起的处理程序吗?
如果可能的话,我需要能够停止 io_context,销毁 io_context 上挂起的处理程序,然后做一些其他事情,最后销毁所有 io 对象(计时器、管道等)与给定的 io_context 和 io_context 本身相关联。
我知道我可以使用 work_guard::reset 并让所有挂起的处理程序到 运行 然后 io_context 将自行停止,但问题是许多处理程序可能产生(post/defer/etc)个新的挂起的处理程序等,即每个这样的处理程序都需要用 'if stopped'.
之类的东西来保护我认为 io_context::shutdown 确实做到了这一点,但除了继承之外,没有办法显式调用关闭函数,因为它不是 public。
谢谢。
使用受保护的 shutdown
尝试您的建议会导致我的系统出现段错误。我认为它受到保护是有原因的:)
无论如何,restart
/stop
/reset
的明智组合似乎可以完成这项工作。奇怪的是,一些处理程序队列显然停留在周围,除非一个人做了一个(空)run
/run_one
。事实上,即使 poll_one
似乎也足够了。所以,无论如何,包括那个。
这是我的测试床代码,您可能会发现它有用:
#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
更新
这是我最好的建议(除了 not sharing io
之外):
#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