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