RESTinio
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 
9 namespace restinio
10 {
11 
12 namespace 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 {
28 
29 public:
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 {
49 
50 public:
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]]
66 inline std::size_t
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  */
87 template< 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 )
100  : m_ioctx_holder{
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] {
135 
137  } };
138  } );
139 
140  // When all thread started successfully
141  // status can be changed.
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.
182  }
183  }
184 
185  bool started() const noexcept { return status_t::started == m_status; }
186 
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 */
std::size_t ensure_pool_size_non_zero(std::size_t pool_size)
auto & io_context() noexcept
Get access to io_context object.
external_io_context_for_thread_pool_t(asio_ns::io_context &ioctx)
Initializing constructor.
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, std::optional< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in std::optional<Value_Type> if parameter exis...
Definition: value_or.hpp:64
A class for holding a reference to external Asio&#39;s io_context.
ioctx_on_thread_pool_t(ioctx_on_thread_pool_t &&)=delete
A class for holding actual instance of Asio&#39;s io_context.
auto & io_context() noexcept
Get access to io_context object.
ioctx_on_thread_pool_t(std::size_t pool_size, Io_Context_Holder_Ctor_Args &&...ioctx_holder_args)
ioctx_on_thread_pool_t(const ioctx_on_thread_pool_t &)=delete
asio_ns::io_context & io_context() noexcept