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