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 
62 /*!
63  * Helper class for creating io_context and running it
64  * (via `io_context::run()`) on a thread pool.
65  *
66  * \note class is not thread-safe (except `io_context()` method).
67  * Expected usage scenario is to start and stop it on the same thread.
68  *
69  * \tparam Io_Context_Holder A type which actually holds io_context object
70  * or a reference to an external io_context object.
71  */
72 template< typename Io_Context_Holder >
74 {
75  public:
78 
79  template< typename... Io_Context_Holder_Ctor_Args >
81  // Pool size.
82  //FIXME: better to use not_null from gsl.
83  std::size_t pool_size,
84  // Optional arguments for Io_Context_Holder instance.
85  Io_Context_Holder_Ctor_Args && ...ioctx_holder_args )
88  , m_pool( pool_size )
90  {}
91 
92  // Makes sure the pool is stopped.
94  {
95  if( started() )
96  {
97  stop();
98  wait();
99  }
100  }
101 
102  void
104  {
105  if( started() )
106  {
107  throw exception_t{
108  "io_context_with_thread_pool is already started" };
109  }
110 
111  try
112  {
113  std::generate(
114  begin( m_pool ),
115  end( m_pool ),
116  [this]{
117  return
118  std::thread{ [this] {
121 
123  } };
124  } );
125 
126  // When all thread started successfully
127  // status can be changed.
129  }
130  catch( const std::exception & )
131  {
132  io_context().stop();
133  for( auto & t : m_pool )
134  if( t.joinable() )
135  t.join();
136 
137  throw;
138  }
139  }
140 
141  void
143  {
144  if( started() )
145  {
146  io_context().stop();
147  }
148  }
149 
150  void
152  {
153  if( started() )
154  {
155  for( auto & t : m_pool )
156  t.join();
157 
158  // When all threads are stopped status can be changed.
160  }
161  }
162 
163  bool started() const noexcept { return status_t::started == m_status; }
164 
166  io_context() noexcept
167  {
168  return m_ioctx_holder.io_context();
169  }
170 
171  private:
172  enum class status_t : std::uint8_t { stopped, started };
173 
174  Io_Context_Holder m_ioctx_holder;
177 };
178 
179 } /* namespace impl */
180 
181 } /* namespace restinio */
auto & io_context() noexcept
Get access to io_context object.
external_io_context_for_thread_pool_t(asio_ns::io_context &ioctx)
Initializing constructor.
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
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, optional_t< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in optional_t<Value_Type> if parameter exists ...
Definition: value_or.hpp:64