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 
231 
234  [&]( const asio_ns::error_code & ec, int ){
235  if( !ec )
236  {
238  [&]{
239  // Stop running io_service.
240  ioctx.stop();
241  },
243  // We can't throw an exception here!
244  // Store it to rethrow later.
246  } );
247  }
248  } );
249 
251  []{ /* Ok. */},
253  // Stop running io_service.
254  // We can't throw an exception here!
255  // Store it to rethrow later.
256  ioctx.stop();
258  } );
259 
260  ioctx.run();
261 
262  // If an error was detected it should be propagated.
263  if( exception_caught )
265 }
266 
267 //! Helper function for running http server until ctrl+c is hit.
268 /*!
269  * This function creates its own instance of Asio's io_context and
270  * uses it exclusively.
271  *
272  * Usage example:
273  * \code
274  * restinio::run(
275  * restinio::on_this_thread<my_traits>()
276  * .port(8080)
277  * .address("localhost")
278  * .request_handler([](auto req) {...}));
279  * \endcode
280  */
281 template<typename Traits>
282 inline void
284  run_on_this_thread_settings_t<Traits> && settings )
285 {
288 }
289 
290 namespace impl {
291 
292 /*!
293  * \brief An implementation of run-function for thread pool case.
294  *
295  * This function receives an already created thread pool object and
296  * creates and runs http-server on this thread pool.
297  *
298  * \since
299  * v.0.4.2
300  */
301 template<typename Io_Context_Holder, typename Traits>
302 void
306 {
308  using server_t = http_server_t<Traits>;
309 
313 
315 
318  [&]( const asio_ns::error_code & ec, int ){
319  if( !ec )
320  {
322  [&]{
323  // Stop running io_service.
324  pool.stop();
325  },
327  // We can't throw an exception here!
328  // Store it to rethrow later.
330  } );
331  }
332  } );
333 
335  []{ /* Ok. */},
337  // Stop running io_service.
338  // We can't throw an exception here!
339  // Store it to rethrow later.
340  pool.stop();
342  } );
343 
344  pool.start();
345  pool.wait();
346 
347  // If an error was detected it should be propagated.
348  if( exception_caught )
350 }
351 
352 } /* namespace impl */
353 
354 //! Helper function for running http server until ctrl+c is hit.
355 /*!
356  * This function creates its own instance of Asio's io_context and
357  * uses it exclusively.
358  *
359  * Usage example:
360  * \code
361  * restinio::run(
362  * restinio::on_thread_pool<my_traits>(4)
363  * .port(8080)
364  * .address("localhost")
365  * .request_handler([](auto req) {...}));
366  * \endcode
367  */
368 template<typename Traits>
369 inline void
370 run( run_on_thread_pool_settings_t<Traits> && settings )
371 {
374 
376 
377  impl::run( pool, std::move(settings) );
378 }
379 
380 //! Helper function for running http server until ctrl+c is hit.
381 /*!
382  * Can be useful when RESTinio server should be run on the user's
383  * own io_context instance.
384  *
385  * For example:
386  * \code
387  * asio::io_context iosvc;
388  * ... // iosvc used by user.
389  * restinio::run(iosvc,
390  * restinio::on_thread_pool<my_traits>(4)
391  * .port(8080)
392  * .address("localhost")
393  * .request_handler([](auto req) {...}));
394  * \endcode
395  *
396  * \since
397  * v.0.4.2
398  */
399 template<typename Traits>
400 inline void
402  //! Asio's io_context to be used.
403  //! Note: this reference should remain valid until RESTinio server finished.
404  asio_ns::io_context & ioctx,
405  //! Settings for that server instance.
406  run_on_thread_pool_settings_t<Traits> && settings )
407 {
410 
412 
413  impl::run( pool, std::move(settings) );
414 }
415 
416 //
417 // run_existing_server_on_thread_pool_t
418 //
419 /*!
420  * @brief Helper type for holding parameters necessary for running
421  * HTTP-server on a thread pool.
422  *
423  * @note This class is not intended for direct use. It is used by
424  * RESTinio itself.
425  *
426  * @since v.0.5.1
427  */
428 template<typename Traits>
430 {
431  //! Size of thread pool.
433  //! Should break signal handler be used?
435  //! HTTP-server to be used on a thread pool.
436  /*!
437  * We assume that this pointer will be valid pointer.
438  */
440 
441 public:
442  //! Initializing constructor.
444  //! Size of the pool.
445  std::size_t pool_size,
446  //! Should break signal handler be used?
447  break_signal_handling_t break_handling,
448  //! A reference to HTTP-server to be run on a thread pool.
449  //! This reference should outlive an instance of
450  //! run_existing_server_on_thread_pool_t.
451  http_server_t<Traits> & server )
454  , m_server{ &server }
455  {}
456 
457  std::size_t
458  pool_size() const noexcept { return m_pool_size; }
459 
461  break_handling() const noexcept { return m_break_handling; }
462 
464  server() const noexcept { return *m_server; }
465 };
466 
467 /*!
468  * @brief Helper function for running an existing HTTP-server on
469  * a thread pool.
470  *
471  * Usage example:
472  * @code
473  * using my_server_t = restinio::http_server_t< my_server_traits_t >;
474  * my_server_t server{
475  * restinio::own_io_context(),
476  * [](auto & settings) {
477  * settings.port(...);
478  * settings.address(...);
479  * settings.request_handler(...);
480  * ...
481  * }
482  * };
483  * ...
484  * restinio::run( restinio::on_thread_pool(
485  * std::thread::hardware_concurrency(),
486  * restinio::use_break_signal_handling(),
487  * server) );
488  * @endcode
489  *
490  * @since v.0.5.1
491  */
492 template<typename Traits>
495  std::size_t pool_size,
496  break_signal_handling_t break_handling,
497  http_server_t<Traits> & server )
498 {
499  return { pool_size, break_handling, server };
500 }
501 
502 namespace impl {
503 
504 /*!
505  * \brief An implementation of run-function for thread pool case
506  * with existing http_server instance.
507  *
508  * This function receives an already created thread pool object and
509  * already created http-server and run it on this thread pool.
510  *
511  * \attention
512  * This function installs break signal handler and stops server when
513  * break signal is raised.
514  *
515  * \since
516  * v.0.5.1
517  */
518 template<typename Io_Context_Holder, typename Traits>
519 void
523 {
525 
528  [&]( const asio_ns::error_code & ec, int ){
529  if( !ec )
530  {
532  [&]{
533  // Stop running io_service.
534  pool.stop();
535  },
537  // We can't throw an exception here!
538  // Store it to rethrow later.
540  } );
541  }
542  } );
543 
545  []{ /* Ok. */},
547  // Stop running io_service.
548  // We can't throw an exception here!
549  // Store it to rethrow later.
550  pool.stop();
552  } );
553 
554  pool.start();
555  pool.wait();
556 
557  // If an error was detected it should be propagated.
558  if( exception_caught )
560 }
561 
562 /*!
563  * \brief An implementation of run-function for thread pool case
564  * with existing http_server instance.
565  *
566  * This function receives an already created thread pool object and
567  * already created http-server and run it on this thread pool.
568  *
569  * \note
570  * This function doesn't install break signal handlers.
571  *
572  * \since
573  * v.0.5.1
574  */
575 template<typename Io_Context_Holder, typename Traits>
576 void
580 {
582 
584  []{ /* Ok. */},
586  // Stop running io_service.
587  // We can't throw an exception here!
588  // Store it to rethrow later.
589  pool.stop();
591  } );
592 
593  pool.start();
594  pool.wait();
595 
596  // If an error was detected it should be propagated.
597  if( exception_caught )
599 }
600 
601 } /* namespace impl */
602 
603 /*!
604  * @brief Helper function for running an existing HTTP-server on
605  * a thread pool.
606  *
607  * Usage example:
608  * @code
609  * using my_server_t = restinio::http_server_t< my_server_traits_t >;
610  * my_server_t server{
611  * restinio::own_io_context(),
612  * [](auto & settings) {
613  * settings.port(...);
614  * settings.address(...);
615  * settings.request_handler(...);
616  * ...
617  * }
618  * };
619  * ...
620  * // run() returns if Ctrl+C is pressed or if HTTP-server will
621  * // be shut down from elsewhere.
622  * restinio::run( restinio::on_thread_pool(
623  * std::thread::hardware_concurrency(),
624  * restinio::use_break_signal_handling(),
625  * server) );
626  * @endcode
627  *
628  * @since v.0.5.1
629  */
630 template<typename Traits>
631 inline void
633 {
636 
638 
641  else
643 }
644 
645 //
646 // initiate_shutdown
647 //
648 /*!
649  * @brief Helper function for initiation of server shutdown.
650  *
651  * Can be useful if an existing HTTP-server is run via run() function.
652  * For example:
653  * @code
654  * restinio::http_server_t< my_traits > server{ ... };
655  * // Launch another thread that will perform some application logic.
656  * std::thread app_logic_thread{ [&server] {
657  * while(some_condition) {
658  * ...
659  * if(exit_case) {
660  * // HTTP-server should be shut down.
661  * restinio::initiate_shutdown( server );
662  * // Our work should be finished.
663  * return;
664  * }
665  * }
666  * } };
667  * // Start HTTP-server. The current thread will be blocked until
668  * // run() returns.
669  * restinio::run( restinio::on_thread_pool(
670  * 4,
671  * restinio::skip_break_signal_handling(),
672  * server) );
673  * // Now app_logic_thread can be joined.
674  * app_logic_thread.join();
675  * @endcode
676  *
677  * @since v.0.5.1
678  */
679 template<typename Traits>
680 inline void
682 {
683  server.io_context().post( [&server] {
684  server.close_sync();
685  server.io_context().stop();
686  } );
687 }
688 
689 /*!
690  * @brief Type of a function to be used as the default on_error-callback.
691  *
692  * Since v.0.7.0 on_pool_runner_t::stop() accept a on_error callback that
693  * will be passed to http_server_t::close_async() and will be called if
694  * an exception is thrown in http_server_t::close_async().
695  * This callback should perform some actions that can help the application
696  * to handle the problem.
697  *
698  * This type is intended to be used as the default on_error callback.
699  *
700  * If an exception in thrown inside http_server_t::close_async() then
701  * the application is in undefined state, it's unknown what can be done
702  * with http_server_t instance and whan can't be.
703  *
704  * Therefore the default on_error callback simply calls std::abort() to
705  * terminate the application and avoid the work in undefined state.
706  *
707  * If such behavour is not desirable the user can provide own
708  * on_error callback.
709  *
710  * @since v.0.7.0
711  */
713 {
714  /*!
715  * @attention
716  * It just calls std::abort().
717  */
718  [[noreturn]]
719  void
720  operator()( std::exception_ptr /*ex*/ ) const noexcept
721  {
722  std::abort();
723  }
724 };
725 
726 //
727 // on_pool_runner_t
728 //
729 /*!
730  * @brief Helper class for running an existing HTTP-server on a thread pool
731  * without blocking the current thread.
732  *
733  * Usage of run() functions has some drawbacks. For example, the current thread
734  * on that run() is called, will be blocked until run() returns.
735  *
736  * Sometimes it is not appropriate and leads to tricks like that:
737  * @code
738  * // HTTP-server to be run on a thread pool.
739  * restinio::http_server_t< my_traits > server{...};
740  *
741  * // Separate worker thread for calling restinio::run().
742  * std::thread run_thread{ [&server] {
743  * restinio::run( restinio::on_thread_pool(
744  * 16,
745  * restinio::skip_break_signal_handling(),
746  * server) );
747  * // Now this thread is blocked until HTTP-server will be finished.
748  * } };
749  *
750  * ... // Some application specific code here.
751  *
752  * // Now the server can be stopped.
753  * restinio::initiate_shutdown( server );
754  * run_thread.join();
755  * @endcode
756  *
757  * Writing such code is a boring and error-prone task. The class
758  * on_pool_runner_t can be used instead:
759  * @code
760  * // HTTP-server to be run on a thread pool.
761  * restinio::http_server_t< my_traits > server{...};
762  *
763  * // Launch HTTP-server on a thread pool.
764  * restinio::on_pool_runner_t< restinio::http_server_t<my_traits> > runner{
765  * 16,
766  * server
767  * };
768  * runner.start();
769  *
770  * ... // Some application specific code here.
771  *
772  * // Now the server can be stopped.
773  * runner.stop(); // (1)
774  * runner.wait();
775  * @endcode
776  *
777  * Moreover the code at point (1) in the example above it not necessary
778  * because on_pool_runner_t automatically stops the server in the destructor.
779  *
780  * @since v.0.5.1
781  */
782 template<typename Http_Server>
784 {
785  //! HTTP-server to be run.
786  Http_Server & m_server;
787 
788  //! Thread pool for running the server.
791 
792 public :
793  on_pool_runner_t( const on_pool_runner_t & ) = delete;
794  on_pool_runner_t( on_pool_runner_t && ) = delete;
795 
796  //! Initializing constructor.
798  //! Size of thread pool.
799  std::size_t pool_size,
800  //! Server instance to be run.
801  //! NOTE. This reference must be valid for all life-time
802  //! of on_pool_runner instance.
803  Http_Server & server )
804  : m_server{ server }
806  {}
807 
808  /*!
809  * @brief Start the server with callbacks that will be called on
810  * success or failure.
811  *
812  * The @a on_ok should be a function/functor with the format:
813  * @code
814  * void () noexcept;
815  * @endcode
816  *
817  * The @a on_error should be a function/functor with the format:
818  * @code
819  * void (std::exception_ptr) noexcept;
820  * @endcode
821  *
822  * @note
823  * Both callbacks will be passed to http_server_t::open_async method.
824  * It means that @a on_error callback will be called for errors detected
825  * by open_async() methods.
826  *
827  * @attention
828  * Both callbacks should be noexcept functions/functors.
829  *
830  * Usage example:
831  * @code
832  * using my_http_server = restinio::http_server_t<some_traits>;
833  *
834  * my_http_server server{...};
835  * restinio::on_pool_runner_t<my_http_server> runner{16, server};
836  *
837  * std::promise<void> run_promise;
838  * auto run_future = run_promise.get_future();
839  * runner.start(
840  * // Ok callback.
841  * [&run_promise]() noexcept {
842  * run_promise.set_value();
843  * },
844  * // Error callback.
845  * [&run_promise](std::exception_ptr ex) noexcept {
846  * run_promise.set_exception(std::move(ex));
847  * });
848  * // Wait while HTTP-server started (or start failed).
849  * run_future.get();
850  * @endcode
851  *
852  * @since v.0.6.7
853  */
854  template<
855  typename On_Ok_Callback,
856  typename On_Error_Callback >
857  void
859  //! A callback to be called if HTTP-server started successfully.
860  On_Ok_Callback && on_ok,
861  //! A callback to be called if HTTP-server is not started by
862  //! some reasons. Please note that this callback is passed
863  //! to http_server_t::open_async() and will be called only
864  //! for errors detected by open_async() methods.
865  //! If some error is detected outside of open_async() (for
866  //! example a failure to start a thread pool) then on_error
867  //! callback won't be called.
868  On_Error_Callback && on_error )
869  {
870  static_assert( noexcept(on_ok()), "On_Ok_Callback should be noexcept" );
871  static_assert( noexcept(on_error(std::declval<std::exception_ptr>())),
872  "On_Error_Callback should be noexcept" );
873 
875  [callback = std::move(on_ok)]() noexcept { callback(); },
876  [this, callback = std::move(on_error)]( std::exception_ptr ex ) noexcept {
877  // There is no sense to run pool.
878  m_pool.stop();
879 
880  callback( std::move(ex) );
881  } );
882 
883  m_pool.start();
884  }
885 
886  //! Start the server.
887  /*!
888  * It just a shorthand for a version of `start` method with callbacks
889  * where all callbacks to nothing.
890  */
891  void
893  {
894  this->start(
895  []() noexcept { /* nothing to do */ },
896  []( std::exception_ptr ) noexcept { /* nothing to do */ } );
897  }
898 
899  //! Is server started.
900  bool
901  started() const noexcept { return m_pool.started(); }
902 
903  //! Stop the server.
904  /*!
905  * This method stops the server by calling http_server_t::close_async()
906  * It means that stop will be performed asynchronously. To wait for the
907  * completion of stop operation the wait() method has to be used.
908  *
909  * The simple usage:
910  * @code
911  * using my_http_server = restinio::http_server_t<some_traits>;
912  *
913  * my_http_server server{...};
914  * restinio::on_pool_runner_t<my_http_server> runner{16, server};
915  *
916  * runner.start(...);
917  *
918  * ...
919  * // Some time later.
920  * runner.stop();
921  *
922  * ... // Some other actions.
923  * // Have to wait the completion of the stop() operation.
924  * runner.wait();
925  * @endcode
926  *
927  * This method accepts @a error_cb callback that will be called
928  * if an exception is thrown in http_server_t::close_async().
929  *
930  * The @a error_cb is an optional parameter, an instance of
931  * abort_app_in_error_callback_t is used by default. It means that
932  * if an exception is thrown on http_server_t::close_async() then
933  * the whole application will be terminated. If such behavior is not
934  * desirable a user has to provide own error callback:
935  * @code
936  * using my_http_server = restinio::http_server_t<some_traits>;
937  *
938  * my_http_server server{...};
939  * restinio::on_pool_runner_t<my_http_server> runner{16, server};
940  *
941  * runner.start(...);
942  *
943  * ...
944  * // Some time later.
945  * runner.stop([](std::exception_ptr ex) {
946  * ... // Some handling of an exception.
947  * });
948  * @endcode
949  * But it's important to note that if an exception is thrown inside
950  * http_server_t::close_async() then the instance of http_server_t
951  * is in undefined state.
952  *
953  * @note
954  * This method is noexcept since v.0.6.7
955  *
956  * @tparam Error_CB Type of the callback to be used if an exception
957  * is thrown inside http_server_t::close_async(). This callback
958  * should be noexcept functor (however, the noexceptness is not
959  * checked at the compile-time to have a possibility to use
960  * std::function as error callback). See abort_app_in_error_callback_t
961  * for a prototype of Error_CB functor.
962  */
963  template< typename Error_CB = abort_app_in_error_callback_t >
964  void
965  stop( Error_CB error_cb = Error_CB{} ) noexcept
966  {
967  // NOTE: m_pool.stop() call be called only inside lambda-functions
968  // because they may be executed some time later after the return
969  // from close_async().
971  [this]() noexcept {
972  // Stop running io_service.
973  m_pool.stop();
974  },
975  [this, callback = std::move(error_cb)]( std::exception_ptr ex ) noexcept {
976  // Stop running io_service anyway.
977  m_pool.stop();
978 
979  // We have to call error_cb in this case.
980  callback( std::move(ex) );
981  } );
982  }
983 
984  //! Wait for full stop of the server.
985  /*!
986  * @note
987  * This method is noexcept since v.0.6.7
988  */
989  void
990  wait() noexcept { m_pool.wait(); }
991 };
992 
993 // Forward declaration.
994 // It's necessary for running_server_handle_t.
995 template< typename Http_Server >
996 class running_server_instance_t;
997 
998 //
999 // running_server_handle_t
1000 //
1001 /*!
1002  * @brief The type to be used as a handle for running server instance.
1003  *
1004  * The handle should be seen as a Moveable and not Copyable type.
1005  *
1006  * @since v.0.6.7
1007  */
1008 template< typename Traits >
1011 
1012 //
1013 // running_server_instance_t
1014 //
1015 /*!
1016  * @brief A helper class used in an implementation of #run_async function.
1017  *
1018  * An instance of that class holds an HTTP-server and thread pool on that
1019  * this HTTP-server is launched.
1020  *
1021  * The HTTP-server will automatically be stopped in the destructor.
1022  * However, a user can stop the HTTP-server manually by using
1023  * stop() and wait() methods.
1024  *
1025  * @since v.0.6.7
1026  */
1027 template< typename Http_Server >
1028 class running_server_instance_t
1029 {
1030  template< typename Traits >
1032  run_async(
1036 
1037  //! Actual server instance.
1038  Http_Server m_server;
1039 
1040  //! The runner of the server.
1041  on_pool_runner_t< Http_Server > m_runner;
1042 
1043  //! Initializing constructor.
1045  io_context_holder_t io_context,
1046  server_settings_t< typename Http_Server::traits_t > && settings,
1047  std::size_t thread_pool_size )
1048  : m_server{ std::move(io_context), std::move(settings) }
1049  , m_runner{ thread_pool_size, m_server }
1050  {}
1051 
1052 
1053  //! Start the HTTP-server.
1054  /*!
1055  * Returns when HTTP-server started or some startup failure detected.
1056  * It means that the caller thread will be blocked until HTTP-server
1057  * calls on_ok or on_error callback.
1058  *
1059  * Throws an exception on an error.
1060  */
1061  void
1063  {
1064  std::promise<void> p;
1065  auto f = p.get_future();
1066  m_runner.start(
1067  [&p]() noexcept { p.set_value(); },
1068  [&p]( std::exception_ptr ex ) noexcept {
1069  p.set_exception( std::move(ex) );
1070  } );
1071  f.get();
1072  }
1073 
1074 public :
1075  /*!
1076  * Stop the HTTP-server.
1077  *
1078  * This method initiates shutdown procedure that can take some
1079  * time. But stop() returns without the waiting for the completeness
1080  * of the shutdown. To wait for the completeness use wait() method:
1081  *
1082  * @code
1083  * auto server = restinio::run_async(...);
1084  * ...
1085  * server->stop(); // Returns without the waiting.
1086  * ... // Some other actions.
1087  * server->wait(); // Returns only when HTTP-server stopped.
1088  * @endcode
1089  *
1090  * @attention
1091  * The current version doesn't guarantee that stop() can be called
1092  * safely several times. Please take care of that and call stop()
1093  * only once.
1094  */
1095  void
1096  stop() noexcept
1097  {
1098  m_runner.stop();
1099  }
1100 
1101  /*!
1102  * @brief Wait for the shutdown of HTTP-server.
1103  *
1104  * @note
1105  * Method stop() should be called before the call to wait():
1106  * @code
1107  * auto server = restinio::run_async(...);
1108  * ...
1109  * server->stop(); // Initiates the shutdown and returns without the waiting.
1110  * server->wait(); // Returns only when HTTP-server stopped.
1111  * @endcode
1112  *
1113  * @attention
1114  * The current version doesn't guarantee that wait() can be called
1115  * safely several times. Please take care of that and call wait()
1116  * only once.
1117  */
1118  void
1119  wait() noexcept
1120  {
1121  m_runner.wait();
1122  }
1123 };
1124 
1125 //
1126 // run_async
1127 //
1128 /*!
1129  * @brief Creates an instance of HTTP-server and launches it on a
1130  * separate thread or thread pool.
1131  *
1132  * Usage example:
1133  * @code
1134  * int main() {
1135  * auto server = restinio::run_async(
1136  * // Asio's io_context to be used.
1137  * // HTTP-server will use own Asio's io_context object.
1138  * restinio::own_io_context(),
1139  * // The settings for the HTTP-server.
1140  * restinio::server_settings_t{}
1141  * .address("127.0.0.1")
1142  * .port(8080)
1143  * .request_handler(...),
1144  * // The size of thread-pool for the HTTP-server.
1145  * 16);
1146  * // If we are here and run_async doesn't throw then HTTP-server
1147  * // is started.
1148  *
1149  * ... // Some other actions.
1150  *
1151  * // No need to stop HTTP-server manually. It will be automatically
1152  * // stopped in the destructor of `server` object.
1153  * }
1154  * @endcode
1155  * Or, if user-defined traits should be used:
1156  * @code
1157  * int main() {
1158  * struct my_traits : public restinio::default_traits_t {
1159  * ...
1160  * };
1161  *
1162  * auto server = restinio::run_async<my_traits>(
1163  * restinio::own_io_context(),
1164  * restinio::server_settings_t<my_traits>{}
1165  * .address(...)
1166  * .port(...)
1167  * .request_handler(...),
1168  * // Use just one thread for the HTTP-server.
1169  * 1u);
1170  *
1171  * ... // Some other actions.
1172  * }
1173  * @endcode
1174  *
1175  * run_async() returns control when HTTP-server is started or some
1176  * startup failure is detected. But if a failure is detected then an
1177  * exception is thrown. So if run_async() returns successfuly then
1178  * HTTP-server is working.
1179  *
1180  * The started HTTP-server will be automatically stopped at the
1181  * destruction of the returned value. Because of that the returned
1182  * value should be stored for the time while HTTP-server is needed.
1183  *
1184  * The started HTTP-server can be stopped manually by calling
1185  * stop() and wait() methods:
1186  * @code
1187  * auto server = restinio::run_async(...);
1188  * ...
1189  * server->stop(); // Returns without the waiting.
1190  * ... // Some other actions.
1191  * server->wait(); // Returns only when HTTP-server stopped.
1192  * @endcode
1193  *
1194  * @since v.0.6.7
1195  */
1196 template< typename Traits = default_traits_t >
1197 [[nodiscard]]
1203 {
1206  std::move(io_context),
1207  std::move(settings),
1209  };
1210 
1211  handle->start();
1212 
1213  return handle;
1214 }
1215 
1216 } /* 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 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.
void wait() noexcept
Wait for the shutdown of HTTP-server.
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...
Http_Server m_server
Actual server instance.
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.
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
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.
running_server_instance_t(io_context_holder_t io_context, server_settings_t< typename Http_Server::traits_t > &&settings, std::size_t thread_pool_size)
Initializing constructor.
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 wait() noexcept
Wait for full stop of the server.
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?
void operator()(std::exception_ptr) const noexcept
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
Type of a function to be used as the default on_error-callback.
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.
running_server_handle_t< Traits > run_async(io_context_holder_t io_context, server_settings_t< Traits > &&settings, std::size_t thread_pool_size)
Creates an instance of HTTP-server and launches it on a separate thread or thread pool...
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 start(On_Ok_Callback &&on_ok, On_Error_Callback &&on_error)
Start the server with callbacks that will be called on success or failure.
void start()
Start the HTTP-server.
void stop(Error_CB error_cb=Error_CB{}) noexcept
Stop the server.
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
on_pool_runner_t< Http_Server > m_runner
The runner of the server.
http_server_t< Traits > & server() const noexcept
impl::ioctx_on_thread_pool_t< impl::external_io_context_for_thread_pool_t > m_pool
Thread pool for running the server.