Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:44

0001 //
0002 // detail/select_reactor.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 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_SELECT_REACTOR_HPP
0012 #define BOOST_ASIO_DETAIL_SELECT_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_IOCP) \
0021   || (!defined(BOOST_ASIO_HAS_DEV_POLL) \
0022       && !defined(BOOST_ASIO_HAS_EPOLL) \
0023       && !defined(BOOST_ASIO_HAS_KQUEUE) \
0024       && !defined(BOOST_ASIO_WINDOWS_RUNTIME))
0025 
0026 #include <cstddef>
0027 #include <boost/asio/detail/fd_set_adapter.hpp>
0028 #include <boost/asio/detail/limits.hpp>
0029 #include <boost/asio/detail/mutex.hpp>
0030 #include <boost/asio/detail/op_queue.hpp>
0031 #include <boost/asio/detail/reactor_op.hpp>
0032 #include <boost/asio/detail/reactor_op_queue.hpp>
0033 #include <boost/asio/detail/scheduler_task.hpp>
0034 #include <boost/asio/detail/select_interrupter.hpp>
0035 #include <boost/asio/detail/socket_types.hpp>
0036 #include <boost/asio/detail/timer_queue_base.hpp>
0037 #include <boost/asio/detail/timer_queue_set.hpp>
0038 #include <boost/asio/detail/wait_op.hpp>
0039 #include <boost/asio/execution_context.hpp>
0040 
0041 #if defined(BOOST_ASIO_HAS_IOCP)
0042 # include <boost/asio/detail/thread.hpp>
0043 #endif // defined(BOOST_ASIO_HAS_IOCP)
0044 
0045 #include <boost/asio/detail/push_options.hpp>
0046 
0047 namespace boost {
0048 namespace asio {
0049 namespace detail {
0050 
0051 class select_reactor
0052   : public execution_context_service_base<select_reactor>
0053 #if !defined(BOOST_ASIO_HAS_IOCP)
0054     , public scheduler_task
0055 #endif // !defined(BOOST_ASIO_HAS_IOCP)
0056 {
0057 public:
0058 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0059   enum op_types { read_op = 0, write_op = 1, except_op = 2,
0060     max_select_ops = 3, connect_op = 3, max_ops = 4 };
0061 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0062   enum op_types { read_op = 0, write_op = 1, except_op = 2,
0063     max_select_ops = 3, connect_op = 1, max_ops = 3 };
0064 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0065 
0066   // Per-descriptor data.
0067   struct per_descriptor_data
0068   {
0069   };
0070 
0071   // Constructor.
0072   BOOST_ASIO_DECL select_reactor(boost::asio::execution_context& ctx);
0073 
0074   // Destructor.
0075   BOOST_ASIO_DECL ~select_reactor();
0076 
0077   // Destroy all user-defined handler objects owned by the service.
0078   BOOST_ASIO_DECL void shutdown();
0079 
0080   // Recreate internal descriptors following a fork.
0081   BOOST_ASIO_DECL void notify_fork(
0082       boost::asio::execution_context::fork_event fork_ev);
0083 
0084   // Initialise the task, but only if the reactor is not in its own thread.
0085   BOOST_ASIO_DECL void init_task();
0086 
0087   // Register a socket with the reactor. Returns 0 on success, system error
0088   // code on failure.
0089   BOOST_ASIO_DECL int register_descriptor(socket_type, per_descriptor_data&);
0090 
0091   // Register a descriptor with an associated single operation. Returns 0 on
0092   // success, system error code on failure.
0093   BOOST_ASIO_DECL int register_internal_descriptor(
0094       int op_type, socket_type descriptor,
0095       per_descriptor_data& descriptor_data, reactor_op* op);
0096 
0097   // Post a reactor operation for immediate completion.
0098   void post_immediate_completion(operation* op, bool is_continuation) const;
0099 
0100   // Post a reactor operation for immediate completion.
0101   BOOST_ASIO_DECL static void call_post_immediate_completion(
0102       operation* op, bool is_continuation, const void* self);
0103 
0104   // Start a new operation. The reactor operation will be performed when the
0105   // given descriptor is flagged as ready, or an error has occurred.
0106   BOOST_ASIO_DECL void start_op(int op_type, socket_type descriptor,
0107       per_descriptor_data&, reactor_op* op, bool is_continuation, bool,
0108       void (*on_immediate)(operation*, bool, const void*),
0109       const void* immediate_arg);
0110 
0111   // Start a new operation. The reactor operation will be performed when the
0112   // given descriptor is flagged as ready, or an error has occurred.
0113   void start_op(int op_type, socket_type descriptor,
0114       per_descriptor_data& descriptor_data, reactor_op* op,
0115       bool is_continuation, bool allow_speculative)
0116   {
0117     start_op(op_type, descriptor, descriptor_data,
0118         op, is_continuation, allow_speculative,
0119         &select_reactor::call_post_immediate_completion, this);
0120   }
0121 
0122   // Cancel all operations associated with the given descriptor. The
0123   // handlers associated with the descriptor will be invoked with the
0124   // operation_aborted error.
0125   BOOST_ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&);
0126 
0127   // Cancel all operations associated with the given descriptor and key. The
0128   // handlers associated with the descriptor will be invoked with the
0129   // operation_aborted error.
0130   BOOST_ASIO_DECL void cancel_ops_by_key(socket_type descriptor,
0131       per_descriptor_data& descriptor_data,
0132       int op_type, void* cancellation_key);
0133 
0134   // Cancel any operations that are running against the descriptor and remove
0135   // its registration from the reactor. The reactor resources associated with
0136   // the descriptor must be released by calling cleanup_descriptor_data.
0137   BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor,
0138       per_descriptor_data&, bool closing);
0139 
0140   // Remove the descriptor's registration from the reactor. The reactor
0141   // resources associated with the descriptor must be released by calling
0142   // cleanup_descriptor_data.
0143   BOOST_ASIO_DECL void deregister_internal_descriptor(
0144       socket_type descriptor, per_descriptor_data&);
0145 
0146   // Perform any post-deregistration cleanup tasks associated with the
0147   // descriptor data.
0148   BOOST_ASIO_DECL void cleanup_descriptor_data(per_descriptor_data&);
0149 
0150   // Move descriptor registration from one descriptor_data object to another.
0151   BOOST_ASIO_DECL void move_descriptor(socket_type descriptor,
0152       per_descriptor_data& target_descriptor_data,
0153       per_descriptor_data& source_descriptor_data);
0154 
0155   // Add a new timer queue to the reactor.
0156   template <typename Time_Traits>
0157   void add_timer_queue(timer_queue<Time_Traits>& queue);
0158 
0159   // Remove a timer queue from the reactor.
0160   template <typename Time_Traits>
0161   void remove_timer_queue(timer_queue<Time_Traits>& queue);
0162 
0163   // Schedule a new operation in the given timer queue to expire at the
0164   // specified absolute time.
0165   template <typename Time_Traits>
0166   void schedule_timer(timer_queue<Time_Traits>& queue,
0167       const typename Time_Traits::time_type& time,
0168       typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);
0169 
0170   // Cancel the timer operations associated with the given token. Returns the
0171   // number of operations that have been posted or dispatched.
0172   template <typename Time_Traits>
0173   std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
0174       typename timer_queue<Time_Traits>::per_timer_data& timer,
0175       std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
0176 
0177   // Cancel the timer operations associated with the given key.
0178   template <typename Time_Traits>
0179   void cancel_timer_by_key(timer_queue<Time_Traits>& queue,
0180       typename timer_queue<Time_Traits>::per_timer_data* timer,
0181       void* cancellation_key);
0182 
0183   // Move the timer operations associated with the given timer.
0184   template <typename Time_Traits>
0185   void move_timer(timer_queue<Time_Traits>& queue,
0186       typename timer_queue<Time_Traits>::per_timer_data& target,
0187       typename timer_queue<Time_Traits>::per_timer_data& source);
0188 
0189   // Run select once until interrupted or events are ready to be dispatched.
0190   BOOST_ASIO_DECL void run(long usec, op_queue<operation>& ops);
0191 
0192   // Interrupt the select loop.
0193   BOOST_ASIO_DECL void interrupt();
0194 
0195 private:
0196 #if defined(BOOST_ASIO_HAS_IOCP)
0197   // Run the select loop in the thread.
0198   BOOST_ASIO_DECL void run_thread();
0199 #endif // defined(BOOST_ASIO_HAS_IOCP)
0200 
0201   // Helper function to add a new timer queue.
0202   BOOST_ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
0203 
0204   // Helper function to remove a timer queue.
0205   BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
0206 
0207   // Get the timeout value for the select call.
0208   BOOST_ASIO_DECL timeval* get_timeout(long usec, timeval& tv);
0209 
0210   // Cancel all operations associated with the given descriptor. This function
0211   // does not acquire the select_reactor's mutex.
0212   BOOST_ASIO_DECL void cancel_ops_unlocked(socket_type descriptor,
0213       const boost::system::error_code& ec);
0214 
0215   // The scheduler implementation used to post completions.
0216 # if defined(BOOST_ASIO_HAS_IOCP)
0217   typedef class win_iocp_io_context scheduler_type;
0218 # else // defined(BOOST_ASIO_HAS_IOCP)
0219   typedef class scheduler scheduler_type;
0220 # endif // defined(BOOST_ASIO_HAS_IOCP)
0221   scheduler_type& scheduler_;
0222 
0223   // Mutex to protect access to internal data.
0224   boost::asio::detail::mutex mutex_;
0225 
0226   // The interrupter is used to break a blocking select call.
0227   select_interrupter interrupter_;
0228 
0229   // The queues of read, write and except operations.
0230   reactor_op_queue<socket_type> op_queue_[max_ops];
0231 
0232   // The file descriptor sets to be passed to the select system call.
0233   fd_set_adapter fd_sets_[max_select_ops];
0234 
0235   // The timer queues.
0236   timer_queue_set timer_queues_;
0237 
0238 #if defined(BOOST_ASIO_HAS_IOCP)
0239   // Helper class to run the reactor loop in a thread.
0240   class thread_function;
0241   friend class thread_function;
0242 
0243   // Does the reactor loop thread need to stop.
0244   bool stop_thread_;
0245 
0246   // The thread that is running the reactor loop.
0247   boost::asio::detail::thread* thread_;
0248 
0249   // Helper class to join and restart the reactor thread.
0250   class restart_reactor : public operation
0251   {
0252   public:
0253     restart_reactor(select_reactor* r)
0254       : operation(&restart_reactor::do_complete),
0255         reactor_(r)
0256     {
0257     }
0258 
0259     BOOST_ASIO_DECL static void do_complete(void* owner, operation* base,
0260         const boost::system::error_code& ec, std::size_t bytes_transferred);
0261 
0262   private:
0263     select_reactor* reactor_;
0264   };
0265 
0266   friend class restart_reactor;
0267 
0268   // Operation used to join and restart the reactor thread.
0269   restart_reactor restart_reactor_;
0270 #endif // defined(BOOST_ASIO_HAS_IOCP)
0271 
0272   // Whether the service has been shut down.
0273   bool shutdown_;
0274 };
0275 
0276 } // namespace detail
0277 } // namespace asio
0278 } // namespace boost
0279 
0280 #include <boost/asio/detail/pop_options.hpp>
0281 
0282 #include <boost/asio/detail/impl/select_reactor.hpp>
0283 #if defined(BOOST_ASIO_HEADER_ONLY)
0284 # include <boost/asio/detail/impl/select_reactor.ipp>
0285 #endif // defined(BOOST_ASIO_HEADER_ONLY)
0286 
0287 #endif // defined(BOOST_ASIO_HAS_IOCP)
0288        //   || (!defined(BOOST_ASIO_HAS_DEV_POLL)
0289        //       && !defined(BOOST_ASIO_HAS_EPOLL)
0290        //       && !defined(BOOST_ASIO_HAS_KQUEUE)
0291        //       && !defined(BOOST_ASIO_WINDOWS_RUNTIME))
0292 
0293 #endif // BOOST_ASIO_DETAIL_SELECT_REACTOR_HPP