RESTinio
Loading...
Searching...
No Matches
ioctx_on_thread_pool.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <thread>
4
5#include <restinio/asio_include.hpp>
6
7#include <restinio/exception.hpp>
8
9namespace restinio
10{
11
12namespace impl
13{
14
15/*!
16 * \brief A class for holding actual instance of Asio's io_context.
17 *
18 * \note
19 * This class is intended to be used as template argument for
20 * ioctx_on_thread_pool_t template.
21 *
22 * \since
23 * v.0.4.2
24 */
26{
27 asio_ns::io_context m_ioctx;
28
29public:
31
32 //! Get access to io_context object.
33 auto & io_context() noexcept { return m_ioctx; }
34};
35
36/*!
37 * \brief A class for holding a reference to external Asio's io_context.
38 *
39 * \note
40 * This class is intended to be used as template argument for
41 * ioctx_on_thread_pool_t template.
42 *
43 * \since
44 * v.0.4.2
45 */
47{
48 asio_ns::io_context & m_ioctx;
49
50public:
51 //! Initializing constructor.
53 //! External io_context to be used.
54 asio_ns::io_context & ioctx )
55 : m_ioctx{ ioctx }
56 {}
57
58 //! Get access to io_context object.
59 auto & io_context() noexcept { return m_ioctx; }
60};
61
63{
64
65[[nodiscard]]
66inline std::size_t
67ensure_pool_size_non_zero( std::size_t pool_size )
68{
69 if( !pool_size )
70 throw exception_t{ "pool_size can't be 0" };
71
72 return pool_size;
73}
74
75} /* namespace pool_size_checking */
76
77/*!
78 * Helper class for creating io_context and running it
79 * (via `io_context::run()`) on a thread pool.
80 *
81 * \note class is not thread-safe (except `io_context()` method).
82 * Expected usage scenario is to start and stop it on the same thread.
83 *
84 * \tparam Io_Context_Holder A type which actually holds io_context object
85 * or a reference to an external io_context object.
86 */
87template< typename Io_Context_Holder >
89{
90 public:
93
94 template< typename... Io_Context_Holder_Ctor_Args >
96 // Pool size.
97 std::size_t pool_size,
98 // Optional arguments for Io_Context_Holder instance.
99 Io_Context_Holder_Ctor_Args && ...ioctx_holder_args )
101 std::forward<Io_Context_Holder_Ctor_Args>(ioctx_holder_args)... }
103 , m_status( status_t::stopped )
104 {}
105
106 // Makes sure the pool is stopped.
108 {
109 if( started() )
110 {
111 stop();
112 wait();
113 }
114 }
115
116 void
118 {
119 if( started() )
120 {
121 throw exception_t{
122 "io_context_with_thread_pool is already started" };
123 }
124
125 try
126 {
127 std::generate(
128 begin( m_pool ),
129 end( m_pool ),
130 [this]{
131 return
132 std::thread{ [this] {
133 auto work{ asio_ns::make_work_guard(
134 m_ioctx_holder.io_context() ) };
135
136 m_ioctx_holder.io_context().run();
137 } };
138 } );
139
140 // When all thread started successfully
141 // status can be changed.
142 m_status = status_t::started;
143 }
144 catch( const std::exception & )
145 {
146 io_context().stop();
147 for( auto & t : m_pool )
148 if( t.joinable() )
149 t.join();
150
151 throw;
152 }
153 }
154
155 // NOTE: this method is marked as noexcept in v.0.6.7.
156 // It's because this method can be called from destructors and
157 // there is no way to recover from an exception thrown from
158 // this method.
159 void
160 stop() noexcept
161 {
162 if( started() )
163 {
164 io_context().stop();
165 }
166 }
167
168 // NOTE: this method is marked as noexcept in v.0.6.7.
169 // It's because this method can be called from destructors and
170 // there is no way to recover from an exception thrown from
171 // this method.
172 void
173 wait() noexcept
174 {
175 if( started() )
176 {
177 for( auto & t : m_pool )
178 t.join();
179
180 // When all threads are stopped status can be changed.
181 m_status = status_t::stopped;
182 }
183 }
184
185 bool started() const noexcept { return status_t::started == m_status; }
186
187 asio_ns::io_context &
188 io_context() noexcept
189 {
190 return m_ioctx_holder.io_context();
191 }
192
193 private:
194 enum class status_t : std::uint8_t { stopped, started };
195
196 Io_Context_Holder m_ioctx_holder;
199};
200
201} /* namespace impl */
202
203} /* namespace restinio */
Exception class for all exceptions thrown by RESTinio.
Definition exception.hpp:26
exception_t(const char *err)
Definition exception.hpp:29
A class for holding a reference to external Asio's io_context.
external_io_context_for_thread_pool_t(asio_ns::io_context &ioctx)
Initializing constructor.
auto & io_context() noexcept
Get access to io_context object.
asio_ns::io_context & io_context() noexcept
ioctx_on_thread_pool_t(const ioctx_on_thread_pool_t &)=delete
ioctx_on_thread_pool_t(ioctx_on_thread_pool_t &&)=delete
ioctx_on_thread_pool_t(std::size_t pool_size, Io_Context_Holder_Ctor_Args &&...ioctx_holder_args)
A class for holding actual instance of Asio's io_context.
auto & io_context() noexcept
Get access to io_context object.
std::size_t ensure_pool_size_non_zero(std::size_t pool_size)