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