LCOV - code coverage report
Current view: top level - corosio/native - native_io_context.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 59 59
Test Date: 2026-10-28 12:45:41 Functions: 100.0 % 30 30

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2026 Steve Gerbino
       3                 : // Copyright (c) 2026 Michael Vandeberg
       4                 : //
       5                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       6                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       7                 : //
       8                 : // Official repository: https://github.com/cppalliance/corosio
       9                 : //
      10                 : 
      11                 : #ifndef BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP
      12                 : #define BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP
      13                 : 
      14                 : #include <boost/corosio/io_context.hpp>
      15                 : #include <boost/corosio/backend.hpp>
      16                 : 
      17                 : #ifndef BOOST_COROSIO_MRDOCS
      18                 : #if BOOST_COROSIO_HAS_EPOLL
      19                 : #include <boost/corosio/native/detail/epoll/epoll_scheduler.hpp>
      20                 : #endif
      21                 : 
      22                 : #if BOOST_COROSIO_HAS_SELECT
      23                 : #include <boost/corosio/native/detail/select/select_scheduler.hpp>
      24                 : #endif
      25                 : 
      26                 : #if BOOST_COROSIO_HAS_KQUEUE
      27                 : #include <boost/corosio/native/detail/kqueue/kqueue_scheduler.hpp>
      28                 : #endif
      29                 : 
      30                 : #if BOOST_COROSIO_HAS_IOCP
      31                 : #include <boost/corosio/native/detail/iocp/win_scheduler.hpp>
      32                 : #endif
      33                 : 
      34                 : #if BOOST_COROSIO_HAS_URING
      35                 : #include <boost/corosio/native/detail/uring/uring_scheduler.hpp>
      36                 : #endif
      37                 : #endif // !BOOST_COROSIO_MRDOCS
      38                 : 
      39                 : namespace boost::corosio {
      40                 : 
      41                 : /** Runs asynchronous operations, calling the backend event loop directly.
      42                 : 
      43                 :     This class template inherits from @ref io_context and shadows
      44                 :     all public methods with versions that call the concrete
      45                 :     scheduler directly, bypassing virtual dispatch. No new state
      46                 :     is added.
      47                 : 
      48                 :     A `native_io_context` IS-A `io_context` and can be passed
      49                 :     anywhere an `io_context&` is accepted. In that case, virtual
      50                 :     dispatch is used transparently.
      51                 : 
      52                 :     @tparam Backend A backend tag value (e.g., `epoll`,
      53                 :         `iocp`) whose type provides `scheduler_type`.
      54                 : 
      55                 :     @par Thread Safety
      56                 :     Same as the underlying context type.
      57                 : 
      58                 :     @par Example
      59                 :     @par !example poll
      60                 : 
      61                 :     @see @ref io_context, @ref epoll_t, @ref iocp_t
      62                 : */
      63                 : template<auto Backend>
      64                 : class native_io_context : public io_context
      65                 : {
      66                 :     using backend_type   = decltype(Backend);
      67                 :     using scheduler_type = typename backend_type::scheduler_type;
      68                 : 
      69 HIT         219 :     scheduler_type& sched() noexcept
      70                 :     {
      71             219 :         return *static_cast<scheduler_type*>(this->sched_);
      72                 :     }
      73                 : 
      74                 : public:
      75                 :     /** Construct with default concurrency.
      76                 : 
      77                 :         @throws std::system_error If the backend's infrastructure
      78                 :             could not be created.
      79                 :     */
      80             224 :     native_io_context() : io_context(Backend) {}
      81                 : 
      82                 :     /** Construct with a concurrency hint.
      83                 : 
      84                 :         @throws std::system_error If the backend's infrastructure
      85                 :             could not be created.
      86                 : 
      87                 :         @param concurrency_hint Hint for the number of threads that
      88                 :             call `run()`.
      89                 :     */
      90               2 :     explicit native_io_context(unsigned concurrency_hint)
      91               2 :         : io_context(Backend, concurrency_hint)
      92                 :     {
      93               2 :     }
      94                 : 
      95                 :     /** Construct with runtime tuning options.
      96                 : 
      97                 :         @throws std::invalid_argument If `opts.thread_pool_size` is
      98                 :             less than 1 (POSIX), `opts.max_events_per_poll` is outside
      99                 :             the range its member documents, or `opts.inline_budget_max`
     100                 :             exceeds `INT_MAX` (platforms with a reactor backend).
     101                 : 
     102                 :         @throws std::system_error If the backend's infrastructure
     103                 :             could not be created.
     104                 : 
     105                 :         @param opts Runtime options controlling scheduler and
     106                 :             service behavior.
     107                 :         @param concurrency_hint Hint for the number of threads that
     108                 :             call `run()`.
     109                 :     */
     110               7 :     explicit native_io_context(
     111                 :         io_context_options const& opts,
     112                 :         unsigned concurrency_hint = std::thread::hardware_concurrency())
     113               7 :         : io_context(Backend, opts, concurrency_hint)
     114                 :     {
     115               7 :     }
     116                 : 
     117                 :     // Non-copyable, non-movable
     118                 :     /// Copy construction is disabled; the context owns its services.
     119                 :     native_io_context(native_io_context const&) = delete;
     120                 :     /// Copy assignment is disabled; the context owns its services.
     121                 :     native_io_context& operator=(native_io_context const&) = delete;
     122                 : 
     123                 :     /** Signal the context to stop processing.
     124                 : 
     125                 :         @throws std::system_error on Windows if the wakeup cannot be
     126                 :             queued, which leaves blocked `run()` callers unable to wake
     127                 :             until a later call succeeds.
     128                 :     */
     129               2 :     void stop()
     130                 :     {
     131               2 :         sched().stop();
     132               2 :     }
     133                 : 
     134                 :     /** Return whether the context stopped.
     135                 : 
     136                 :         @return `true` if the context has stopped.
     137                 :     */
     138              26 :     bool stopped() const noexcept
     139                 :     {
     140              26 :         return const_cast<native_io_context*>(this)->sched().stopped();
     141                 :     }
     142                 : 
     143                 :     /// Restart the context after being stopped.
     144              16 :     void restart()
     145                 :     {
     146              16 :         sched().restart();
     147              16 :     }
     148                 : 
     149                 :     /** Process all pending work items.
     150                 : 
     151                 :         @throws std::system_error if waiting on the operating system's
     152                 :             event demultiplexer fails other than by interruption or
     153                 :             another transient condition; the context can no longer
     154                 :             dispatch work. On Windows, also if a wakeup needed to
     155                 :             stop the context cannot be queued.
     156                 : 
     157                 :         @return The number of handlers executed.
     158                 :     */
     159             141 :     std::size_t run()
     160                 :     {
     161             141 :         frame_allocator_restore restore;
     162             282 :         return sched().run();
     163             141 :     }
     164                 : 
     165                 :     /** Process at most one pending work item.
     166                 : 
     167                 :         @throws std::system_error if waiting on the operating system's
     168                 :             event demultiplexer fails other than by interruption or
     169                 :             another transient condition; the context can no longer
     170                 :             dispatch work. On Windows, also if a wakeup needed to
     171                 :             stop the context cannot be queued.
     172                 : 
     173                 :         @return The number of handlers executed (0 or 1).
     174                 :     */
     175               2 :     std::size_t run_one()
     176                 :     {
     177               2 :         frame_allocator_restore restore;
     178               4 :         return sched().run_one();
     179               2 :     }
     180                 : 
     181                 :     /** Process work items for the specified duration.
     182                 : 
     183                 :         @throws std::system_error if waiting on the operating system's
     184                 :             event demultiplexer fails other than by interruption or
     185                 :             another transient condition; the context can no longer
     186                 :             dispatch work. On Windows, also if a wakeup needed to
     187                 :             stop the context cannot be queued.
     188                 : 
     189                 :         @param rel_time The duration for which to process work.
     190                 : 
     191                 :         @return The number of handlers executed.
     192                 :     */
     193                 :     template<class Rep, class Period>
     194               6 :     std::size_t run_for(std::chrono::duration<Rep, Period> const& rel_time)
     195                 :     {
     196               6 :         return run_until(std::chrono::steady_clock::now() + rel_time);
     197                 :     }
     198                 : 
     199                 :     /** Process work items until the specified time.
     200                 : 
     201                 :         @throws std::system_error if waiting on the operating system's
     202                 :             event demultiplexer fails other than by interruption or
     203                 :             another transient condition; the context can no longer
     204                 :             dispatch work. On Windows, also if a wakeup needed to
     205                 :             stop the context cannot be queued.
     206                 : 
     207                 :         @param abs_time The time point until which to process work.
     208                 : 
     209                 :         @return The number of handlers executed.
     210                 :     */
     211                 :     template<class Clock, class Duration>
     212                 :     std::size_t
     213               6 :     run_until(std::chrono::time_point<Clock, Duration> const& abs_time)
     214                 :     {
     215               6 :         std::size_t n = 0;
     216              10 :         while (run_one_until(abs_time))
     217               4 :             if (n != (std::numeric_limits<std::size_t>::max)())
     218               4 :                 ++n;
     219               6 :         return n;
     220                 :     }
     221                 : 
     222                 :     /** Process at most one work item for the specified duration.
     223                 : 
     224                 :         @throws std::system_error if waiting on the operating system's
     225                 :             event demultiplexer fails other than by interruption or
     226                 :             another transient condition; the context can no longer
     227                 :             dispatch work. On Windows, also if a wakeup needed to
     228                 :             stop the context cannot be queued.
     229                 : 
     230                 :         @param rel_time The duration for which the call may block.
     231                 : 
     232                 :         @return The number of handlers executed (0 or 1).
     233                 :     */
     234                 :     template<class Rep, class Period>
     235                 :     std::size_t run_one_for(std::chrono::duration<Rep, Period> const& rel_time)
     236                 :     {
     237                 :         return run_one_until(std::chrono::steady_clock::now() + rel_time);
     238                 :     }
     239                 : 
     240                 :     /** Process at most one work item until the specified time.
     241                 : 
     242                 :         @throws std::system_error if waiting on the operating system's
     243                 :             event demultiplexer fails other than by interruption or
     244                 :             another transient condition; the context can no longer
     245                 :             dispatch work. On Windows, also if a wakeup needed to
     246                 :             stop the context cannot be queued.
     247                 : 
     248                 :         @param abs_time The time point until which the call may block.
     249                 : 
     250                 :         @return The number of handlers executed (0 or 1).
     251                 :     */
     252                 :     template<class Clock, class Duration>
     253                 :     std::size_t
     254              14 :     run_one_until(std::chrono::time_point<Clock, Duration> const& abs_time)
     255                 :     {
     256              14 :         frame_allocator_restore restore;
     257              14 :         typename Clock::time_point now = Clock::now();
     258               4 :         for (;;)
     259                 :         {
     260              18 :             auto rel_time  = abs_time - now;
     261                 :             using rel_type = decltype(rel_time);
     262              18 :             if (rel_time < rel_type::zero())
     263               2 :                 rel_time = rel_type::zero();
     264              16 :             else if (rel_time > std::chrono::seconds(1))
     265               8 :                 rel_time = std::chrono::seconds(1);
     266                 : 
     267              36 :             std::size_t s = sched().wait_one(
     268                 :                 static_cast<long>(
     269              18 :                     std::chrono::duration_cast<std::chrono::microseconds>(
     270                 :                         rel_time)
     271              18 :                         .count()));
     272                 : 
     273              18 :             if (s || stopped())
     274              12 :                 return s;
     275                 : 
     276               6 :             now = Clock::now();
     277               6 :             if (now >= abs_time)
     278               2 :                 return 0;
     279                 :         }
     280              14 :     }
     281                 : 
     282                 :     /** Process all ready work items without blocking.
     283                 : 
     284                 :         @throws std::system_error if waiting on the operating system's
     285                 :             event demultiplexer fails other than by interruption or
     286                 :             another transient condition; the context can no longer
     287                 :             dispatch work. On Windows, also if a wakeup needed to
     288                 :             stop the context cannot be queued.
     289                 : 
     290                 :         @return The number of handlers executed.
     291                 :     */
     292              12 :     std::size_t poll()
     293                 :     {
     294              12 :         frame_allocator_restore restore;
     295              24 :         return sched().poll();
     296              12 :     }
     297                 : 
     298                 :     /** Process at most one ready work item without blocking.
     299                 : 
     300                 :         @throws std::system_error if waiting on the operating system's
     301                 :             event demultiplexer fails other than by interruption or
     302                 :             another transient condition; the context can no longer
     303                 :             dispatch work. On Windows, also if a wakeup needed to
     304                 :             stop the context cannot be queued.
     305                 : 
     306                 :         @return The number of handlers executed (0 or 1).
     307                 :     */
     308               2 :     std::size_t poll_one()
     309                 :     {
     310               2 :         frame_allocator_restore restore;
     311               4 :         return sched().poll_one();
     312               2 :     }
     313                 : };
     314                 : 
     315                 : } // namespace boost::corosio
     316                 : 
     317                 : #endif // BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP
        

Generated by: LCOV version 2.3