Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-04 08:42:01

0001 //
0002 // detail/epoll_reactor.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 // defined(_MSC_VER) && (_MSC_VER >= 1200)
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 // defined(BOOST_ASIO_HAS_TIMERFD)
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   // The mutex type used by this reactor.
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   // Per-descriptor queues.
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   // Per-descriptor data.
0082   typedef descriptor_state* per_descriptor_data;
0083 
0084   // Constructor.
0085   BOOST_ASIO_DECL epoll_reactor(boost::asio::execution_context& ctx);
0086 
0087   // Destructor.
0088   BOOST_ASIO_DECL ~epoll_reactor();
0089 
0090   // Destroy all user-defined handler objects owned by the service.
0091   BOOST_ASIO_DECL void shutdown();
0092 
0093   // Recreate internal descriptors following a fork.
0094   BOOST_ASIO_DECL void notify_fork(
0095       boost::asio::execution_context::fork_event fork_ev);
0096 
0097   // Initialise the task.
0098   BOOST_ASIO_DECL void init_task();
0099 
0100   // Register a socket with the reactor. Returns 0 on success, system error
0101   // code on failure.
0102   BOOST_ASIO_DECL int register_descriptor(socket_type descriptor,
0103       per_descriptor_data& descriptor_data);
0104 
0105   // Register a descriptor with an associated single operation. Returns 0 on
0106   // success, system error code on failure.
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   // Move descriptor registration from one descriptor_data object to another.
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   // Post a reactor operation for immediate completion.
0117   void post_immediate_completion(operation* op, bool is_continuation) const;
0118 
0119   // Post a reactor operation for immediate completion.
0120   BOOST_ASIO_DECL static void call_post_immediate_completion(
0121       operation* op, bool is_continuation, const void* self);
0122 
0123   // Start a new operation. The reactor operation will be performed when the
0124   // given descriptor is flagged as ready, or an error has occurred.
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   // Start a new operation. The reactor operation will be performed when the
0132   // given descriptor is flagged as ready, or an error has occurred.
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   // Cancel all operations associated with the given descriptor. The
0143   // handlers associated with the descriptor will be invoked with the
0144   // operation_aborted error.
0145   BOOST_ASIO_DECL void cancel_ops(socket_type descriptor,
0146       per_descriptor_data& descriptor_data);
0147 
0148   // Cancel all operations associated with the given descriptor and key. The
0149   // handlers associated with the descriptor will be invoked with the
0150   // operation_aborted error.
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   // Cancel any operations that are running against the descriptor and remove
0156   // its registration from the reactor. The reactor resources associated with
0157   // the descriptor must be released by calling cleanup_descriptor_data.
0158   BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor,
0159       per_descriptor_data& descriptor_data, bool closing);
0160 
0161   // Remove the descriptor's registration from the reactor. The reactor
0162   // resources associated with the descriptor must be released by calling
0163   // cleanup_descriptor_data.
0164   BOOST_ASIO_DECL void deregister_internal_descriptor(
0165       socket_type descriptor, per_descriptor_data& descriptor_data);
0166 
0167   // Perform any post-deregistration cleanup tasks associated with the
0168   // descriptor data.
0169   BOOST_ASIO_DECL void cleanup_descriptor_data(
0170       per_descriptor_data& descriptor_data);
0171 
0172   // Add a new timer queue to the reactor.
0173   template <typename TimeTraits, typename Allocator>
0174   void add_timer_queue(timer_queue<TimeTraits, Allocator>& timer_queue);
0175 
0176   // Remove a timer queue from the reactor.
0177   template <typename TimeTraits, typename Allocator>
0178   void remove_timer_queue(timer_queue<TimeTraits, Allocator>& timer_queue);
0179 
0180   // Schedule a new operation in the given timer queue to expire at the
0181   // specified absolute time.
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   // Cancel the timer operations associated with the given token. Returns the
0189   // number of operations that have been posted or dispatched.
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   // Cancel the timer operations associated with the given key.
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   // Move the timer operations associated with the given timer.
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   // Run epoll once until interrupted or events are ready to be dispatched.
0208   BOOST_ASIO_DECL void run(long usec, op_queue<operation>& ops);
0209 
0210   // Interrupt the select loop.
0211   BOOST_ASIO_DECL void interrupt();
0212 
0213 private:
0214   // The hint to pass to epoll_create to size its data structures.
0215   enum { epoll_size = 20000 };
0216 
0217   // Create the epoll file descriptor. Throws an exception if the descriptor
0218   // cannot be created.
0219   BOOST_ASIO_DECL static int do_epoll_create();
0220 
0221   // Create the timerfd file descriptor. Does not throw.
0222   BOOST_ASIO_DECL static int do_timerfd_create();
0223 
0224   // Allocate a new descriptor state object.
0225   BOOST_ASIO_DECL descriptor_state* allocate_descriptor_state();
0226 
0227   // Free an existing descriptor state object.
0228   BOOST_ASIO_DECL void free_descriptor_state(descriptor_state* s);
0229 
0230   // Helper function to add a new timer queue.
0231   BOOST_ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
0232 
0233   // Helper function to remove a timer queue.
0234   BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
0235 
0236   // Called to recalculate and update the timeout.
0237   BOOST_ASIO_DECL void update_timeout();
0238 
0239   // Get the timeout value for the epoll_wait call. The timeout value is
0240   // returned as a number of milliseconds. A return value of -1 indicates
0241   // that epoll_wait should block indefinitely.
0242   BOOST_ASIO_DECL int get_timeout(int msec);
0243 
0244 #if defined(BOOST_ASIO_HAS_TIMERFD)
0245   // Get the timeout value for the timer descriptor. The return value is the
0246   // flag argument to be used when calling timerfd_settime.
0247   BOOST_ASIO_DECL int get_timeout(itimerspec& ts);
0248 #endif // defined(BOOST_ASIO_HAS_TIMERFD)
0249 
0250   // The scheduler implementation used to post completions.
0251   scheduler& scheduler_;
0252 
0253   // Mutex to protect access to internal data.
0254   mutex mutex_;
0255 
0256   // The interrupter is used to break a blocking epoll_wait call.
0257   select_interrupter interrupter_;
0258 
0259   // The epoll file descriptor.
0260   int epoll_fd_;
0261 
0262   // The timer file descriptor.
0263   int timer_fd_;
0264 
0265   // The timer queues.
0266   timer_queue_set timer_queues_;
0267 
0268   // Whether the service has been shut down.
0269   bool shutdown_;
0270 
0271   // Whether I/O locking is enabled.
0272   const bool io_locking_;
0273 
0274   // How any times to spin waiting for the I/O mutex.
0275   const int io_locking_spin_count_;
0276 
0277   // Mutex to protect access to the registered descriptors.
0278   mutex registered_descriptors_mutex_;
0279 
0280   // Keep track of all registered descriptors.
0281   object_pool<descriptor_state, execution_context::allocator<void>>
0282     registered_descriptors_;
0283 
0284   // Helper class to do post-perform_io cleanup.
0285   struct perform_io_cleanup_on_block_exit;
0286   friend struct perform_io_cleanup_on_block_exit;
0287 };
0288 
0289 } // namespace detail
0290 } // namespace asio
0291 } // namespace boost
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 // defined(BOOST_ASIO_HEADER_ONLY)
0299 
0300 #endif // defined(BOOST_ASIO_HAS_EPOLL)
0301 
0302 #endif // BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP