File indexing completed on 2026-09-04 08:42:01
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP
0012 #define BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019
0020 #if defined(BOOST_ASIO_HAS_EPOLL)
0021
0022 #include <boost/asio/detail/atomic_count.hpp>
0023 #include <boost/asio/detail/conditionally_enabled_mutex.hpp>
0024 #include <boost/asio/detail/limits.hpp>
0025 #include <boost/asio/detail/object_pool.hpp>
0026 #include <boost/asio/detail/op_queue.hpp>
0027 #include <boost/asio/detail/reactor_op.hpp>
0028 #include <boost/asio/detail/scheduler_task.hpp>
0029 #include <boost/asio/detail/select_interrupter.hpp>
0030 #include <boost/asio/detail/socket_types.hpp>
0031 #include <boost/asio/detail/timer_queue_base.hpp>
0032 #include <boost/asio/detail/timer_queue_set.hpp>
0033 #include <boost/asio/detail/wait_op.hpp>
0034 #include <boost/asio/execution_context.hpp>
0035
0036 #if defined(BOOST_ASIO_HAS_TIMERFD)
0037 # include <sys/timerfd.h>
0038 #endif
0039
0040 #include <boost/asio/detail/push_options.hpp>
0041
0042 namespace boost {
0043 namespace asio {
0044 namespace detail {
0045
0046 class epoll_reactor
0047 : public execution_context_service_base<epoll_reactor>,
0048 public scheduler_task
0049 {
0050 private:
0051
0052 typedef conditionally_enabled_mutex mutex;
0053
0054 public:
0055 enum op_types { read_op = 0, write_op = 1,
0056 connect_op = 1, except_op = 2, max_ops = 3 };
0057
0058
0059 struct descriptor_state : operation
0060 {
0061 descriptor_state* next_;
0062 descriptor_state* prev_;
0063
0064 mutex mutex_;
0065 epoll_reactor* reactor_;
0066 int descriptor_;
0067 uint32_t registered_events_;
0068 op_queue<reactor_op> op_queue_[max_ops];
0069 bool try_speculative_[max_ops];
0070 bool shutdown_;
0071
0072 BOOST_ASIO_DECL descriptor_state(bool locking, int spin_count);
0073 void set_ready_events(uint32_t events) { task_result_ = events; }
0074 void add_ready_events(uint32_t events) { task_result_ |= events; }
0075 BOOST_ASIO_DECL operation* perform_io(uint32_t events);
0076 BOOST_ASIO_DECL static void do_complete(
0077 void* owner, operation* base,
0078 const boost::system::error_code& ec, std::size_t bytes_transferred);
0079 };
0080
0081
0082 typedef descriptor_state* per_descriptor_data;
0083
0084
0085 BOOST_ASIO_DECL epoll_reactor(boost::asio::execution_context& ctx);
0086
0087
0088 BOOST_ASIO_DECL ~epoll_reactor();
0089
0090
0091 BOOST_ASIO_DECL void shutdown();
0092
0093
0094 BOOST_ASIO_DECL void notify_fork(
0095 boost::asio::execution_context::fork_event fork_ev);
0096
0097
0098 BOOST_ASIO_DECL void init_task();
0099
0100
0101
0102 BOOST_ASIO_DECL int register_descriptor(socket_type descriptor,
0103 per_descriptor_data& descriptor_data);
0104
0105
0106
0107 BOOST_ASIO_DECL int register_internal_descriptor(
0108 int op_type, socket_type descriptor,
0109 per_descriptor_data& descriptor_data, reactor_op* op);
0110
0111
0112 BOOST_ASIO_DECL void move_descriptor(socket_type descriptor,
0113 per_descriptor_data& target_descriptor_data,
0114 per_descriptor_data& source_descriptor_data);
0115
0116
0117 void post_immediate_completion(operation* op, bool is_continuation) const;
0118
0119
0120 BOOST_ASIO_DECL static void call_post_immediate_completion(
0121 operation* op, bool is_continuation, const void* self);
0122
0123
0124
0125 BOOST_ASIO_DECL void start_op(int op_type, socket_type descriptor,
0126 per_descriptor_data& descriptor_data, reactor_op* op,
0127 bool is_continuation, bool allow_speculative,
0128 void (*on_immediate)(operation*, bool, const void*),
0129 const void* immediate_arg);
0130
0131
0132
0133 void start_op(int op_type, socket_type descriptor,
0134 per_descriptor_data& descriptor_data, reactor_op* op,
0135 bool is_continuation, bool allow_speculative)
0136 {
0137 start_op(op_type, descriptor, descriptor_data,
0138 op, is_continuation, allow_speculative,
0139 &epoll_reactor::call_post_immediate_completion, this);
0140 }
0141
0142
0143
0144
0145 BOOST_ASIO_DECL void cancel_ops(socket_type descriptor,
0146 per_descriptor_data& descriptor_data);
0147
0148
0149
0150
0151 BOOST_ASIO_DECL void cancel_ops_by_key(socket_type descriptor,
0152 per_descriptor_data& descriptor_data,
0153 int op_type, void* cancellation_key);
0154
0155
0156
0157
0158 BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor,
0159 per_descriptor_data& descriptor_data, bool closing);
0160
0161
0162
0163
0164 BOOST_ASIO_DECL void deregister_internal_descriptor(
0165 socket_type descriptor, per_descriptor_data& descriptor_data);
0166
0167
0168
0169 BOOST_ASIO_DECL void cleanup_descriptor_data(
0170 per_descriptor_data& descriptor_data);
0171
0172
0173 template <typename TimeTraits, typename Allocator>
0174 void add_timer_queue(timer_queue<TimeTraits, Allocator>& timer_queue);
0175
0176
0177 template <typename TimeTraits, typename Allocator>
0178 void remove_timer_queue(timer_queue<TimeTraits, Allocator>& timer_queue);
0179
0180
0181
0182 template <typename TimeTraits, typename Allocator>
0183 void schedule_timer(timer_queue<TimeTraits, Allocator>& queue,
0184 const typename TimeTraits::time_type& time,
0185 typename timer_queue<TimeTraits, Allocator>::per_timer_data& timer,
0186 wait_op* op);
0187
0188
0189
0190 template <typename TimeTraits, typename Allocator>
0191 std::size_t cancel_timer(timer_queue<TimeTraits, Allocator>& queue,
0192 typename timer_queue<TimeTraits, Allocator>::per_timer_data& timer,
0193 std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
0194
0195
0196 template <typename TimeTraits, typename Allocator>
0197 void cancel_timer_by_key(timer_queue<TimeTraits, Allocator>& queue,
0198 typename timer_queue<TimeTraits, Allocator>::per_timer_data* timer,
0199 void* cancellation_key);
0200
0201
0202 template <typename TimeTraits, typename Allocator>
0203 void move_timer(timer_queue<TimeTraits, Allocator>& queue,
0204 typename timer_queue<TimeTraits, Allocator>::per_timer_data& target,
0205 typename timer_queue<TimeTraits, Allocator>::per_timer_data& source);
0206
0207
0208 BOOST_ASIO_DECL void run(long usec, op_queue<operation>& ops);
0209
0210
0211 BOOST_ASIO_DECL void interrupt();
0212
0213 private:
0214
0215 enum { epoll_size = 20000 };
0216
0217
0218
0219 BOOST_ASIO_DECL static int do_epoll_create();
0220
0221
0222 BOOST_ASIO_DECL static int do_timerfd_create();
0223
0224
0225 BOOST_ASIO_DECL descriptor_state* allocate_descriptor_state();
0226
0227
0228 BOOST_ASIO_DECL void free_descriptor_state(descriptor_state* s);
0229
0230
0231 BOOST_ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
0232
0233
0234 BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
0235
0236
0237 BOOST_ASIO_DECL void update_timeout();
0238
0239
0240
0241
0242 BOOST_ASIO_DECL int get_timeout(int msec);
0243
0244 #if defined(BOOST_ASIO_HAS_TIMERFD)
0245
0246
0247 BOOST_ASIO_DECL int get_timeout(itimerspec& ts);
0248 #endif
0249
0250
0251 scheduler& scheduler_;
0252
0253
0254 mutex mutex_;
0255
0256
0257 select_interrupter interrupter_;
0258
0259
0260 int epoll_fd_;
0261
0262
0263 int timer_fd_;
0264
0265
0266 timer_queue_set timer_queues_;
0267
0268
0269 bool shutdown_;
0270
0271
0272 const bool io_locking_;
0273
0274
0275 const int io_locking_spin_count_;
0276
0277
0278 mutex registered_descriptors_mutex_;
0279
0280
0281 object_pool<descriptor_state, execution_context::allocator<void>>
0282 registered_descriptors_;
0283
0284
0285 struct perform_io_cleanup_on_block_exit;
0286 friend struct perform_io_cleanup_on_block_exit;
0287 };
0288
0289 }
0290 }
0291 }
0292
0293 #include <boost/asio/detail/pop_options.hpp>
0294
0295 #include <boost/asio/detail/impl/epoll_reactor.hpp>
0296 #if defined(BOOST_ASIO_HEADER_ONLY)
0297 # include <boost/asio/detail/impl/epoll_reactor.ipp>
0298 #endif
0299
0300 #endif
0301
0302 #endif