RESTinio
Loading...
Searching...
No Matches
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#if defined(RESTINIO_DEFAULT_BREAK_SIGNALS_LIST)
17#error "RESTINIO_DEFAULT_BREAK_SIGNALS_LIST symbol should not be defined by user"
18#else
19#define RESTINIO_DEFAULT_BREAK_SIGNALS_LIST SIGINT,SIGTERM
20#endif
21
22namespace restinio
23{
24
25//
26// break_signal_handling_t
27//
28/*!
29 * @brief Indication of usage of break signal handlers for some forms
30 * of run functions.
31 *
32 * @since v.0.5.1
33 */
35{
36 //! Signal handler should be used by run() function.
38 //! Signal handler should not be used by run() function.
40};
41
42/*!
43 * @brief Make the indicator for usage of break signal handler.
44 *
45 * Usage example:
46 * @code
47 * restinio::run( restinio::on_thread_pool(
48 * std::thread::hardware_concurrency(),
49 * restinio::use_break_signal_handling(),
50 * my_server) );
51 * @endcode
52 *
53 * @since v.0.5.1
54 */
55inline constexpr break_signal_handling_t
60
61/*!
62 * @brief Make the indicator for absence of break signal handler.
63 *
64 * Usage example:
65 * @code
66 * restinio::run( restinio::on_thread_pool(
67 * std::thread::hardware_concurrency(),
68 * restinio::skip_break_signal_handling(),
69 * my_server) );
70 * @endcode
71 *
72 * @since v.0.5.1
73 */
74inline constexpr break_signal_handling_t
79
80//
81// run_on_this_thread_settings_t
82//
83/*!
84 * \brief Settings for the case when http_server must be run
85 * on the context of the current thread.
86 *
87 * \note
88 * Shouldn't be used directly. Only as result of on_this_thread()
89 * function as parameter for run().
90 */
91template<typename Traits>
92class run_on_this_thread_settings_t final
94 run_on_this_thread_settings_t<Traits>,
95 Traits>
96{
98 run_on_this_thread_settings_t<Traits>, Traits>;
99public:
100 // Inherit constructors from base class.
102};
103
104//
105// on_this_thread
106//
107/*!
108 * \brief A special marker for the case when http_server must be
109 * run on the context of the current thread.
110 *
111 * Usage example:
112 * \code
113 * // Run with the default traits.
114 * run( restinio::on_this_thread()
115 * .port(8080)
116 * .address("localhost")
117 * .request_handler(...) );
118 * \endcode
119 * For a case when some custom traits must be used:
120 * \code
121 * run( restinio::on_this_thread<my_server_traits_t>()
122 * .port(8080)
123 * .address("localhost")
124 * .request_handler(...) );
125 * \endcode
126 */
127template<typename Traits = default_single_thread_traits_t>
128run_on_this_thread_settings_t<Traits>
129on_this_thread() { return run_on_this_thread_settings_t<Traits>{}; }
130
131//
132// run_on_thread_pool_settings_t
133//
134/*!
135 * \brief Settings for the case when http_server must be run
136 * on the context of the current thread.
137 *
138 * \note
139 * Shouldn't be used directly. Only as result of on_thread_pool()
140 * function as parameter for run().
141 */
142template<typename Traits>
143class run_on_thread_pool_settings_t final
145 run_on_thread_pool_settings_t<Traits>,
146 Traits>
147{
148 //! Size of the pool.
149 std::size_t m_pool_size;
150
151public:
152 //! Constructor.
154 //! Size of the pool.
155 std::size_t pool_size )
156 : m_pool_size(pool_size)
157 {}
158
159 //! Get the pool size.
160 std::size_t
161 pool_size() const { return m_pool_size; }
162};
163
164//
165// on_thread_pool
166//
167/*!
168 * \brief A special marker for the case when http_server must be
169 * run on an thread pool.
170 *
171 * Usage example:
172 * \code
173 * // Run with the default traits.
174 * run( restinio::on_thread_pool(16) // 16 -- is the pool size.
175 * .port(8080)
176 * .address("localhost")
177 * .request_handler(...) );
178 * \endcode
179 * For a case when some custom traits must be used:
180 * \code
181 * run( restinio::on_thread_pool<my_server_traits_t>(16)
182 * .port(8080)
183 * .address("localhost")
184 * .request_handler(...) );
185 * \endcode
186 */
187template<typename Traits = default_traits_t>
188run_on_thread_pool_settings_t<Traits>
190 //! Size of the pool.
191 std::size_t pool_size )
192{
193 return run_on_thread_pool_settings_t<Traits>( pool_size );
194}
195
196//
197// run()
198//
199
200
201//! Helper function for running http server until ctrl+c is hit.
202/*!
203 * Can be useful when RESTinio server should be run on the user's
204 * own io_context instance.
205 *
206 * For example:
207 * \code
208 * asio::io_context iosvc;
209 * ... // iosvc used by user.
210 * restinio::run(iosvc,
211 * restinio::on_this_thread<my_traits>()
212 * .port(8080)
213 * .address("localhost")
214 * .request_handler([](auto req) {...}));
215 * \endcode
216 *
217 * \since
218 * v.0.4.2
219 */
220template<typename Traits>
221inline void
223 //! Asio's io_context to be used.
224 //! Note: this reference should remain valid until RESTinio server finished.
225 asio_ns::io_context & ioctx,
226 //! Settings for that server instance.
227 run_on_this_thread_settings_t<Traits> && settings )
228{
229 using settings_t = run_on_this_thread_settings_t<Traits>;
230 using server_t = http_server_t<Traits>;
231
232 server_t server{
234 std::forward<settings_t>(settings) };
235
236 std::exception_ptr exception_caught;
237
238 asio_ns::signal_set break_signals{
239 server.io_context(),
241 };
242 break_signals.async_wait(
243 [&]( const asio_ns::error_code & ec, int ){
244 if( !ec )
245 {
246 server.close_async(
247 [&]{
248 // Stop running io_service.
249 ioctx.stop();
250 },
251 [&exception_caught]( std::exception_ptr ex ){
252 // We can't throw an exception here!
253 // Store it to rethrow later.
254 exception_caught = ex;
255 } );
256 }
257 } );
258
259 server.open_async(
260 []{ /* Ok. */},
261 [&ioctx, &exception_caught]( std::exception_ptr ex ){
262 // Stop running io_service.
263 // We can't throw an exception here!
264 // Store it to rethrow later.
265 ioctx.stop();
266 exception_caught = ex;
267 } );
268
269 ioctx.run();
270
271 // If an error was detected it should be propagated.
272 if( exception_caught )
273 std::rethrow_exception( exception_caught );
274}
275
276//! Helper function for running http server until ctrl+c is hit.
277/*!
278 * This function creates its own instance of Asio's io_context and
279 * uses it exclusively.
280 *
281 * Usage example:
282 * \code
283 * restinio::run(
284 * restinio::on_this_thread<my_traits>()
285 * .port(8080)
286 * .address("localhost")
287 * .request_handler([](auto req) {...}));
288 * \endcode
289 */
290template<typename Traits>
291inline void
293 run_on_this_thread_settings_t<Traits> && settings )
294{
295 asio_ns::io_context io_context;
296 run( io_context, std::move(settings) );
297}
298
299namespace impl {
300
301/*!
302 * \brief An implementation of run-function for thread pool case.
303 *
304 * This function receives an already created thread pool object and
305 * creates and runs http-server on this thread pool.
306 *
307 * \since
308 * v.0.4.2
309 */
310template<typename Io_Context_Holder, typename Traits>
311void
313 ioctx_on_thread_pool_t<Io_Context_Holder> & pool,
314 run_on_thread_pool_settings_t<Traits> && settings )
315{
316 using settings_t = run_on_thread_pool_settings_t<Traits>;
317 using server_t = http_server_t<Traits>;
318
319 server_t server{
320 restinio::external_io_context( pool.io_context() ),
321 std::forward<settings_t>(settings) };
322
323 std::exception_ptr exception_caught;
324
325 asio_ns::signal_set break_signals{
326 server.io_context(),
328 };
329 break_signals.async_wait(
330 [&]( const asio_ns::error_code & ec, int ){
331 if( !ec )
332 {
333 server.close_async(
334 [&]{
335 // Stop running io_service.
336 pool.stop();
337 },
338 [&exception_caught]( std::exception_ptr ex ){
339 // We can't throw an exception here!
340 // Store it to rethrow later.
341 exception_caught = ex;
342 } );
343 }
344 } );
345
346 server.open_async(
347 []{ /* Ok. */},
348 [&pool, &exception_caught]( std::exception_ptr ex ){
349 // Stop running io_service.
350 // We can't throw an exception here!
351 // Store it to rethrow later.
352 pool.stop();
353 exception_caught = ex;
354 } );
355
356 pool.start();
357 pool.wait();
358
359 // If an error was detected it should be propagated.
360 if( exception_caught )
361 std::rethrow_exception( exception_caught );
362}
363
364} /* namespace impl */
365
366//! Helper function for running http server until ctrl+c is hit.
367/*!
368 * This function creates its own instance of Asio's io_context and
369 * uses it exclusively.
370 *
371 * Usage example:
372 * \code
373 * restinio::run(
374 * restinio::on_thread_pool<my_traits>(4)
375 * .port(8080)
376 * .address("localhost")
377 * .request_handler([](auto req) {...}));
378 * \endcode
379 */
380template<typename Traits>
381inline void
382run( run_on_thread_pool_settings_t<Traits> && settings )
383{
384 using thread_pool_t = impl::ioctx_on_thread_pool_t<
386
387 thread_pool_t pool( settings.pool_size() );
388
389 impl::run( pool, std::move(settings) );
390}
391
392//! Helper function for running http server until ctrl+c is hit.
393/*!
394 * Can be useful when RESTinio server should be run on the user's
395 * own io_context instance.
396 *
397 * For example:
398 * \code
399 * asio::io_context iosvc;
400 * ... // iosvc used by user.
401 * restinio::run(iosvc,
402 * restinio::on_thread_pool<my_traits>(4)
403 * .port(8080)
404 * .address("localhost")
405 * .request_handler([](auto req) {...}));
406 * \endcode
407 *
408 * \since
409 * v.0.4.2
410 */
411template<typename Traits>
412inline void
414 //! Asio's io_context to be used.
415 //! Note: this reference should remain valid until RESTinio server finished.
416 asio_ns::io_context & ioctx,
417 //! Settings for that server instance.
418 run_on_thread_pool_settings_t<Traits> && settings )
419{
420 using thread_pool_t = impl::ioctx_on_thread_pool_t<
422
423 thread_pool_t pool{ settings.pool_size(), ioctx };
424
425 impl::run( pool, std::move(settings) );
426}
427
428//
429// run_existing_server_on_thread_pool_t
430//
431/*!
432 * @brief Helper type for holding parameters necessary for running
433 * HTTP-server on a thread pool.
434 *
435 * @note This class is not intended for direct use. It is used by
436 * RESTinio itself.
437 *
438 * @since v.0.5.1
439 */
440template<typename Traits>
442{
443 //! Size of thread pool.
444 std::size_t m_pool_size;
445 //! Should break signal handler be used?
447 //! HTTP-server to be used on a thread pool.
448 /*!
449 * We assume that this pointer will be valid pointer.
450 */
452
453public:
454 //! Initializing constructor.
456 //! Size of the pool.
457 std::size_t pool_size,
458 //! Should break signal handler be used?
459 break_signal_handling_t break_handling,
460 //! A reference to HTTP-server to be run on a thread pool.
461 //! This reference should outlive an instance of
462 //! run_existing_server_on_thread_pool_t.
463 http_server_t<Traits> & server )
464 : m_pool_size{ pool_size }
465 , m_break_handling{ break_handling }
466 , m_server{ &server }
467 {}
468
469 std::size_t
470 pool_size() const noexcept { return m_pool_size; }
471
473 break_handling() const noexcept { return m_break_handling; }
474
475 http_server_t<Traits> &
476 server() const noexcept { return *m_server; }
477};
478
479/*!
480 * @brief Helper function for running an existing HTTP-server on
481 * a thread pool.
482 *
483 * Usage example:
484 * @code
485 * using my_server_t = restinio::http_server_t< my_server_traits_t >;
486 * my_server_t server{
487 * restinio::own_io_context(),
488 * [](auto & settings) {
489 * settings.port(...);
490 * settings.address(...);
491 * settings.request_handler(...);
492 * ...
493 * }
494 * };
495 * ...
496 * restinio::run( restinio::on_thread_pool(
497 * std::thread::hardware_concurrency(),
498 * restinio::use_break_signal_handling(),
499 * server) );
500 * @endcode
501 *
502 * @since v.0.5.1
503 */
504template<typename Traits>
507 std::size_t pool_size,
508 break_signal_handling_t break_handling,
509 http_server_t<Traits> & server )
510{
511 return { pool_size, break_handling, server };
512}
513
514namespace impl {
515
516/*!
517 * \brief An implementation of run-function for thread pool case
518 * with existing http_server instance.
519 *
520 * This function receives an already created thread pool object and
521 * already created http-server and run it on this thread pool.
522 *
523 * \attention
524 * This function installs break signal handler and stops server when
525 * break signal is raised.
526 *
527 * \since
528 * v.0.5.1
529 */
530template<typename Io_Context_Holder, typename Traits>
531void
533 ioctx_on_thread_pool_t<Io_Context_Holder> & pool,
534 http_server_t<Traits> & server )
535{
536 std::exception_ptr exception_caught;
537
538 asio_ns::signal_set break_signals{
539 server.io_context(),
541 };
542 break_signals.async_wait(
543 [&]( const asio_ns::error_code & ec, int ){
544 if( !ec )
545 {
546 server.close_async(
547 [&]{
548 // Stop running io_service.
549 pool.stop();
550 },
551 [&exception_caught]( std::exception_ptr ex ){
552 // We can't throw an exception here!
553 // Store it to rethrow later.
554 exception_caught = ex;
555 } );
556 }
557 } );
558
559 server.open_async(
560 []{ /* Ok. */},
561 [&pool, &exception_caught]( std::exception_ptr ex ){
562 // Stop running io_service.
563 // We can't throw an exception here!
564 // Store it to rethrow later.
565 pool.stop();
566 exception_caught = ex;
567 } );
568
569 pool.start();
570 pool.wait();
571
572 // If an error was detected it should be propagated.
573 if( exception_caught )
574 std::rethrow_exception( exception_caught );
575}
576
577/*!
578 * \brief An implementation of run-function for thread pool case
579 * with existing http_server instance.
580 *
581 * This function receives an already created thread pool object and
582 * already created http-server and run it on this thread pool.
583 *
584 * \note
585 * This function doesn't install break signal handlers.
586 *
587 * \since
588 * v.0.5.1
589 */
590template<typename Io_Context_Holder, typename Traits>
591void
593 ioctx_on_thread_pool_t<Io_Context_Holder> & pool,
594 http_server_t<Traits> & server )
595{
596 std::exception_ptr exception_caught;
597
598 server.open_async(
599 []{ /* Ok. */},
600 [&pool, &exception_caught]( std::exception_ptr ex ){
601 // Stop running io_service.
602 // We can't throw an exception here!
603 // Store it to rethrow later.
604 pool.stop();
605 exception_caught = ex;
606 } );
607
608 pool.start();
609 pool.wait();
610
611 // If an error was detected it should be propagated.
612 if( exception_caught )
613 std::rethrow_exception( exception_caught );
614}
615
616} /* namespace impl */
617
618/*!
619 * @brief Helper function for running an existing HTTP-server on
620 * a thread pool.
621 *
622 * Usage example:
623 * @code
624 * using my_server_t = restinio::http_server_t< my_server_traits_t >;
625 * my_server_t server{
626 * restinio::own_io_context(),
627 * [](auto & settings) {
628 * settings.port(...);
629 * settings.address(...);
630 * settings.request_handler(...);
631 * ...
632 * }
633 * };
634 * ...
635 * // run() returns if Ctrl+C is pressed or if HTTP-server will
636 * // be shut down from elsewhere.
637 * restinio::run( restinio::on_thread_pool(
638 * std::thread::hardware_concurrency(),
639 * restinio::use_break_signal_handling(),
640 * server) );
641 * @endcode
642 *
643 * @since v.0.5.1
644 */
645template<typename Traits>
646inline void
648{
649 using thread_pool_t = impl::ioctx_on_thread_pool_t<
651
652 thread_pool_t pool{ params.pool_size(), params.server().io_context() };
653
654 if( break_signal_handling_t::used == params.break_handling() )
655 impl::run_with_break_signal_handling( pool, params.server() );
656 else
657 impl::run_without_break_signal_handling( pool, params.server() );
658}
659
660//
661// initiate_shutdown
662//
663/*!
664 * @brief Helper function for initiation of server shutdown.
665 *
666 * Can be useful if an existing HTTP-server is run via run() function.
667 * For example:
668 * @code
669 * restinio::http_server_t< my_traits > server{ ... };
670 * // Launch another thread that will perform some application logic.
671 * std::thread app_logic_thread{ [&server] {
672 * while(some_condition) {
673 * ...
674 * if(exit_case) {
675 * // HTTP-server should be shut down.
676 * restinio::initiate_shutdown( server );
677 * // Our work should be finished.
678 * return;
679 * }
680 * }
681 * } };
682 * // Start HTTP-server. The current thread will be blocked until
683 * // run() returns.
684 * restinio::run( restinio::on_thread_pool(
685 * 4,
686 * restinio::skip_break_signal_handling(),
687 * server) );
688 * // Now app_logic_thread can be joined.
689 * app_logic_thread.join();
690 * @endcode
691 *
692 * @since v.0.5.1
693 */
694template<typename Traits>
695inline void
697{
698 asio_ns::post(
699 server.io_context(),
700 [&server] {
701 server.close_sync();
702 server.io_context().stop();
703 } );
704}
705
706/*!
707 * @brief Type of a function to be used as the default on_error-callback.
708 *
709 * Since v.0.7.0 on_pool_runner_t::stop() accept a on_error callback that
710 * will be passed to http_server_t::close_async() and will be called if
711 * an exception is thrown in http_server_t::close_async().
712 * This callback should perform some actions that can help the application
713 * to handle the problem.
714 *
715 * This type is intended to be used as the default on_error callback.
716 *
717 * If an exception in thrown inside http_server_t::close_async() then
718 * the application is in undefined state, it's unknown what can be done
719 * with http_server_t instance and whan can't be.
720 *
721 * Therefore the default on_error callback simply calls std::abort() to
722 * terminate the application and avoid the work in undefined state.
723 *
724 * If such behavour is not desirable the user can provide own
725 * on_error callback.
726 *
727 * @since v.0.7.0
728 */
730{
731 /*!
732 * @attention
733 * It just calls std::abort().
734 */
735 [[noreturn]]
736 void
737 operator()( std::exception_ptr /*ex*/ ) const noexcept
738 {
739 std::abort();
740 }
741};
742
743//
744// on_pool_runner_t
745//
746/*!
747 * @brief Helper class for running an existing HTTP-server on a thread pool
748 * without blocking the current thread.
749 *
750 * Usage of run() functions has some drawbacks. For example, the current thread
751 * on that run() is called, will be blocked until run() returns.
752 *
753 * Sometimes it is not appropriate and leads to tricks like that:
754 * @code
755 * // HTTP-server to be run on a thread pool.
756 * restinio::http_server_t< my_traits > server{...};
757 *
758 * // Separate worker thread for calling restinio::run().
759 * std::thread run_thread{ [&server] {
760 * restinio::run( restinio::on_thread_pool(
761 * 16,
762 * restinio::skip_break_signal_handling(),
763 * server) );
764 * // Now this thread is blocked until HTTP-server will be finished.
765 * } };
766 *
767 * ... // Some application specific code here.
768 *
769 * // Now the server can be stopped.
770 * restinio::initiate_shutdown( server );
771 * run_thread.join();
772 * @endcode
773 *
774 * Writing such code is a boring and error-prone task. The class
775 * on_pool_runner_t can be used instead:
776 * @code
777 * // HTTP-server to be run on a thread pool.
778 * restinio::http_server_t< my_traits > server{...};
779 *
780 * // Launch HTTP-server on a thread pool.
781 * restinio::on_pool_runner_t< restinio::http_server_t<my_traits> > runner{
782 * 16,
783 * server
784 * };
785 * runner.start();
786 *
787 * ... // Some application specific code here.
788 *
789 * // Now the server can be stopped.
790 * runner.stop(); // (1)
791 * runner.wait();
792 * @endcode
793 *
794 * Moreover the code at point (1) in the example above it not necessary
795 * because on_pool_runner_t automatically stops the server in the destructor.
796 *
797 * @since v.0.5.1
798 */
799template<typename Http_Server>
801{
802 //! HTTP-server to be run.
803 Http_Server & m_server;
804
805 //! Thread pool for running the server.
808
809public :
812
813 //! Initializing constructor.
815 //! Size of thread pool.
816 std::size_t pool_size,
817 //! Server instance to be run.
818 //! NOTE. This reference must be valid for all life-time
819 //! of on_pool_runner instance.
820 Http_Server & server )
821 : m_server{ server }
823 {}
824
825 /*!
826 * @brief Start the server with callbacks that will be called on
827 * success or failure.
828 *
829 * The @a on_ok should be a function/functor with the format:
830 * @code
831 * void () noexcept;
832 * @endcode
833 *
834 * The @a on_error should be a function/functor with the format:
835 * @code
836 * void (std::exception_ptr) noexcept;
837 * @endcode
838 *
839 * @note
840 * Both callbacks will be passed to http_server_t::open_async method.
841 * It means that @a on_error callback will be called for errors detected
842 * by open_async() methods.
843 *
844 * @attention
845 * Both callbacks should be noexcept functions/functors.
846 *
847 * Usage example:
848 * @code
849 * using my_http_server = restinio::http_server_t<some_traits>;
850 *
851 * my_http_server server{...};
852 * restinio::on_pool_runner_t<my_http_server> runner{16, server};
853 *
854 * std::promise<void> run_promise;
855 * auto run_future = run_promise.get_future();
856 * runner.start(
857 * // Ok callback.
858 * [&run_promise]() noexcept {
859 * run_promise.set_value();
860 * },
861 * // Error callback.
862 * [&run_promise](std::exception_ptr ex) noexcept {
863 * run_promise.set_exception(std::move(ex));
864 * });
865 * // Wait while HTTP-server started (or start failed).
866 * run_future.get();
867 * @endcode
868 *
869 * @since v.0.6.7
870 */
871 template<
872 typename On_Ok_Callback,
873 typename On_Error_Callback >
874 void
876 //! A callback to be called if HTTP-server started successfully.
877 On_Ok_Callback && on_ok,
878 //! A callback to be called if HTTP-server is not started by
879 //! some reasons. Please note that this callback is passed
880 //! to http_server_t::open_async() and will be called only
881 //! for errors detected by open_async() methods.
882 //! If some error is detected outside of open_async() (for
883 //! example a failure to start a thread pool) then on_error
884 //! callback won't be called.
885 On_Error_Callback && on_error )
886 {
887 static_assert( noexcept(on_ok()), "On_Ok_Callback should be noexcept" );
888 static_assert( noexcept(on_error(std::declval<std::exception_ptr>())),
889 "On_Error_Callback should be noexcept" );
890
891 m_server.open_async(
892 [callback = std::move(on_ok)]() noexcept { callback(); },
893 [this, callback = std::move(on_error)]( std::exception_ptr ex ) noexcept {
894 // There is no sense to run pool.
895 m_pool.stop();
896
897 callback( std::move(ex) );
898 } );
899
900 m_pool.start();
901 }
902
903 //! Start the server.
904 /*!
905 * It just a shorthand for a version of `start` method with callbacks
906 * where all callbacks to nothing.
907 */
908 void
910 {
911 this->start(
912 []() noexcept { /* nothing to do */ },
913 []( std::exception_ptr ) noexcept { /* nothing to do */ } );
914 }
915
916 //! Is server started.
917 bool
918 started() const noexcept { return m_pool.started(); }
919
920 //! Stop the server.
921 /*!
922 * This method stops the server by calling http_server_t::close_async()
923 * It means that stop will be performed asynchronously. To wait for the
924 * completion of stop operation the wait() method has to be used.
925 *
926 * The simple usage:
927 * @code
928 * using my_http_server = restinio::http_server_t<some_traits>;
929 *
930 * my_http_server server{...};
931 * restinio::on_pool_runner_t<my_http_server> runner{16, server};
932 *
933 * runner.start(...);
934 *
935 * ...
936 * // Some time later.
937 * runner.stop();
938 *
939 * ... // Some other actions.
940 * // Have to wait the completion of the stop() operation.
941 * runner.wait();
942 * @endcode
943 *
944 * This method accepts @a error_cb callback that will be called
945 * if an exception is thrown in http_server_t::close_async().
946 *
947 * The @a error_cb is an optional parameter, an instance of
948 * abort_app_in_error_callback_t is used by default. It means that
949 * if an exception is thrown on http_server_t::close_async() then
950 * the whole application will be terminated. If such behavior is not
951 * desirable a user has to provide own error callback:
952 * @code
953 * using my_http_server = restinio::http_server_t<some_traits>;
954 *
955 * my_http_server server{...};
956 * restinio::on_pool_runner_t<my_http_server> runner{16, server};
957 *
958 * runner.start(...);
959 *
960 * ...
961 * // Some time later.
962 * runner.stop([](std::exception_ptr ex) {
963 * ... // Some handling of an exception.
964 * });
965 * @endcode
966 * But it's important to note that if an exception is thrown inside
967 * http_server_t::close_async() then the instance of http_server_t
968 * is in undefined state.
969 *
970 * @note
971 * This method is noexcept since v.0.6.7
972 *
973 * @tparam Error_CB Type of the callback to be used if an exception
974 * is thrown inside http_server_t::close_async(). This callback
975 * should be noexcept functor (however, the noexceptness is not
976 * checked at the compile-time to have a possibility to use
977 * std::function as error callback). See abort_app_in_error_callback_t
978 * for a prototype of Error_CB functor.
979 */
980 template< typename Error_CB = abort_app_in_error_callback_t >
981 void
982 stop( Error_CB error_cb = Error_CB{} ) noexcept
983 {
984 // NOTE: m_pool.stop() call be called only inside lambda-functions
985 // because they may be executed some time later after the return
986 // from close_async().
987 m_server.close_async(
988 [this]() noexcept {
989 // Stop running io_service.
990 m_pool.stop();
991 },
992 [this, callback = std::move(error_cb)]( std::exception_ptr ex ) noexcept {
993 // Stop running io_service anyway.
994 m_pool.stop();
995
996 // We have to call error_cb in this case.
997 callback( std::move(ex) );
998 } );
999 }
1000
1001 //! Wait for full stop of the server.
1002 /*!
1003 * @note
1004 * This method is noexcept since v.0.6.7
1005 */
1006 void
1007 wait() noexcept { m_pool.wait(); }
1008};
1009
1010// Forward declaration.
1011// It's necessary for running_server_handle_t.
1012template< typename Http_Server >
1014
1015//
1016// running_server_handle_t
1017//
1018/*!
1019 * @brief The type to be used as a handle for running server instance.
1020 *
1021 * The handle should be seen as a Moveable and not Copyable type.
1022 *
1023 * @since v.0.6.7
1024 */
1025template< typename Traits >
1028
1029//
1030// running_server_instance_t
1031//
1032/*!
1033 * @brief A helper class used in an implementation of #run_async function.
1034 *
1035 * An instance of that class holds an HTTP-server and thread pool on that
1036 * this HTTP-server is launched.
1037 *
1038 * The HTTP-server will automatically be stopped in the destructor.
1039 * However, a user can stop the HTTP-server manually by using
1040 * stop() and wait() methods.
1041 *
1042 * @since v.0.6.7
1043 */
1044template< typename Http_Server >
1046{
1047 template< typename Traits >
1049 run_async(
1051 server_settings_t<Traits> &&,
1052 std::size_t thread_pool_size );
1053
1054 //! Actual server instance.
1055 Http_Server m_server;
1056
1057 //! The runner of the server.
1059
1060 //! Initializing constructor.
1062 io_context_holder_t io_context,
1063 server_settings_t< typename Http_Server::traits_t > && settings,
1064 std::size_t thread_pool_size )
1065 : m_server{ std::move(io_context), std::move(settings) }
1066 , m_runner{ thread_pool_size, m_server }
1067 {}
1068
1069
1070 //! Start the HTTP-server.
1071 /*!
1072 * Returns when HTTP-server started or some startup failure detected.
1073 * It means that the caller thread will be blocked until HTTP-server
1074 * calls on_ok or on_error callback.
1075 *
1076 * Throws an exception on an error.
1077 */
1078 void
1080 {
1081 std::promise<void> p;
1082 auto f = p.get_future();
1083 m_runner.start(
1084 [&p]() noexcept { p.set_value(); },
1085 [&p]( std::exception_ptr ex ) noexcept {
1086 p.set_exception( std::move(ex) );
1087 } );
1088 f.get();
1089 }
1090
1091public :
1092 /*!
1093 * Stop the HTTP-server.
1094 *
1095 * This method initiates shutdown procedure that can take some
1096 * time. But stop() returns without the waiting for the completeness
1097 * of the shutdown. To wait for the completeness use wait() method:
1098 *
1099 * @code
1100 * auto server = restinio::run_async(...);
1101 * ...
1102 * server->stop(); // Returns without the waiting.
1103 * ... // Some other actions.
1104 * server->wait(); // Returns only when HTTP-server stopped.
1105 * @endcode
1106 *
1107 * @attention
1108 * The current version doesn't guarantee that stop() can be called
1109 * safely several times. Please take care of that and call stop()
1110 * only once.
1111 */
1112 void
1113 stop() noexcept
1114 {
1115 m_runner.stop();
1116 }
1117
1118 /*!
1119 * @brief Wait for the shutdown of HTTP-server.
1120 *
1121 * @note
1122 * Method stop() should be called before the call to wait():
1123 * @code
1124 * auto server = restinio::run_async(...);
1125 * ...
1126 * server->stop(); // Initiates the shutdown and returns without the waiting.
1127 * server->wait(); // Returns only when HTTP-server stopped.
1128 * @endcode
1129 *
1130 * @attention
1131 * The current version doesn't guarantee that wait() can be called
1132 * safely several times. Please take care of that and call wait()
1133 * only once.
1134 */
1135 void
1136 wait() noexcept
1137 {
1138 m_runner.wait();
1139 }
1140};
1141
1142//
1143// run_async
1144//
1145/*!
1146 * @brief Creates an instance of HTTP-server and launches it on a
1147 * separate thread or thread pool.
1148 *
1149 * Usage example:
1150 * @code
1151 * int main() {
1152 * auto server = restinio::run_async(
1153 * // Asio's io_context to be used.
1154 * // HTTP-server will use own Asio's io_context object.
1155 * restinio::own_io_context(),
1156 * // The settings for the HTTP-server.
1157 * restinio::server_settings_t{}
1158 * .address("127.0.0.1")
1159 * .port(8080)
1160 * .request_handler(...),
1161 * // The size of thread-pool for the HTTP-server.
1162 * 16);
1163 * // If we are here and run_async doesn't throw then HTTP-server
1164 * // is started.
1165 *
1166 * ... // Some other actions.
1167 *
1168 * // No need to stop HTTP-server manually. It will be automatically
1169 * // stopped in the destructor of `server` object.
1170 * }
1171 * @endcode
1172 * Or, if user-defined traits should be used:
1173 * @code
1174 * int main() {
1175 * struct my_traits : public restinio::default_traits_t {
1176 * ...
1177 * };
1178 *
1179 * auto server = restinio::run_async<my_traits>(
1180 * restinio::own_io_context(),
1181 * restinio::server_settings_t<my_traits>{}
1182 * .address(...)
1183 * .port(...)
1184 * .request_handler(...),
1185 * // Use just one thread for the HTTP-server.
1186 * 1u);
1187 *
1188 * ... // Some other actions.
1189 * }
1190 * @endcode
1191 *
1192 * run_async() returns control when HTTP-server is started or some
1193 * startup failure is detected. But if a failure is detected then an
1194 * exception is thrown. So if run_async() returns successfuly then
1195 * HTTP-server is working.
1196 *
1197 * The started HTTP-server will be automatically stopped at the
1198 * destruction of the returned value. Because of that the returned
1199 * value should be stored for the time while HTTP-server is needed.
1200 *
1201 * The started HTTP-server can be stopped manually by calling
1202 * stop() and wait() methods:
1203 * @code
1204 * auto server = restinio::run_async(...);
1205 * ...
1206 * server->stop(); // Returns without the waiting.
1207 * ... // Some other actions.
1208 * server->wait(); // Returns only when HTTP-server stopped.
1209 * @endcode
1210 *
1211 * @since v.0.6.7
1212 */
1213template< typename Traits = default_traits_t >
1214[[nodiscard]]
1217 io_context_holder_t io_context,
1218 server_settings_t< Traits > && settings,
1219 std::size_t thread_pool_size )
1220{
1221 running_server_handle_t< Traits > handle{
1223 std::move(io_context),
1224 std::move(settings),
1225 thread_pool_size }
1226 };
1227
1228 handle->start();
1229
1230 return handle;
1231}
1232
1233} /* namespace restinio */
1234
1235#undef RESTINIO_DEFAULT_BREAK_SIGNALS_LIST
Basic container for http_server settings.
Definition settings.hpp:555
Class for http-server.
A class for holding a reference to external Asio's io_context.
A class for holding actual instance of Asio's io_context.
Helper class for holding shared pointer to io_context.
Helper class for running an existing HTTP-server on a thread pool without blocking the current thread...
void wait() noexcept
Wait for full stop of the server.
void start()
Start the server.
on_pool_runner_t(std::size_t pool_size, Http_Server &server)
Initializing constructor.
impl::ioctx_on_thread_pool_t< impl::external_io_context_for_thread_pool_t > m_pool
Thread pool for running the server.
on_pool_runner_t(const on_pool_runner_t &)=delete
bool started() const noexcept
Is server started.
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 stop(Error_CB error_cb=Error_CB{}) noexcept
Stop the server.
on_pool_runner_t(on_pool_runner_t &&)=delete
Http_Server & m_server
HTTP-server to be run.
Helper type for holding parameters necessary for running HTTP-server on a thread pool.
http_server_t< Traits > * m_server
HTTP-server to be used on a thread pool.
break_signal_handling_t m_break_handling
Should break signal handler be used?
break_signal_handling_t break_handling() const noexcept
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.
http_server_t< Traits > & server() const noexcept
basic_server_settings_t< run_on_this_thread_settings_t< Traits >, Traits > base_type_t
std::size_t m_pool_size
Size of the pool.
std::size_t pool_size() const
Get the pool size.
run_on_thread_pool_settings_t(std::size_t pool_size)
Constructor.
A helper class used in an implementation of run_async function.
void start()
Start the HTTP-server.
void wait() noexcept
Wait for the shutdown of HTTP-server.
friend running_server_handle_t< Traits > run_async(io_context_holder_t, server_settings_t< Traits > &&, std::size_t thread_pool_size)
Creates an instance of HTTP-server and launches it on a separate thread or thread pool.
Http_Server m_server
Actual server instance.
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.
on_pool_runner_t< Http_Server > m_runner
The runner of the server.
#define RESTINIO_DEFAULT_BREAK_SIGNALS_LIST
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 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.
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.
constexpr break_signal_handling_t skip_break_signal_handling() noexcept
Make the indicator for absence of break signal handler.
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.
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.
void run(run_on_this_thread_settings_t< Traits > &&settings)
Helper function for running http server until ctrl+c is hit.
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.
io_context_holder_t external_io_context(asio_ns::io_context &ctx)
Function which tells that http_server should use external instance of io_context and should not contr...
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.
void run(run_on_thread_pool_settings_t< Traits > &&settings)
Helper function for running http server until ctrl+c is hit.
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.
constexpr break_signal_handling_t use_break_signal_handling() noexcept
Make the indicator for usage of break signal handler.
void run(run_existing_server_on_thread_pool_t< Traits > &&params)
Helper function for running an existing HTTP-server on a thread pool.
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.
break_signal_handling_t
Indication of usage of break signal handlers for some forms of run functions.
@ used
Signal handler should be used by run() function.
@ skipped
Signal handler should not be used by run() function.
void initiate_shutdown(http_server_t< Traits > &server)
Helper function for initiation of server shutdown.
Type of a function to be used as the default on_error-callback.
void operator()(std::exception_ptr) const noexcept