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