1    	//
2    	// detail/epoll_reactor.hpp
3    	// ~~~~~~~~~~~~~~~~~~~~~~~~
4    	//
5    	// Copyright (c) 2003-2018 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 BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP
12   	#define BOOST_ASIO_DETAIL_EPOLL_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 <boost/asio/detail/config.hpp>
19   	
20   	#if defined(BOOST_ASIO_HAS_EPOLL)
21   	
22   	#include <boost/asio/detail/atomic_count.hpp>
23   	#include <boost/asio/detail/conditionally_enabled_mutex.hpp>
24   	#include <boost/asio/detail/limits.hpp>
25   	#include <boost/asio/detail/object_pool.hpp>
26   	#include <boost/asio/detail/op_queue.hpp>
27   	#include <boost/asio/detail/reactor_op.hpp>
28   	#include <boost/asio/detail/select_interrupter.hpp>
29   	#include <boost/asio/detail/socket_types.hpp>
30   	#include <boost/asio/detail/timer_queue_base.hpp>
31   	#include <boost/asio/detail/timer_queue_set.hpp>
32   	#include <boost/asio/detail/wait_op.hpp>
33   	#include <boost/asio/execution_context.hpp>
34   	
35   	#if defined(BOOST_ASIO_HAS_TIMERFD)
36   	# include <sys/timerfd.h>
37   	#endif // defined(BOOST_ASIO_HAS_TIMERFD)
38   	
39   	#include <boost/asio/detail/push_options.hpp>
40   	
41   	namespace boost {
42   	namespace asio {
43   	namespace detail {
44   	
45   	class epoll_reactor
46   	  : public execution_context_service_base<epoll_reactor>
47   	{
48   	private:
49   	  // The mutex type used by this reactor.
50   	  typedef conditionally_enabled_mutex mutex;
51   	
52   	public:
53   	  enum op_types { read_op = 0, write_op = 1,
54   	    connect_op = 1, except_op = 2, max_ops = 3 };
55   	
56   	  // Per-descriptor queues.
57   	  class descriptor_state : operation
58   	  {
59   	    friend class epoll_reactor;
60   	    friend class object_pool_access;
61   	
(6) Event member_decl: Class member declaration for "next_".
Also see events: [uninit_member][member_decl][uninit_member][member_decl][uninit_member][member_decl][uninit_member][member_decl][uninit_member][member_decl][uninit_member]
62   	    descriptor_state* next_;
(8) Event member_decl: Class member declaration for "prev_".
Also see events: [member_decl][uninit_member][uninit_member][member_decl][uninit_member][member_decl][uninit_member][member_decl][uninit_member][member_decl][uninit_member]
63   	    descriptor_state* prev_;
64   	
65   	    mutex mutex_;
(10) Event member_decl: Class member declaration for "reactor_".
Also see events: [member_decl][uninit_member][member_decl][uninit_member][uninit_member][member_decl][uninit_member][member_decl][uninit_member][member_decl][uninit_member]
66   	    epoll_reactor* reactor_;
(12) Event member_decl: Class member declaration for "descriptor_".
Also see events: [member_decl][uninit_member][member_decl][uninit_member][member_decl][uninit_member][uninit_member][member_decl][uninit_member][member_decl][uninit_member]
67   	    int descriptor_;
(14) Event member_decl: Class member declaration for "registered_events_".
Also see events: [member_decl][uninit_member][member_decl][uninit_member][member_decl][uninit_member][member_decl][uninit_member][uninit_member][member_decl][uninit_member]
68   	    uint32_t registered_events_;
69   	    op_queue<reactor_op> op_queue_[max_ops];
70   	    bool try_speculative_[max_ops];
(16) Event member_decl: Class member declaration for "shutdown_".
Also see events: [member_decl][uninit_member][member_decl][uninit_member][member_decl][uninit_member][member_decl][uninit_member][member_decl][uninit_member][uninit_member]
71   	    bool shutdown_;
72   	
73   	    BOOST_ASIO_DECL descriptor_state(bool locking);
74   	    void set_ready_events(uint32_t events) { task_result_ = events; }
75   	    void add_ready_events(uint32_t events) { task_result_ |= events; }
76   	    BOOST_ASIO_DECL operation* perform_io(uint32_t events);
77   	    BOOST_ASIO_DECL static void do_complete(
78   	        void* owner, operation* base,
79   	        const boost::system::error_code& ec, std::size_t bytes_transferred);
80   	  };
81   	
82   	  // Per-descriptor data.
83   	  typedef descriptor_state* per_descriptor_data;
84   	
85   	  // Constructor.
86   	  BOOST_ASIO_DECL epoll_reactor(boost::asio::execution_context& ctx);
87   	
88   	  // Destructor.
89   	  BOOST_ASIO_DECL ~epoll_reactor();
90   	
91   	  // Destroy all user-defined handler objects owned by the service.
92   	  BOOST_ASIO_DECL void shutdown();
93   	
94   	  // Recreate internal descriptors following a fork.
95   	  BOOST_ASIO_DECL void notify_fork(
96   	      boost::asio::execution_context::fork_event fork_ev);
97   	
98   	  // Initialise the task.
99   	  BOOST_ASIO_DECL void init_task();
100  	
101  	  // Register a socket with the reactor. Returns 0 on success, system error
102  	  // code on failure.
103  	  BOOST_ASIO_DECL int register_descriptor(socket_type descriptor,
104  	      per_descriptor_data& descriptor_data);
105  	
106  	  // Register a descriptor with an associated single operation. Returns 0 on
107  	  // success, system error code on failure.
108  	  BOOST_ASIO_DECL int register_internal_descriptor(
109  	      int op_type, socket_type descriptor,
110  	      per_descriptor_data& descriptor_data, reactor_op* op);
111  	
112  	  // Move descriptor registration from one descriptor_data object to another.
113  	  BOOST_ASIO_DECL void move_descriptor(socket_type descriptor,
114  	      per_descriptor_data& target_descriptor_data,
115  	      per_descriptor_data& source_descriptor_data);
116  	
117  	  // Post a reactor operation for immediate completion.
118  	  void post_immediate_completion(reactor_op* op, bool is_continuation)
119  	  {
120  	    scheduler_.post_immediate_completion(op, is_continuation);
121  	  }
122  	
123  	  // Start a new operation. The reactor operation will be performed when the
124  	  // given descriptor is flagged as ready, or an error has occurred.
125  	  BOOST_ASIO_DECL void start_op(int op_type, socket_type descriptor,
126  	      per_descriptor_data& descriptor_data, reactor_op* op,
127  	      bool is_continuation, bool allow_speculative);
128  	
129  	  // Cancel all operations associated with the given descriptor. The
130  	  // handlers associated with the descriptor will be invoked with the
131  	  // operation_aborted error.
132  	  BOOST_ASIO_DECL void cancel_ops(socket_type descriptor,
133  	      per_descriptor_data& descriptor_data);
134  	
135  	  // Cancel any operations that are running against the descriptor and remove
136  	  // its registration from the reactor. The reactor resources associated with
137  	  // the descriptor must be released by calling cleanup_descriptor_data.
138  	  BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor,
139  	      per_descriptor_data& descriptor_data, bool closing);
140  	
141  	  // Remove the descriptor's registration from the reactor. The reactor
142  	  // resources associated with the descriptor must be released by calling
143  	  // cleanup_descriptor_data.
144  	  BOOST_ASIO_DECL void deregister_internal_descriptor(
145  	      socket_type descriptor, per_descriptor_data& descriptor_data);
146  	
147  	  // Perform any post-deregistration cleanup tasks associated with the
148  	  // descriptor data.
149  	  BOOST_ASIO_DECL void cleanup_descriptor_data(
150  	      per_descriptor_data& descriptor_data);
151  	
152  	  // Add a new timer queue to the reactor.
153  	  template <typename Time_Traits>
154  	  void add_timer_queue(timer_queue<Time_Traits>& timer_queue);
155  	
156  	  // Remove a timer queue from the reactor.
157  	  template <typename Time_Traits>
158  	  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue);
159  	
160  	  // Schedule a new operation in the given timer queue to expire at the
161  	  // specified absolute time.
162  	  template <typename Time_Traits>
163  	  void schedule_timer(timer_queue<Time_Traits>& queue,
164  	      const typename Time_Traits::time_type& time,
165  	      typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);
166  	
167  	  // Cancel the timer operations associated with the given token. Returns the
168  	  // number of operations that have been posted or dispatched.
169  	  template <typename Time_Traits>
170  	  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
171  	      typename timer_queue<Time_Traits>::per_timer_data& timer,
172  	      std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
173  	
174  	  // Move the timer operations associated with the given timer.
175  	  template <typename Time_Traits>
176  	  void move_timer(timer_queue<Time_Traits>& queue,
177  	      typename timer_queue<Time_Traits>::per_timer_data& target,
178  	      typename timer_queue<Time_Traits>::per_timer_data& source);
179  	
180  	  // Run epoll once until interrupted or events are ready to be dispatched.
181  	  BOOST_ASIO_DECL void run(long usec, op_queue<operation>& ops);
182  	
183  	  // Interrupt the select loop.
184  	  BOOST_ASIO_DECL void interrupt();
185  	
186  	private:
187  	  // The hint to pass to epoll_create to size its data structures.
188  	  enum { epoll_size = 20000 };
189  	
190  	  // Create the epoll file descriptor. Throws an exception if the descriptor
191  	  // cannot be created.
192  	  BOOST_ASIO_DECL static int do_epoll_create();
193  	
194  	  // Create the timerfd file descriptor. Does not throw.
195  	  BOOST_ASIO_DECL static int do_timerfd_create();
196  	
197  	  // Allocate a new descriptor state object.
198  	  BOOST_ASIO_DECL descriptor_state* allocate_descriptor_state();
199  	
200  	  // Free an existing descriptor state object.
201  	  BOOST_ASIO_DECL void free_descriptor_state(descriptor_state* s);
202  	
203  	  // Helper function to add a new timer queue.
204  	  BOOST_ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
205  	
206  	  // Helper function to remove a timer queue.
207  	  BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
208  	
209  	  // Called to recalculate and update the timeout.
210  	  BOOST_ASIO_DECL void update_timeout();
211  	
212  	  // Get the timeout value for the epoll_wait call. The timeout value is
213  	  // returned as a number of milliseconds. A return value of -1 indicates
214  	  // that epoll_wait should block indefinitely.
215  	  BOOST_ASIO_DECL int get_timeout(int msec);
216  	
217  	#if defined(BOOST_ASIO_HAS_TIMERFD)
218  	  // Get the timeout value for the timer descriptor. The return value is the
219  	  // flag argument to be used when calling timerfd_settime.
220  	  BOOST_ASIO_DECL int get_timeout(itimerspec& ts);
221  	#endif // defined(BOOST_ASIO_HAS_TIMERFD)
222  	
223  	  // The scheduler implementation used to post completions.
224  	  scheduler& scheduler_;
225  	
226  	  // Mutex to protect access to internal data.
227  	  mutex mutex_;
228  	
229  	  // The interrupter is used to break a blocking epoll_wait call.
230  	  select_interrupter interrupter_;
231  	
232  	  // The epoll file descriptor.
233  	  int epoll_fd_;
234  	
235  	  // The timer file descriptor.
236  	  int timer_fd_;
237  	
238  	  // The timer queues.
239  	  timer_queue_set timer_queues_;
240  	
241  	  // Whether the service has been shut down.
242  	  bool shutdown_;
243  	
244  	  // Mutex to protect access to the registered descriptors.
245  	  mutex registered_descriptors_mutex_;
246  	
247  	  // Keep track of all registered descriptors.
248  	  object_pool<descriptor_state> registered_descriptors_;
249  	
250  	  // Helper class to do post-perform_io cleanup.
251  	  struct perform_io_cleanup_on_block_exit;
252  	  friend struct perform_io_cleanup_on_block_exit;
253  	};
254  	
255  	} // namespace detail
256  	} // namespace asio
257  	} // namespace boost
258  	
259  	#include <boost/asio/detail/pop_options.hpp>
260  	
261  	#include <boost/asio/detail/impl/epoll_reactor.hpp>
262  	#if defined(BOOST_ASIO_HEADER_ONLY)
263  	# include <boost/asio/detail/impl/epoll_reactor.ipp>
264  	#endif // defined(BOOST_ASIO_HEADER_ONLY)
265  	
266  	#endif // defined(BOOST_ASIO_HAS_EPOLL)
267  	
268  	#endif // BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP
269