100.00% Lines (45/45) 100.00% Functions (12/12)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2026 Steve Gerbino 2   // Copyright (c) 2026 Steve Gerbino
3   // Copyright (c) 2026 Michael Vandeberg 3   // Copyright (c) 2026 Michael Vandeberg
4   // 4   //
5   // Distributed under the Boost Software License, Version 1.0. (See accompanying 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) 6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7   // 7   //
8   // Official repository: https://github.com/cppalliance/corosio 8   // Official repository: https://github.com/cppalliance/corosio
9   // 9   //
10   10  
11   #ifndef BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP 11   #ifndef BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP
12   #define BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP 12   #define BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP
13   13  
14   #include <boost/corosio/io_context.hpp> 14   #include <boost/corosio/io_context.hpp>
15   #include <boost/corosio/backend.hpp> 15   #include <boost/corosio/backend.hpp>
16   16  
17   #ifndef BOOST_COROSIO_MRDOCS 17   #ifndef BOOST_COROSIO_MRDOCS
18   #if BOOST_COROSIO_HAS_EPOLL 18   #if BOOST_COROSIO_HAS_EPOLL
19   #include <boost/corosio/native/detail/epoll/epoll_scheduler.hpp> 19   #include <boost/corosio/native/detail/epoll/epoll_scheduler.hpp>
20   #endif 20   #endif
21   21  
22   #if BOOST_COROSIO_HAS_SELECT 22   #if BOOST_COROSIO_HAS_SELECT
23   #include <boost/corosio/native/detail/select/select_scheduler.hpp> 23   #include <boost/corosio/native/detail/select/select_scheduler.hpp>
24   #endif 24   #endif
25   25  
26   #if BOOST_COROSIO_HAS_KQUEUE 26   #if BOOST_COROSIO_HAS_KQUEUE
27   #include <boost/corosio/native/detail/kqueue/kqueue_scheduler.hpp> 27   #include <boost/corosio/native/detail/kqueue/kqueue_scheduler.hpp>
28   #endif 28   #endif
29   29  
30   #if BOOST_COROSIO_HAS_IOCP 30   #if BOOST_COROSIO_HAS_IOCP
31   #include <boost/corosio/native/detail/iocp/win_scheduler.hpp> 31   #include <boost/corosio/native/detail/iocp/win_scheduler.hpp>
32   #endif 32   #endif
33   33  
34   #if BOOST_COROSIO_HAS_URING 34   #if BOOST_COROSIO_HAS_URING
35   #include <boost/corosio/native/detail/uring/uring_scheduler.hpp> 35   #include <boost/corosio/native/detail/uring/uring_scheduler.hpp>
36   #endif 36   #endif
37   #endif // !BOOST_COROSIO_MRDOCS 37   #endif // !BOOST_COROSIO_MRDOCS
38   38  
39   namespace boost::corosio { 39   namespace boost::corosio {
40   40  
41 - /** An I/O context with devirtualized event loop methods. 41 + /** Runs asynchronous operations, calling the backend event loop directly.
42   42  
43   This class template inherits from @ref io_context and shadows 43   This class template inherits from @ref io_context and shadows
44   all public methods with versions that call the concrete 44   all public methods with versions that call the concrete
45   scheduler directly, bypassing virtual dispatch. No new state 45   scheduler directly, bypassing virtual dispatch. No new state
46   is added. 46   is added.
47   47  
48   A `native_io_context` IS-A `io_context` and can be passed 48   A `native_io_context` IS-A `io_context` and can be passed
49 - anywhere an `io_context&` is accepted, in which case virtual 49 + anywhere an `io_context&` is accepted. In that case, virtual
50   dispatch is used transparently. 50   dispatch is used transparently.
51   51  
52   @tparam Backend A backend tag value (e.g., `epoll`, 52   @tparam Backend A backend tag value (e.g., `epoll`,
53   `iocp`) whose type provides `scheduler_type`. 53   `iocp`) whose type provides `scheduler_type`.
54   54  
55   @par Thread Safety 55   @par Thread Safety
56   Same as the underlying context type. 56   Same as the underlying context type.
57   57  
58   @par Example 58   @par Example
59   @par !example poll 59   @par !example poll
60   60  
61   @see io_context, epoll_t, iocp_t 61   @see io_context, epoll_t, iocp_t
62   */ 62   */
63   template<auto Backend> 63   template<auto Backend>
64   class native_io_context : public io_context 64   class native_io_context : public io_context
65   { 65   {
66   using backend_type = decltype(Backend); 66   using backend_type = decltype(Backend);
67   using scheduler_type = typename backend_type::scheduler_type; 67   using scheduler_type = typename backend_type::scheduler_type;
68   68  
HITCBC 69   171 scheduler_type& sched() noexcept 69   171 scheduler_type& sched() noexcept
70   { 70   {
HITCBC 71   171 return *static_cast<scheduler_type*>(this->sched_); 71   171 return *static_cast<scheduler_type*>(this->sched_);
72   } 72   }
73   73  
74   public: 74   public:
75   /** Construct with default concurrency. */ 75   /** Construct with default concurrency. */
HITCBC 76   178 native_io_context() : io_context(Backend) {} 76   178 native_io_context() : io_context(Backend) {}
77   77  
78   /** Construct with a concurrency hint. 78   /** Construct with a concurrency hint.
79   79  
80   @param concurrency_hint Hint for the number of threads that 80   @param concurrency_hint Hint for the number of threads that
81 - will call `run()`. 81 + call `run()`.
82   */ 82   */
HITCBC 83   2 explicit native_io_context(unsigned concurrency_hint) 83   2 explicit native_io_context(unsigned concurrency_hint)
HITCBC 84   2 : io_context(Backend, concurrency_hint) 84   2 : io_context(Backend, concurrency_hint)
85   { 85   {
HITCBC 86   2 } 86   2 }
87   87  
88   /** Construct with runtime tuning options. 88   /** Construct with runtime tuning options.
89   89  
90   @param opts Runtime options controlling scheduler and 90   @param opts Runtime options controlling scheduler and
91   service behavior. 91   service behavior.
92   @param concurrency_hint Hint for the number of threads that 92   @param concurrency_hint Hint for the number of threads that
93 - will call `run()`. 93 + call `run()`.
94   */ 94   */
HITCBC 95   5 explicit native_io_context( 95   5 explicit native_io_context(
96   io_context_options const& opts, 96   io_context_options const& opts,
97   unsigned concurrency_hint = std::thread::hardware_concurrency()) 97   unsigned concurrency_hint = std::thread::hardware_concurrency())
HITCBC 98   5 : io_context(Backend, opts, concurrency_hint) 98   5 : io_context(Backend, opts, concurrency_hint)
99   { 99   {
HITCBC 100   5 } 100   5 }
101   101  
102   // Non-copyable, non-movable 102   // Non-copyable, non-movable
103 - native_io_context(native_io_context const&) = delete; 103 + /// Copy construction is disabled; the context owns its services.
  104 + native_io_context(native_io_context const&) = delete;
  105 + /// Copy assignment is disabled; the context owns its services.
104   native_io_context& operator=(native_io_context const&) = delete; 106   native_io_context& operator=(native_io_context const&) = delete;
105   107  
106   /// Signal the context to stop processing. 108   /// Signal the context to stop processing.
HITCBC 107   2 void stop() 109   2 void stop()
108   { 110   {
HITCBC 109   2 sched().stop(); 111   2 sched().stop();
HITCBC 110   2 } 112   2 }
111   113  
112 - /// Return whether the context has been stopped. 114 + /** Return whether the context stopped.
  115 +
  116 + @return `true` if the context has stopped.
  117 + */
HITCBC 113   22 bool stopped() const noexcept 118   22 bool stopped() const noexcept
114   { 119   {
HITCBC 115   22 return const_cast<native_io_context*>(this)->sched().stopped(); 120   22 return const_cast<native_io_context*>(this)->sched().stopped();
116   } 121   }
117   122  
118   /// Restart the context after being stopped. 123   /// Restart the context after being stopped.
HITCBC 119   16 void restart() 124   16 void restart()
120   { 125   {
HITCBC 121   16 sched().restart(); 126   16 sched().restart();
HITCBC 122   16 } 127   16 }
123   128  
124   /** Process all pending work items. 129   /** Process all pending work items.
125   130  
126   @return The number of handlers executed. 131   @return The number of handlers executed.
127   */ 132   */
HITCBC 128   117 std::size_t run() 133   117 std::size_t run()
129   { 134   {
HITCBC 130   117 return sched().run(); 135   117 return sched().run();
131   } 136   }
132   137  
133   /** Process at most one pending work item. 138   /** Process at most one pending work item.
134   139  
135   @return The number of handlers executed (0 or 1). 140   @return The number of handlers executed (0 or 1).
136   */ 141   */
137   std::size_t run_one() 142   std::size_t run_one()
138   { 143   {
139   return sched().run_one(); 144   return sched().run_one();
140   } 145   }
141   146  
142   /** Process work items for the specified duration. 147   /** Process work items for the specified duration.
143   148  
144   @param rel_time The duration for which to process work. 149   @param rel_time The duration for which to process work.
145   150  
146   @return The number of handlers executed. 151   @return The number of handlers executed.
147   */ 152   */
148   template<class Rep, class Period> 153   template<class Rep, class Period>
HITCBC 149   4 std::size_t run_for(std::chrono::duration<Rep, Period> const& rel_time) 154   4 std::size_t run_for(std::chrono::duration<Rep, Period> const& rel_time)
150   { 155   {
HITCBC 151   4 return run_until(std::chrono::steady_clock::now() + rel_time); 156   4 return run_until(std::chrono::steady_clock::now() + rel_time);
152   } 157   }
153   158  
154   /** Process work items until the specified time. 159   /** Process work items until the specified time.
155   160  
156   @param abs_time The time point until which to process work. 161   @param abs_time The time point until which to process work.
157   162  
158   @return The number of handlers executed. 163   @return The number of handlers executed.
159   */ 164   */
160   template<class Clock, class Duration> 165   template<class Clock, class Duration>
161   std::size_t 166   std::size_t
HITCBC 162   4 run_until(std::chrono::time_point<Clock, Duration> const& abs_time) 167   4 run_until(std::chrono::time_point<Clock, Duration> const& abs_time)
163   { 168   {
HITCBC 164   4 std::size_t n = 0; 169   4 std::size_t n = 0;
HITCBC 165   6 while (run_one_until(abs_time)) 170   6 while (run_one_until(abs_time))
HITCBC 166   2 if (n != (std::numeric_limits<std::size_t>::max)()) 171   2 if (n != (std::numeric_limits<std::size_t>::max)())
HITCBC 167   2 ++n; 172   2 ++n;
HITCBC 168   4 return n; 173   4 return n;
169   } 174   }
170   175  
171   /** Process at most one work item for the specified duration. 176   /** Process at most one work item for the specified duration.
172   177  
173   @param rel_time The duration for which the call may block. 178   @param rel_time The duration for which the call may block.
174   179  
175   @return The number of handlers executed (0 or 1). 180   @return The number of handlers executed (0 or 1).
176   */ 181   */
177   template<class Rep, class Period> 182   template<class Rep, class Period>
178   std::size_t run_one_for(std::chrono::duration<Rep, Period> const& rel_time) 183   std::size_t run_one_for(std::chrono::duration<Rep, Period> const& rel_time)
179   { 184   {
180   return run_one_until(std::chrono::steady_clock::now() + rel_time); 185   return run_one_until(std::chrono::steady_clock::now() + rel_time);
181   } 186   }
182   187  
183   /** Process at most one work item until the specified time. 188   /** Process at most one work item until the specified time.
184   189  
185   @param abs_time The time point until which the call may block. 190   @param abs_time The time point until which the call may block.
186   191  
187   @return The number of handlers executed (0 or 1). 192   @return The number of handlers executed (0 or 1).
188   */ 193   */
189   template<class Clock, class Duration> 194   template<class Clock, class Duration>
190   std::size_t 195   std::size_t
HITCBC 191   10 run_one_until(std::chrono::time_point<Clock, Duration> const& abs_time) 196   10 run_one_until(std::chrono::time_point<Clock, Duration> const& abs_time)
192   { 197   {
HITCBC 193   10 typename Clock::time_point now = Clock::now(); 198   10 typename Clock::time_point now = Clock::now();
HITCBC 194   2 for (;;) 199   2 for (;;)
195   { 200   {
HITCBC 196   12 auto rel_time = abs_time - now; 201   12 auto rel_time = abs_time - now;
197   using rel_type = decltype(rel_time); 202   using rel_type = decltype(rel_time);
HITCBC 198   12 if (rel_time < rel_type::zero()) 203   12 if (rel_time < rel_type::zero())
HITCBC 199   2 rel_time = rel_type::zero(); 204   2 rel_time = rel_type::zero();
HITCBC 200   10 else if (rel_time > std::chrono::seconds(1)) 205   10 else if (rel_time > std::chrono::seconds(1))
HITCBC 201   2 rel_time = std::chrono::seconds(1); 206   2 rel_time = std::chrono::seconds(1);
202   207  
HITCBC 203   24 std::size_t s = sched().wait_one( 208   24 std::size_t s = sched().wait_one(
204   static_cast<long>( 209   static_cast<long>(
HITCBC 205   12 std::chrono::duration_cast<std::chrono::microseconds>( 210   12 std::chrono::duration_cast<std::chrono::microseconds>(
206   rel_time) 211   rel_time)
HITCBC 207   12 .count())); 212   12 .count()));
208   213  
HITCBC 209   12 if (s || stopped()) 214   12 if (s || stopped())
HITCBC 210   10 return s; 215   10 return s;
211   216  
HITCBC 212   4 now = Clock::now(); 217   4 now = Clock::now();
HITCBC 213   4 if (now >= abs_time) 218   4 if (now >= abs_time)
HITCBC 214   2 return 0; 219   2 return 0;
215   } 220   }
216   } 221   }
217   222  
218   /** Process all ready work items without blocking. 223   /** Process all ready work items without blocking.
219   224  
220   @return The number of handlers executed. 225   @return The number of handlers executed.
221   */ 226   */
HITCBC 222   2 std::size_t poll() 227   2 std::size_t poll()
223   { 228   {
HITCBC 224   2 return sched().poll(); 229   2 return sched().poll();
225   } 230   }
226   231  
227   /** Process at most one ready work item without blocking. 232   /** Process at most one ready work item without blocking.
228   233  
229   @return The number of handlers executed (0 or 1). 234   @return The number of handlers executed (0 or 1).
230   */ 235   */
231   std::size_t poll_one() 236   std::size_t poll_one()
232   { 237   {
233   return sched().poll_one(); 238   return sched().poll_one();
234   } 239   }
235   }; 240   };
236   241  
237   } // namespace boost::corosio 242   } // namespace boost::corosio
238   243  
239   #endif // BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP 244   #endif // BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP