Line data Source code
1 : #include "io_context_of.hpp"
2 : #include <boost/asio/strand.hpp>
3 : #include <chrono>
4 : #include <stdexcept>
5 :
6 : namespace thinger::asio {
7 :
8 : namespace {
9 :
10 : using io_executor = boost::asio::io_context::executor_type;
11 : // The executor of an io_context that keeps it running (as the work guards and the
12 : // executors of the handlers hold)
13 : using tracked_io_executor = boost::asio::io_context::basic_executor_type<std::allocator<void>, 4>;
14 :
15 : // How long run_until() waits for a handler before it checks again
16 : constexpr auto RUN_SLICE = std::chrono::milliseconds{10};
17 :
18 : }
19 :
20 772854 : boost::asio::io_context* io_context_of(const boost::asio::any_io_executor& executor) {
21 772854 : if (auto* io = executor.target<io_executor>()) return &io->context();
22 655115 : if (auto* io = executor.target<tracked_io_executor>()) return &io->context();
23 655109 : if (auto* strand = executor.target<boost::asio::strand<io_executor>>()) {
24 45 : return &strand->get_inner_executor().context();
25 : }
26 655064 : if (auto* strand = executor.target<boost::asio::strand<boost::asio::any_io_executor>>()) {
27 21 : return io_context_of(strand->get_inner_executor());
28 : }
29 655043 : return nullptr;
30 : }
31 :
32 2501120 : bool running_in_this_thread(const boost::asio::any_io_executor& executor) {
33 2501120 : if (auto* io = executor.target<io_executor>()) return io->running_in_this_thread();
34 5839 : if (auto* io = executor.target<tracked_io_executor>()) return io->running_in_this_thread();
35 5833 : if (auto* strand = executor.target<boost::asio::strand<io_executor>>()) return strand->running_in_this_thread();
36 411 : if (auto* strand = executor.target<boost::asio::strand<boost::asio::any_io_executor>>()) {
37 405 : return strand->running_in_this_thread();
38 : }
39 6 : return false;
40 : }
41 :
42 3196 : void run_until(boost::asio::io_context& io_context, const std::function<bool()>& done) {
43 3196 : if (io_context.get_executor().running_in_this_thread()) {
44 0 : throw std::logic_error("run_until() called on a thread running its io_context");
45 : }
46 50521 : while (!done()) {
47 44129 : if (io_context.run_one_for(RUN_SLICE) == 0 && io_context.stopped()) io_context.restart();
48 : }
49 3196 : io_context.poll();
50 3196 : if (io_context.stopped()) io_context.restart();
51 3196 : }
52 :
53 : } // namespace thinger::asio
|