1 // 2 // detail/dev_poll_reactor.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef ASIO_DETAIL_DEV_POLL_REACTOR_HPP 12 #define ASIO_DETAIL_DEV_POLL_REACTOR_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include "asio/detail/config.hpp" 19 20 #if defined(ASIO_HAS_DEV_POLL) 21 22 #include <cstddef> 23 #include <vector> 24 #include <sys/devpoll.h> 25 #include "asio/detail/hash_map.hpp" 26 #include "asio/detail/limits.hpp" 27 #include "asio/detail/mutex.hpp" 28 #include "asio/detail/op_queue.hpp" 29 #include "asio/detail/reactor_op.hpp" 30 #include "asio/detail/reactor_op_queue.hpp" 31 #include "asio/detail/select_interrupter.hpp" 32 #include "asio/detail/socket_types.hpp" 33 #include "asio/detail/timer_queue_base.hpp" 34 #include "asio/detail/timer_queue_set.hpp" 35 #include "asio/detail/wait_op.hpp" 36 #include "asio/io_service.hpp" 37 38 #include "asio/detail/push_options.hpp" 39 40 namespace asio { 41 namespace detail { 42 43 class dev_poll_reactor 44 : public asio::detail::service_base<dev_poll_reactor> 45 { 46 public: 47 enum op_types { read_op = 0, write_op = 1, 48 connect_op = 1, except_op = 2, max_ops = 3 }; 49 50 // Per-descriptor data. 51 struct per_descriptor_data 52 { 53 }; 54 55 // Constructor. 56 ASIO_DECL dev_poll_reactor(asio::io_service& io_service); 57 58 // Destructor. 59 ASIO_DECL ~dev_poll_reactor(); 60 61 // Destroy all user-defined handler objects owned by the service. 62 ASIO_DECL void shutdown_service(); 63 64 // Recreate internal descriptors following a fork. 65 ASIO_DECL void fork_service( 66 asio::io_service::fork_event fork_ev); 67 68 // Initialise the task. 69 ASIO_DECL void init_task(); 70 71 // Register a socket with the reactor. Returns 0 on success, system error 72 // code on failure. 73 ASIO_DECL int register_descriptor(socket_type, per_descriptor_data&); 74 75 // Register a descriptor with an associated single operation. Returns 0 on 76 // success, system error code on failure. 77 ASIO_DECL int register_internal_descriptor( 78 int op_type, socket_type descriptor, 79 per_descriptor_data& descriptor_data, reactor_op* op); 80 81 // Move descriptor registration from one descriptor_data object to another. 82 ASIO_DECL void move_descriptor(socket_type descriptor, 83 per_descriptor_data& target_descriptor_data, 84 per_descriptor_data& source_descriptor_data); 85 86 // Post a reactor operation for immediate completion. post_immediate_completion(reactor_op * op,bool is_continuation)87 void post_immediate_completion(reactor_op* op, bool is_continuation) 88 { 89 io_service_.post_immediate_completion(op, is_continuation); 90 } 91 92 // Start a new operation. The reactor operation will be performed when the 93 // given descriptor is flagged as ready, or an error has occurred. 94 ASIO_DECL void start_op(int op_type, socket_type descriptor, 95 per_descriptor_data&, reactor_op* op, 96 bool is_continuation, bool allow_speculative); 97 98 // Cancel all operations associated with the given descriptor. The 99 // handlers associated with the descriptor will be invoked with the 100 // operation_aborted error. 101 ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&); 102 103 // Cancel any operations that are running against the descriptor and remove 104 // its registration from the reactor. 105 ASIO_DECL void deregister_descriptor(socket_type descriptor, 106 per_descriptor_data&, bool closing); 107 108 // Cancel any operations that are running against the descriptor and remove 109 // its registration from the reactor. 110 ASIO_DECL void deregister_internal_descriptor( 111 socket_type descriptor, per_descriptor_data&); 112 113 // Add a new timer queue to the reactor. 114 template <typename Time_Traits> 115 void add_timer_queue(timer_queue<Time_Traits>& queue); 116 117 // Remove a timer queue from the reactor. 118 template <typename Time_Traits> 119 void remove_timer_queue(timer_queue<Time_Traits>& queue); 120 121 // Schedule a new operation in the given timer queue to expire at the 122 // specified absolute time. 123 template <typename Time_Traits> 124 void schedule_timer(timer_queue<Time_Traits>& queue, 125 const typename Time_Traits::time_type& time, 126 typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op); 127 128 // Cancel the timer operations associated with the given token. Returns the 129 // number of operations that have been posted or dispatched. 130 template <typename Time_Traits> 131 std::size_t cancel_timer(timer_queue<Time_Traits>& queue, 132 typename timer_queue<Time_Traits>::per_timer_data& timer, 133 std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)()); 134 135 // Run /dev/poll once until interrupted or events are ready to be dispatched. 136 ASIO_DECL void run(bool block, op_queue<operation>& ops); 137 138 // Interrupt the select loop. 139 ASIO_DECL void interrupt(); 140 141 private: 142 // Create the /dev/poll file descriptor. Throws an exception if the descriptor 143 // cannot be created. 144 ASIO_DECL static int do_dev_poll_create(); 145 146 // Helper function to add a new timer queue. 147 ASIO_DECL void do_add_timer_queue(timer_queue_base& queue); 148 149 // Helper function to remove a timer queue. 150 ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue); 151 152 // Get the timeout value for the /dev/poll DP_POLL operation. The timeout 153 // value is returned as a number of milliseconds. A return value of -1 154 // indicates that the poll should block indefinitely. 155 ASIO_DECL int get_timeout(); 156 157 // Cancel all operations associated with the given descriptor. The do_cancel 158 // function of the handler objects will be invoked. This function does not 159 // acquire the dev_poll_reactor's mutex. 160 ASIO_DECL void cancel_ops_unlocked(socket_type descriptor, 161 const asio::error_code& ec); 162 163 // Add a pending event entry for the given descriptor. 164 ASIO_DECL ::pollfd& add_pending_event_change(int descriptor); 165 166 // The io_service implementation used to post completions. 167 io_service_impl& io_service_; 168 169 // Mutex to protect access to internal data. 170 asio::detail::mutex mutex_; 171 172 // The /dev/poll file descriptor. 173 int dev_poll_fd_; 174 175 // Vector of /dev/poll events waiting to be written to the descriptor. 176 std::vector< ::pollfd> pending_event_changes_; 177 178 // Hash map to associate a descriptor with a pending event change index. 179 hash_map<int, std::size_t> pending_event_change_index_; 180 181 // The interrupter is used to break a blocking DP_POLL operation. 182 select_interrupter interrupter_; 183 184 // The queues of read, write and except operations. 185 reactor_op_queue<socket_type> op_queue_[max_ops]; 186 187 // The timer queues. 188 timer_queue_set timer_queues_; 189 190 // Whether the service has been shut down. 191 bool shutdown_; 192 }; 193 194 } // namespace detail 195 } // namespace asio 196 197 #include "asio/detail/pop_options.hpp" 198 199 #include "asio/detail/impl/dev_poll_reactor.hpp" 200 #if defined(ASIO_HEADER_ONLY) 201 # include "asio/detail/impl/dev_poll_reactor.ipp" 202 #endif // defined(ASIO_HEADER_ONLY) 203 204 #endif // defined(ASIO_HAS_DEV_POLL) 205 206 #endif // ASIO_DETAIL_DEV_POLL_REACTOR_HPP 207