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
30namespace asio {
31namespace detail {
32
33struct task_io_service_thread_info;
34
35class task_io_service
36  : public asio::detail::service_base<task_io_service>
37{
38public:
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
117private:
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