GCC Code Coverage Report


Directory: libs/beast2/
File: src/asio_io_context.cpp
Date: 2025-11-13 15:50:44
Exec Total Coverage
Lines: 0 43 0.0%
Functions: 0 12 0.0%
Branches: 0 28 0.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/beast2
8 //
9
10 #include <boost/beast2/asio_io_context.hpp>
11 #include <boost/beast2/application.hpp>
12 #include <boost/beast2/server/call_mf.hpp>
13 #include <boost/asio/executor_work_guard.hpp>
14 #include <boost/asio/signal_set.hpp>
15 #include <thread>
16 #include <vector>
17
18 namespace boost {
19 namespace beast2 {
20
21 namespace {
22
23 /** Asio's io_context as an application part
24 */
25 class asio_io_context_impl
26 : public asio_io_context
27 {
28 public:
29 using key_type = asio_io_context;
30
31 ~asio_io_context_impl()
32 {
33 }
34
35 asio_io_context_impl(
36 application& app,
37 int num_threads)
38 : app_(app)
39 , num_threads_(num_threads)
40 , ioc_(num_threads)
41 , sigs_(ioc_.get_executor(), SIGINT, SIGTERM)
42 , work_(ioc_.get_executor())
43 {
44 if(num_threads > 1)
45 vt_.resize(num_threads - 1);
46 }
47
48 executor_type
49 get_executor() noexcept override
50 {
51 return ioc_.get_executor();
52 }
53
54 std::size_t
55 concurrency() const noexcept override
56 {
57 return num_threads_;
58 }
59
60 void attach() override
61 {
62 // VFALCO exception catcher?
63 ioc_.run();
64
65 // VFALCO can't figure out where to put this
66 for(auto& t : vt_)
67 t.join();
68 }
69
70 void start() override
71 {
72 // Capture SIGINT and SIGTERM to
73 // perform a clean shutdown
74 sigs_.async_wait(call_mf(
75 &asio_io_context_impl::on_signal, this));
76
77 for(auto& t : vt_)
78 {
79 t = std::thread(
80 [&]
81 {
82 // VFALCO exception catcher?
83 ioc_.run();
84 });
85 }
86 }
87
88 void stop() override
89 {
90 system::error_code ec;
91 sigs_.cancel(ec); // VFALCO should we use the 0-arg overload?
92 work_.reset();
93 }
94
95 private:
96 void
97 on_signal(
98 system::error_code const& ec, int)
99 {
100 if(ec == asio::error::operation_aborted)
101 return;
102 app_.stop();
103 }
104
105 application& app_;
106 int num_threads_;
107 asio::io_context ioc_;
108 asio::signal_set sigs_;
109 asio::executor_work_guard<
110 asio::io_context::executor_type> work_;
111 std::vector<std::thread> vt_;
112 };
113
114 } // (anon)
115
116 //------------------------------------------------
117
118 asio_io_context::
119 ~asio_io_context() = default;
120
121 auto
122 install_single_threaded_asio_io_context(
123 application& app) ->
124 asio_io_context&
125 {
126 return app.emplace<
127 asio_io_context_impl>(app, 1);
128 }
129
130 auto
131 install_multi_threaded_asio_io_context(
132 application& app,
133 int num_threads) ->
134 asio_io_context&
135 {
136 return app.emplace<
137 asio_io_context_impl>(app, num_threads);
138 }
139
140 } // beast2
141 } // boost
142