RESTinio
http_server_run.hpp
Go to the documentation of this file.
1 /*
2  * restinio
3  */
4 
5 /*!
6  * \file
7  * \brief Helper function for simple run of HTTP server.
8  */
9 
10 #pragma once
11 
12 #include <restinio/impl/ioctx_on_thread_pool.hpp>
13 
14 #include <restinio/http_server.hpp>
15 
16 namespace restinio
17 {
18 
19 //
20 // break_signal_handling_t
21 //
22 /*!
23  * @brief Indication of usage of break signal handlers for some forms
24  * of run functions.
25  *
26  * @since v.0.5.1
27  */
29 {
30  //! Signal handler should be used by run() function.
31  used,
32  //! Signal handler should not be used by run() function.
33  skipped
34 };
35 
36 /*!
37  * @brief Make the indicator for usage of break signal handler.
38  *
39  * Usage example:
40  * @code
41  * restinio::run( restinio::on_thread_pool(
42  * std::thread::hardware_concurrency(),
43  * restinio::use_break_signal_handling(),
44  * my_server) );
45  * @endcode
46  *
47  * @since v.0.5.1
48  */
49 inline constexpr break_signal_handling_t
51 {
53 }
54 
55 /*!
56  * @brief Make the indicator for absence of break signal handler.
57  *
58  * Usage example:
59  * @code
60  * restinio::run( restinio::on_thread_pool(
61  * std::thread::hardware_concurrency(),
62  * restinio::skip_break_signal_handling(),
63  * my_server) );
64  * @endcode
65  *
66  * @since v.0.5.1
67  */
68 inline constexpr break_signal_handling_t
70 {
72 }
73 
74 //
75 // run_on_this_thread_settings_t
76 //
77 /*!
78  * \brief Settings for the case when http_server must be run
79  * on the context of the current thread.
80  *
81  * \note
82  * Shouldn't be used directly. Only as result of on_this_thread()
83  * function as parameter for run().
84  */
85 template<typename Traits>
87  : public basic_server_settings_t<
89  Traits>
90 {
93 public:
94  // Inherit constructors from base class.
95  using base_type_t::base_type_t;
96 };
97 
98 //
99 // on_this_thread
100 //
101 /*!
102  * \brief A special marker for the case when http_server must be
103  * run on the context of the current thread.
104  *
105  * Usage example:
106  * \code
107  * // Run with the default traits.
108  * run( restinio::on_this_thread()
109  * .port(8080)
110  * .address("localhost")
111  * .request_handler(...) );
112  * \endcode
113  * For a case when some custom traits must be used:
114  * \code
115  * run( restinio::on_this_thread<my_server_traits_t>()
116  * .port(8080)
117  * .address("localhost")
118  * .request_handler(...) );
119  * \endcode
120  */
121 template<typename Traits = default_single_thread_traits_t>
124 
125 //
126 // run_on_thread_pool_settings_t
127 //
128 /*!
129  * \brief Settings for the case when http_server must be run
130  * on the context of the current thread.
131  *
132  * \note
133  * Shouldn't be used directly. Only as result of on_thread_pool()
134  * function as parameter for run().
135  */
136 template<typename Traits>
138  : public basic_server_settings_t<
140  Traits>
141 {
142  //! Size of the pool.
144 
145 public:
146  //! Constructor.
148  //! Size of the pool.
149  std::size_t pool_size )
151  {}
152 
153  //! Get the pool size.
154  std::size_t
155  pool_size() const { return m_pool_size; }
156 };
157 
158 //
159 // on_thread_pool
160 //
161 /*!
162  * \brief A special marker for the case when http_server must be
163  * run on an thread pool.
164  *
165  * Usage example:
166  * \code
167  * // Run with the default traits.
168  * run( restinio::on_thread_pool(16) // 16 -- is the pool size.
169  * .port(8080)
170  * .address("localhost")
171  * .request_handler(...) );
172  * \endcode
173  * For a case when some custom traits must be used:
174  * \code
175  * run( restinio::on_thread_pool<my_server_traits_t>(16)
176  * .port(8080)
177  * .address("localhost")
178  * .request_handler(...) );
179  * \endcode
180  */
181 template<typename Traits = default_traits_t>
184  //! Size of the pool.
185  std::size_t pool_size )
186 {
188 }
189 
190 //
191 // run()
192 //
193 
194 
195 //! Helper function for running http server until ctrl+c is hit.
196 /*!
197  * Can be useful when RESTinio server should be run on the user's
198  * own io_context instance.
199  *
200  * For example:
201  * \code
202  * asio::io_context iosvc;
203  * ... // iosvc used by user.
204  * restinio::run(iosvc,
205  * restinio::on_this_thread<my_traits>()
206  * .port(8080)
207  * .address("localhost")
208  * .request_handler([](auto req) {...}));
209  * \endcode
210  *
211  * \since
212  * v.0.4.2
213  */
214 template<typename Traits>
215 inline void
217  //! Asio's io_context to be used.
218  //! Note: this reference should remain valid until RESTinio server finished.
219  asio_ns::io_context & ioctx,
220  //! Settings for that server instance.
221  run_on_this_thread_settings_t<Traits> && settings )
222 {
224  using server_t = http_server_t<Traits>;
225 
229 
232  [&]( const asio_ns::error_code & ec, int ){
233  if( !ec )
234  {
236  [&]{
237  // Stop running io_service.
238  ioctx.stop();
239  },
240  []( std::exception_ptr ex ){
242  } );
243  }
244  } );
245 
247  []{ /* Ok. */},
248  []( std::exception_ptr ex ){
250  } );
251 
252  ioctx.run();
253 }
254 
255 //! Helper function for running http server until ctrl+c is hit.
256 /*!
257  * This function creates its own instance of Asio's io_context and
258  * uses it exclusively.
259  *
260  * Usage example:
261  * \code
262  * restinio::run(
263  * restinio::on_this_thread<my_traits>()
264  * .port(8080)
265  * .address("localhost")
266  * .request_handler([](auto req) {...}));
267  * \endcode
268  */
269 template<typename Traits>
270 inline void
272  run_on_this_thread_settings_t<Traits> && settings )
273 {
276 }
277 
278 namespace impl {
279 
280 /*!
281  * \brief An implementation of run-function for thread pool case.
282  *
283  * This function receives an already created thread pool object and
284  * creates and runs http-server on this thread pool.
285  *
286  * \since
287  * v.0.4.2
288  */
289 template<typename Io_Context_Holder, typename Traits>
290 void
294 {
296  using server_t = http_server_t<Traits>;
297 
301 
304  [&]( const asio_ns::error_code & ec, int ){
305  if( !ec )
306  {
308  [&]{
309  // Stop running io_service.
310  pool.stop();
311  },
312  []( std::exception_ptr ex ){
314  } );
315  }
316  } );
317 
319  []{ /* Ok. */},
320  []( std::exception_ptr ex ){
322  } );
323 
324  pool.start();
325  pool.wait();
326 }
327 
328 } /* namespace impl */
329 
330 //! Helper function for running http server until ctrl+c is hit.
331 /*!
332  * This function creates its own instance of Asio's io_context and
333  * uses it exclusively.
334  *
335  * Usage example:
336  * \code
337  * restinio::run(
338  * restinio::on_thread_pool<my_traits>(4)
339  * .port(8080)
340  * .address("localhost")
341  * .request_handler([](auto req) {...}));
342  * \endcode
343  */
344 template<typename Traits>
345 inline void
346 run( run_on_thread_pool_settings_t<Traits> && settings )
347 {
350 
352 
353  impl::run( pool, std::move(settings) );
354 }
355 
356 //! Helper function for running http server until ctrl+c is hit.
357 /*!
358  * Can be useful when RESTinio server should be run on the user's
359  * own io_context instance.
360  *
361  * For example:
362  * \code
363  * asio::io_context iosvc;
364  * ... // iosvc used by user.
365  * restinio::run(iosvc,
366  * restinio::on_thread_pool<my_traits>(4)
367  * .port(8080)
368  * .address("localhost")
369  * .request_handler([](auto req) {...}));
370  * \endcode
371  *
372  * \since
373  * v.0.4.2
374  */
375 template<typename Traits>
376 inline void
378  //! Asio's io_context to be used.
379  //! Note: this reference should remain valid until RESTinio server finished.
380  asio_ns::io_context & ioctx,
381  //! Settings for that server instance.
382  run_on_thread_pool_settings_t<Traits> && settings )
383 {
386 
388 
389  impl::run( pool, std::move(settings) );
390 }
391 
392 //
393 // run_existing_server_on_thread_pool_t
394 //
395 /*!
396  * @brief Helper type for holding parameters necessary for running
397  * HTTP-server on a thread pool.
398  *
399  * @note This class is not intended for direct use. It is used by
400  * RESTinio itself.
401  *
402  * @since v.0.5.1
403  */
404 template<typename Traits>
406 {
407  //! Size of thread pool.
409  //! Should break signal handler be used?
411  //! HTTP-server to be used on a thread pool.
412  /*!
413  * We assume that this pointer will be valid pointer.
414  */
416 
417 public:
418  //! Initializing constructor.
420  //! Size of the pool.
421  std::size_t pool_size,
422  //! Should break signal handler be used?
423  break_signal_handling_t break_handling,
424  //! A reference to HTTP-server to be run on a thread pool.
425  //! This reference should outlive an instance of
426  //! run_existing_server_on_thread_pool_t.
427  http_server_t<Traits> & server )
430  , m_server{ &server }
431  {}
432 
433  std::size_t
434  pool_size() const noexcept { return m_pool_size; }
435 
437  break_handling() const noexcept { return m_break_handling; }
438 
440  server() const noexcept { return *m_server; }
441 };
442 
443 /*!
444  * @brief Helper function for running an existing HTTP-server on
445  * a thread pool.
446  *
447  * Usage example:
448  * @code
449  * using my_server_t = restinio::http_server_t< my_server_traits_t >;
450  * my_server_t server{
451  * restinio::own_io_context(),
452  * [](auto & settings) {
453  * settings.port(...);
454  * settings.address(...);
455  * settings.request_handler(...);
456  * ...
457  * }
458  * };
459  * ...
460  * restinio::run( restinio::on_thread_pool(
461  * std::thread::hardware_concurrency(),
462  * restinio::use_break_signal_handling(),
463  * server) );
464  * @endcode
465  *
466  * @since v.0.5.1
467  */
468 template<typename Traits>
471  std::size_t pool_size,
472  break_signal_handling_t break_handling,
473  http_server_t<Traits> & server )
474 {
475  return { pool_size, break_handling, server };
476 }
477 
478 namespace impl {
479 
480 /*!
481  * \brief An implementation of run-function for thread pool case
482  * with existing http_server instance.
483  *
484  * This function receives an already created thread pool object and
485  * already created http-server and run it on this thread pool.
486  *
487  * \attention
488  * This function installs break signal handler and stops server when
489  * break signal is raised.
490  *
491  * \since
492  * v.0.5.1
493  */
494 template<typename Io_Context_Holder, typename Traits>
495 void
499 {
502  [&]( const asio_ns::error_code & ec, int ){
503  if( !ec )
504  {
506  [&]{
507  // Stop running io_service.
508  pool.stop();
509  },
510  []( std::exception_ptr ex ){
512  } );
513  }
514  } );
515 
517  []{ /* Ok. */},
518  []( std::exception_ptr ex ){
520  } );
521 
522  pool.start();
523  pool.wait();
524 }
525 
526 /*!
527  * \brief An implementation of run-function for thread pool case
528  * with existing http_server instance.
529  *
530  * This function receives an already created thread pool object and
531  * already created http-server and run it on this thread pool.
532  *
533  * \note
534  * This function doesn't install break signal handlers.
535  *
536  * \since
537  * v.0.5.1
538  */
539 template<typename Io_Context_Holder, typename Traits>
540 void
544 {
546  []{ /* Ok. */},
547  []( std::exception_ptr ex ){
549  } );
550 
551  pool.start();
552  pool.wait();
553 }
554 
555 } /* namespace impl */
556 
557 /*!
558  * @brief Helper function for running an existing HTTP-server on
559  * a thread pool.
560  *
561  * Usage example:
562  * @code
563  * using my_server_t = restinio::http_server_t< my_server_traits_t >;
564  * my_server_t server{
565  * restinio::own_io_context(),
566  * [](auto & settings) {
567  * settings.port(...);
568  * settings.address(...);
569  * settings.request_handler(...);
570  * ...
571  * }
572  * };
573  * ...
574  * // run() returns if Ctrl+C is pressed or if HTTP-server will
575  * // be shut down from elsewhere.
576  * restinio::run( restinio::on_thread_pool(
577  * std::thread::hardware_concurrency(),
578  * restinio::use_break_signal_handling(),
579  * server) );
580  * @endcode
581  *
582  * @since v.0.5.1
583  */
584 template<typename Traits>
585 inline void
587 {
590 
592 
595  else
597 }
598 
599 //
600 // initiate_shutdown
601 //
602 /*!
603  * @brief Helper function for initiation of server shutdown.
604  *
605  * Can be useful if an existing HTTP-server is run via run() function.
606  * For example:
607  * @code
608  * restinio::http_server_t< my_traits > server{ ... };
609  * // Launch another thread that will perform some application logic.
610  * std::thread app_logic_thread{ [&server] {
611  * while(some_condition) {
612  * ...
613  * if(exit_case) {
614  * // HTTP-server should be shut down.
615  * restinio::initiate_shutdown( server );
616  * // Our work should be finished.
617  * return;
618  * }
619  * }
620  * } };
621  * // Start HTTP-server. The current thread will be blocked until
622  * // run() returns.
623  * restinio::run( restinio::on_thread_pool(
624  * 4,
625  * restinio::skip_break_signal_handling(),
626  * server) );
627  * // Now app_logic_thread can be joined.
628  * app_logic_thread.join();
629  * @endcode
630  *
631  * @since v.0.5.1
632  */
633 template<typename Traits>
634 inline void
636 {
637  server.io_context().post( [&server] {
638  server.close_sync();
639  server.io_context().stop();
640  } );
641 }
642 
643 //
644 // on_pool_runner_t
645 //
646 /*!
647  * @brief Helper class for running an existing HTTP-server on a thread pool
648  * without blocking the current thread.
649  *
650  * Usage of run() functions has some drawbacks. For example, the current thread
651  * on that run() is called, will be blocked until run() returns.
652  *
653  * Sometimes it is not appropriate and leads to tricks like that:
654  * @code
655  * // HTTP-server to be run on a thread pool.
656  * restinio::http_server_t< my_traits > server{...};
657  *
658  * // Separate worker thread for calling restinio::run().
659  * std::thread run_thread{ [&server] {
660  * restinio::run( restinio::on_thread_pool(
661  * 16,
662  * restinio::skip_break_signal_handling(),
663  * server) );
664  * // Now this thread is blocked until HTTP-server will be finished.
665  * } };
666  *
667  * ... // Some application specific code here.
668  *
669  * // Now the server can be stopped.
670  * restinio::initiate_shutdown( server );
671  * run_thread.join();
672  * @endcode
673  *
674  * Writing such code is a boring and error-prone task. The class
675  * on_pool_runner_t can be used instead:
676  * @code
677  * // HTTP-server to be run on a thread pool.
678  * restinio::http_server_t< my_traits > server{...};
679  *
680  * // Launch HTTP-server on a thread pool.
681  * restinio::on_pool_runner_t< restinio::http_server_t<my_traits> > runner{
682  * 16,
683  * server
684  * };
685  *
686  * ... // Some application specific code here.
687  *
688  * // Now the server can be stopped.
689  * runner.stop(); // (1)
690  * runner.wait();
691  * @endcode
692  *
693  * Moreover the code at point (1) in the example above it not necessary
694  * because on_pool_runner_t automatically stops the server in the destructor.
695  *
696  * @since v.0.5.1
697  */
698 template<typename Http_Server>
700 {
701  //! HTTP-server to be run.
702  Http_Server & m_server;
703 
704  //! Thread pool for running the server.
707 
708 public :
709  on_pool_runner_t( const on_pool_runner_t & ) = delete;
710  on_pool_runner_t( on_pool_runner_t && ) = delete;
711 
712  //! Initializing constructor.
714  //! Size of thread pool.
715  std::size_t pool_size,
716  //! Server instance to be run.
717  //! NOTE. This reference must be valid for all life-time
718  //! of on_pool_runner instance.
719  Http_Server & server )
720  : m_server{ server }
722  {}
723 
724  //! Start the server.
725  void
727  {
729  []{ /* Ok. */},
730  []( std::exception_ptr ex ){
732  } );
733 
734  m_pool.start();
735  }
736 
737 
738  //! Is server started.
739  bool
740  started() const noexcept { return m_pool.started(); }
741 
742  //! Stop the server.
743  void
745  {
747  [this]{
748  // Stop running io_service.
749  m_pool.stop();
750  },
751  []( std::exception_ptr ex ){
753  } );
754  }
755 
756  //! Wait for full stop of the server.
757  void
758  wait() { m_pool.wait(); }
759 };
760 
761 } /* namespace restinio */
void initiate_shutdown(http_server_t< Traits > &server)
Helper function for initiation of server shutdown.
void run(run_on_thread_pool_settings_t< Traits > &&settings)
Helper function for running http server until ctrl+c is hit.
void stop()
Stop the server.
void wait()
Wait for full stop of the server.
void run_without_break_signal_handling(ioctx_on_thread_pool_t< Io_Context_Holder > &pool, http_server_t< Traits > &server)
An implementation of run-function for thread pool case with existing http_server instance.
std::size_t m_pool_size
Size of the pool.
Helper type for holding parameters necessary for running HTTP-server on a thread pool.
void run(run_existing_server_on_thread_pool_t< Traits > &&params)
Helper function for running an existing HTTP-server on a thread pool.
run_existing_server_on_thread_pool_t(std::size_t pool_size, break_signal_handling_t break_handling, http_server_t< Traits > &server)
Initializing constructor.
run_on_this_thread_settings_t< Traits > on_this_thread()
A special marker for the case when http_server must be run on the context of the current thread...
constexpr break_signal_handling_t skip_break_signal_handling() noexcept
Make the indicator for absence of break signal handler.
void run(ioctx_on_thread_pool_t< Io_Context_Holder > &pool, run_on_thread_pool_settings_t< Traits > &&settings)
An implementation of run-function for thread pool case.
Helper class for running an existing HTTP-server on a thread pool without blocking the current thread...
std::size_t m_pool_size
Size of thread pool.
void run(run_on_this_thread_settings_t< Traits > &&settings)
Helper function for running http server until ctrl+c is hit.
on_pool_runner_t(std::size_t pool_size, Http_Server &server)
Initializing constructor.
http_server_t< Traits > * m_server
HTTP-server to be used on a thread pool.
Http_Server & m_server
HTTP-server to be run.
void run(asio_ns::io_context &ioctx, run_on_this_thread_settings_t< Traits > &&settings)
Helper function for running http server until ctrl+c is hit.
run_existing_server_on_thread_pool_t< Traits > on_thread_pool(std::size_t pool_size, break_signal_handling_t break_handling, http_server_t< Traits > &server)
Helper function for running an existing HTTP-server on a thread pool.
break_signal_handling_t
Indication of usage of break signal handlers for some forms of run functions.
void start()
Start the server.
on_pool_runner_t(on_pool_runner_t &&)=delete
break_signal_handling_t m_break_handling
Should break signal handler be used?
constexpr break_signal_handling_t use_break_signal_handling() noexcept
Make the indicator for usage of break signal handler.
on_pool_runner_t(const on_pool_runner_t &)=delete
void run_with_break_signal_handling(ioctx_on_thread_pool_t< Io_Context_Holder > &pool, http_server_t< Traits > &server)
An implementation of run-function for thread pool case with existing http_server instance.
Settings for the case when http_server must be run on the context of the current thread.
std::size_t pool_size() const
Get the pool size.
bool started() const noexcept
Is server started.
run_on_thread_pool_settings_t(std::size_t pool_size)
Constructor.
Settings for the case when http_server must be run on the context of the current thread.
run_on_thread_pool_settings_t< Traits > on_thread_pool(std::size_t pool_size)
A special marker for the case when http_server must be run on an thread pool.
Signal handler should not be used by run() function.
void run(asio_ns::io_context &ioctx, run_on_thread_pool_settings_t< Traits > &&settings)
Helper function for running http server until ctrl+c is hit.
Signal handler should be used by run() function.
break_signal_handling_t break_handling() const noexcept
http_server_t< Traits > & server() const 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
impl::ioctx_on_thread_pool_t< impl::external_io_context_for_thread_pool_t > m_pool
Thread pool for running the server.