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 - /** Runs asynchronous operations, calling the backend event loop directly. 41 + /** An I/O context with devirtualized event loop methods.
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 that case, virtual 49 + anywhere an `io_context&` is accepted, in which 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 - call `run()`. 81 + will 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 - call `run()`. 93 + will 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 - /// Copy construction is disabled; the context owns its services. 103 + native_io_context(native_io_context const&) = delete;
104 - native_io_context(native_io_context const&) = delete;  
105 - /// Copy assignment is disabled; the context owns its services.  
106   native_io_context& operator=(native_io_context const&) = delete; 104   native_io_context& operator=(native_io_context const&) = delete;
107   105  
108   /// Signal the context to stop processing. 106   /// Signal the context to stop processing.
HITCBC 109   2 void stop() 107   2 void stop()
110   { 108   {
HITCBC 111   2 sched().stop(); 109   2 sched().stop();
HITCBC 112   2 } 110   2 }
113   111  
114 - /** Return whether the context stopped. 112 + /// Return whether the context has been stopped.
115 -  
116 - @return `true` if the context has stopped.  
117 - */  
HITCBC 118   22 bool stopped() const noexcept 113   22 bool stopped() const noexcept
119   { 114   {
HITCBC 120   22 return const_cast<native_io_context*>(this)->sched().stopped(); 115   22 return const_cast<native_io_context*>(this)->sched().stopped();
121   } 116   }
122   117  
123   /// Restart the context after being stopped. 118   /// Restart the context after being stopped.
HITCBC 124   16 void restart() 119   16 void restart()
125   { 120   {
HITCBC 126   16 sched().restart(); 121   16 sched().restart();
HITCBC 127   16 } 122   16 }
128   123  
129   /** Process all pending work items. 124   /** Process all pending work items.
130   125  
131   @return The number of handlers executed. 126   @return The number of handlers executed.
132   */ 127   */
HITCBC 133   117 std::size_t run() 128   117 std::size_t run()
134   { 129   {
HITCBC 135   117 return sched().run(); 130   117 return sched().run();
136   } 131   }
137   132  
138   /** Process at most one pending work item. 133   /** Process at most one pending work item.
139   134  
140   @return The number of handlers executed (0 or 1). 135   @return The number of handlers executed (0 or 1).
141   */ 136   */
142   std::size_t run_one() 137   std::size_t run_one()
143   { 138   {
144   return sched().run_one(); 139   return sched().run_one();
145   } 140   }
146   141  
147   /** Process work items for the specified duration. 142   /** Process work items for the specified duration.
148   143  
149   @param rel_time The duration for which to process work. 144   @param rel_time The duration for which to process work.
150   145  
151   @return The number of handlers executed. 146   @return The number of handlers executed.
152   */ 147   */
153   template<class Rep, class Period> 148   template<class Rep, class Period>
HITCBC 154   4 std::size_t run_for(std::chrono::duration<Rep, Period> const& rel_time) 149   4 std::size_t run_for(std::chrono::duration<Rep, Period> const& rel_time)
155   { 150   {
HITCBC 156   4 return run_until(std::chrono::steady_clock::now() + rel_time); 151   4 return run_until(std::chrono::steady_clock::now() + rel_time);
157   } 152   }
158   153  
159   /** Process work items until the specified time. 154   /** Process work items until the specified time.
160   155  
161   @param abs_time The time point until which to process work. 156   @param abs_time The time point until which to process work.
162   157  
163   @return The number of handlers executed. 158   @return The number of handlers executed.
164   */ 159   */
165   template<class Clock, class Duration> 160   template<class Clock, class Duration>
166   std::size_t 161   std::size_t
HITCBC 167   4 run_until(std::chrono::time_point<Clock, Duration> const& abs_time) 162   4 run_until(std::chrono::time_point<Clock, Duration> const& abs_time)
168   { 163   {
HITCBC 169   4 std::size_t n = 0; 164   4 std::size_t n = 0;
HITCBC 170   6 while (run_one_until(abs_time)) 165   6 while (run_one_until(abs_time))
HITCBC 171   2 if (n != (std::numeric_limits<std::size_t>::max)()) 166   2 if (n != (std::numeric_limits<std::size_t>::max)())
HITCBC 172   2 ++n; 167   2 ++n;
HITCBC 173   4 return n; 168   4 return n;
174   } 169   }
175   170  
176   /** Process at most one work item for the specified duration. 171   /** Process at most one work item for the specified duration.
177   172  
178   @param rel_time The duration for which the call may block. 173   @param rel_time The duration for which the call may block.
179   174  
180   @return The number of handlers executed (0 or 1). 175   @return The number of handlers executed (0 or 1).
181   */ 176   */
182   template<class Rep, class Period> 177   template<class Rep, class Period>
183   std::size_t run_one_for(std::chrono::duration<Rep, Period> const& rel_time) 178   std::size_t run_one_for(std::chrono::duration<Rep, Period> const& rel_time)
184   { 179   {
185   return run_one_until(std::chrono::steady_clock::now() + rel_time); 180   return run_one_until(std::chrono::steady_clock::now() + rel_time);
186   } 181   }
187   182  
188   /** Process at most one work item until the specified time. 183   /** Process at most one work item until the specified time.
189   184  
190   @param abs_time The time point until which the call may block. 185   @param abs_time The time point until which the call may block.
191   186  
192   @return The number of handlers executed (0 or 1). 187   @return The number of handlers executed (0 or 1).
193   */ 188   */
194   template<class Clock, class Duration> 189   template<class Clock, class Duration>
195   std::size_t 190   std::size_t
HITCBC 196   10 run_one_until(std::chrono::time_point<Clock, Duration> const& abs_time) 191   10 run_one_until(std::chrono::time_point<Clock, Duration> const& abs_time)
197   { 192   {
HITCBC 198   10 typename Clock::time_point now = Clock::now(); 193   10 typename Clock::time_point now = Clock::now();
HITCBC 199   2 for (;;) 194   2 for (;;)
200   { 195   {
HITCBC 201   12 auto rel_time = abs_time - now; 196   12 auto rel_time = abs_time - now;
202   using rel_type = decltype(rel_time); 197   using rel_type = decltype(rel_time);
HITCBC 203   12 if (rel_time < rel_type::zero()) 198   12 if (rel_time < rel_type::zero())
HITCBC 204   2 rel_time = rel_type::zero(); 199   2 rel_time = rel_type::zero();
HITCBC 205   10 else if (rel_time > std::chrono::seconds(1)) 200   10 else if (rel_time > std::chrono::seconds(1))
HITCBC 206   2 rel_time = std::chrono::seconds(1); 201   2 rel_time = std::chrono::seconds(1);
207   202  
HITCBC 208   24 std::size_t s = sched().wait_one( 203   24 std::size_t s = sched().wait_one(
209   static_cast<long>( 204   static_cast<long>(
HITCBC 210   12 std::chrono::duration_cast<std::chrono::microseconds>( 205   12 std::chrono::duration_cast<std::chrono::microseconds>(
211   rel_time) 206   rel_time)
HITCBC 212   12 .count())); 207   12 .count()));
213   208  
HITCBC 214   12 if (s || stopped()) 209   12 if (s || stopped())
HITCBC 215   10 return s; 210   10 return s;
216   211  
HITCBC 217   4 now = Clock::now(); 212   4 now = Clock::now();
HITCBC 218   4 if (now >= abs_time) 213   4 if (now >= abs_time)
HITCBC 219   2 return 0; 214   2 return 0;
220   } 215   }
221   } 216   }
222   217  
223   /** Process all ready work items without blocking. 218   /** Process all ready work items without blocking.
224   219  
225   @return The number of handlers executed. 220   @return The number of handlers executed.
226   */ 221   */
HITCBC 227   2 std::size_t poll() 222   2 std::size_t poll()
228   { 223   {
HITCBC 229   2 return sched().poll(); 224   2 return sched().poll();
230   } 225   }
231   226  
232   /** Process at most one ready work item without blocking. 227   /** Process at most one ready work item without blocking.
233   228  
234   @return The number of handlers executed (0 or 1). 229   @return The number of handlers executed (0 or 1).
235   */ 230   */
236   std::size_t poll_one() 231   std::size_t poll_one()
237   { 232   {
238   return sched().poll_one(); 233   return sched().poll_one();
239   } 234   }
240   }; 235   };
241   236  
242   } // namespace boost::corosio 237   } // namespace boost::corosio
243   238  
244   #endif // BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP 239   #endif // BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP