]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // detail/task_io_service.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 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. | |
79 | void work_started() | |
80 | { | |
81 | ++outstanding_work_; | |
82 | } | |
83 | ||
84 | // Notify that some work has finished. | |
85 | void work_finished() | |
86 | { | |
87 | if (--outstanding_work_ == 0) | |
88 | stop(); | |
89 | } | |
90 | ||
91 | // Return whether a handler can be dispatched immediately. | |
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 | { | |
168 | 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 |