1 // 2 // detail/task_io_service.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_TASK_IO_SERVICE_HPP 12 #define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_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_IOCP) 21 22 #include <boost/system/error_code.hpp> 23 #include <boost/asio/io_service.hpp> 24 #include <boost/asio/detail/atomic_count.hpp> 25 #include <boost/asio/detail/call_stack.hpp> 26 #include <boost/asio/detail/event.hpp> 27 #include <boost/asio/detail/mutex.hpp> 28 #include <boost/asio/detail/op_queue.hpp> 29 #include <boost/asio/detail/reactor_fwd.hpp> 30 #include <boost/asio/detail/task_io_service_operation.hpp> 31 32 #include <boost/asio/detail/push_options.hpp> 33 34 namespace boost { 35 namespace asio { 36 namespace detail { 37 38 struct task_io_service_thread_info; 39 40 class task_io_service 41 : public boost::asio::detail::service_base<task_io_service> 42 { 43 public: 44 typedef task_io_service_operation operation; 45 46 // Constructor. Specifies the number of concurrent threads that are likely to 47 // run the io_service. If set to 1 certain optimisation are performed. 48 BOOST_ASIO_DECL task_io_service(boost::asio::io_service& io_service, 49 std::size_t concurrency_hint = 0); 50 51 // Destroy all user-defined handler objects owned by the service. 52 BOOST_ASIO_DECL void shutdown_service(); 53 54 // Initialise the task, if required. 55 BOOST_ASIO_DECL void init_task(); 56 57 // Run the event loop until interrupted or no more work. 58 BOOST_ASIO_DECL std::size_t run(boost::system::error_code& ec); 59 60 // Run until interrupted or one operation is performed. 61 BOOST_ASIO_DECL std::size_t run_one(boost::system::error_code& ec); 62 63 // Poll for operations without blocking. 64 BOOST_ASIO_DECL std::size_t poll(boost::system::error_code& ec); 65 66 // Poll for one operation without blocking. 67 BOOST_ASIO_DECL std::size_t poll_one(boost::system::error_code& ec); 68 69 // Interrupt the event processing loop. 70 BOOST_ASIO_DECL void stop(); 71 72 // Determine whether the io_service is stopped. 73 BOOST_ASIO_DECL bool stopped() const; 74 75 // Reset in preparation for a subsequent run invocation. 76 BOOST_ASIO_DECL void reset(); 77 78 // Notify that some work has started. work_started()79 void work_started() 80 { 81 ++outstanding_work_; 82 } 83 84 // Notify that some work has finished. work_finished()85 void work_finished() 86 { 87 if (--outstanding_work_ == 0) 88 stop(); 89 } 90 91 // Return whether a handler can be dispatched immediately. can_dispatch()92 bool can_dispatch() 93 { 94 return thread_call_stack::contains(this) != 0; 95 } 96 97 // Request invocation of the given handler. 98 template <typename Handler> 99 void dispatch(Handler& handler); 100 101 // Request invocation of the given handler and return immediately. 102 template <typename Handler> 103 void post(Handler& handler); 104 105 // Request invocation of the given operation and return immediately. Assumes 106 // that work_started() has not yet been called for the operation. 107 BOOST_ASIO_DECL void post_immediate_completion( 108 operation* op, bool is_continuation); 109 110 // Request invocation of the given operation and return immediately. Assumes 111 // that work_started() was previously called for the operation. 112 BOOST_ASIO_DECL void post_deferred_completion(operation* op); 113 114 // Request invocation of the given operations and return immediately. Assumes 115 // that work_started() was previously called for each operation. 116 BOOST_ASIO_DECL void post_deferred_completions(op_queue<operation>& ops); 117 118 // Process unfinished operations as part of a shutdown_service operation. 119 // Assumes that work_started() was previously called for the operations. 120 BOOST_ASIO_DECL void abandon_operations(op_queue<operation>& ops); 121 122 private: 123 // Structure containing thread-specific data. 124 typedef task_io_service_thread_info thread_info; 125 126 // Enqueue the given operation following a failed attempt to dispatch the 127 // operation for immediate invocation. 128 BOOST_ASIO_DECL void do_dispatch(operation* op); 129 130 // Run at most one operation. May block. 131 BOOST_ASIO_DECL std::size_t do_run_one(mutex::scoped_lock& lock, 132 thread_info& this_thread, const boost::system::error_code& ec); 133 134 // Poll for at most one operation. 135 BOOST_ASIO_DECL std::size_t do_poll_one(mutex::scoped_lock& lock, 136 thread_info& this_thread, const boost::system::error_code& ec); 137 138 // Stop the task and all idle threads. 139 BOOST_ASIO_DECL void stop_all_threads(mutex::scoped_lock& lock); 140 141 // Wake a single idle thread, or the task, and always unlock the mutex. 142 BOOST_ASIO_DECL void wake_one_thread_and_unlock( 143 mutex::scoped_lock& lock); 144 145 // Helper class to perform task-related operations on block exit. 146 struct task_cleanup; 147 friend struct task_cleanup; 148 149 // Helper class to call work-related operations on block exit. 150 struct work_cleanup; 151 friend struct work_cleanup; 152 153 // Whether to optimise for single-threaded use cases. 154 const bool one_thread_; 155 156 // Mutex to protect access to internal data. 157 mutable mutex mutex_; 158 159 // Event to wake up blocked threads. 160 event wakeup_event_; 161 162 // The task to be run by this service. 163 reactor* task_; 164 165 // Operation object to represent the position of the task in the queue. 166 struct task_operation : operation 167 { task_operationboost::asio::detail::task_io_service::task_operation168 task_operation() : operation(0) {} 169 } task_operation_; 170 171 // Whether the task has been interrupted. 172 bool task_interrupted_; 173 174 // The count of unfinished work. 175 atomic_count outstanding_work_; 176 177 // The queue of handlers that are ready to be delivered. 178 op_queue<operation> op_queue_; 179 180 // Flag to indicate that the dispatcher has been stopped. 181 bool stopped_; 182 183 // Flag to indicate that the dispatcher has been shut down. 184 bool shutdown_; 185 186 // Per-thread call stack to track the state of each thread in the io_service. 187 typedef call_stack<task_io_service, thread_info> thread_call_stack; 188 }; 189 190 } // namespace detail 191 } // namespace asio 192 } // namespace boost 193 194 #include <boost/asio/detail/pop_options.hpp> 195 196 #include <boost/asio/detail/impl/task_io_service.hpp> 197 #if defined(BOOST_ASIO_HEADER_ONLY) 198 # include <boost/asio/detail/impl/task_io_service.ipp> 199 #endif // defined(BOOST_ASIO_HEADER_ONLY) 200 201 #endif // !defined(BOOST_ASIO_HAS_IOCP) 202 203 #endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP 204