Clementine
scheduler.hpp
1 //
2 // detail/scheduler.hpp
3 // ~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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_SCHEDULER_HPP
12 #define ASIO_DETAIL_SCHEDULER_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include "asio/detail/config.hpp"
19 
20 #include "asio/error_code.hpp"
21 #include "asio/execution_context.hpp"
22 #include "asio/detail/atomic_count.hpp"
23 #include "asio/detail/conditionally_enabled_event.hpp"
24 #include "asio/detail/conditionally_enabled_mutex.hpp"
25 #include "asio/detail/op_queue.hpp"
26 #include "asio/detail/reactor_fwd.hpp"
27 #include "asio/detail/scheduler_operation.hpp"
28 #include "asio/detail/thread.hpp"
29 #include "asio/detail/thread_context.hpp"
30 
31 #include "asio/detail/push_options.hpp"
32 
33 namespace asio {
34 namespace detail {
35 
36 struct scheduler_thread_info;
37 
38 class scheduler
39  : public execution_context_service_base<scheduler>,
40  public thread_context
41 {
42 public:
43  typedef scheduler_operation operation;
44 
45  // Constructor. Specifies the number of concurrent threads that are likely to
46  // run the scheduler. If set to 1 certain optimisation are performed.
47  ASIO_DECL scheduler(asio::execution_context& ctx,
48  int concurrency_hint = 0, bool own_thread = true);
49 
50  // Destructor.
51  ASIO_DECL ~scheduler();
52 
53  // Destroy all user-defined handler objects owned by the service.
54  ASIO_DECL void shutdown();
55 
56  // Initialise the task, if required.
57  ASIO_DECL void init_task();
58 
59  // Run the event loop until interrupted or no more work.
60  ASIO_DECL std::size_t run(asio::error_code& ec);
61 
62  // Run until interrupted or one operation is performed.
63  ASIO_DECL std::size_t run_one(asio::error_code& ec);
64 
65  // Run until timeout, interrupted, or one operation is performed.
66  ASIO_DECL std::size_t wait_one(
67  long usec, asio::error_code& ec);
68 
69  // Poll for operations without blocking.
70  ASIO_DECL std::size_t poll(asio::error_code& ec);
71 
72  // Poll for one operation without blocking.
73  ASIO_DECL std::size_t poll_one(asio::error_code& ec);
74 
75  // Interrupt the event processing loop.
76  ASIO_DECL void stop();
77 
78  // Determine whether the scheduler is stopped.
79  ASIO_DECL bool stopped() const;
80 
81  // Restart in preparation for a subsequent run invocation.
82  ASIO_DECL void restart();
83 
84  // Notify that some work has started.
85  void work_started()
86  {
87  ++outstanding_work_;
88  }
89 
90  // Used to compensate for a forthcoming work_finished call. Must be called
91  // from within a scheduler-owned thread.
92  ASIO_DECL void compensating_work_started();
93 
94  // Notify that some work has finished.
95  void work_finished()
96  {
97  if (--outstanding_work_ == 0)
98  stop();
99  }
100 
101  // Return whether a handler can be dispatched immediately.
102  bool can_dispatch()
103  {
104  return thread_call_stack::contains(this) != 0;
105  }
106 
108  ASIO_DECL void capture_current_exception();
109 
110  // Request invocation of the given operation and return immediately. Assumes
111  // that work_started() has not yet been called for the operation.
112  ASIO_DECL void post_immediate_completion(
113  operation* op, bool is_continuation);
114 
115  // Request invocation of the given operations and return immediately. Assumes
116  // that work_started() has not yet been called for the operations.
117  ASIO_DECL void post_immediate_completions(std::size_t n,
118  op_queue<operation>& ops, bool is_continuation);
119 
120  // Request invocation of the given operation and return immediately. Assumes
121  // that work_started() was previously called for the operation.
122  ASIO_DECL void post_deferred_completion(operation* op);
123 
124  // Request invocation of the given operations and return immediately. Assumes
125  // that work_started() was previously called for each operation.
126  ASIO_DECL void post_deferred_completions(op_queue<operation>& ops);
127 
128  // Enqueue the given operation following a failed attempt to dispatch the
129  // operation for immediate invocation.
130  ASIO_DECL void do_dispatch(operation* op);
131 
132  // Process unfinished operations as part of a shutdownoperation. Assumes that
133  // work_started() was previously called for the operations.
134  ASIO_DECL void abandon_operations(op_queue<operation>& ops);
135 
136  // Get the concurrency hint that was used to initialise the scheduler.
137  int concurrency_hint() const
138  {
139  return concurrency_hint_;
140  }
141 
142 private:
143  // The mutex type used by this scheduler.
145 
146  // The event type used by this scheduler.
148 
149  // Structure containing thread-specific data.
151 
152  // Run at most one operation. May block.
153  ASIO_DECL std::size_t do_run_one(mutex::scoped_lock& lock,
154  thread_info& this_thread, const asio::error_code& ec);
155 
156  // Run at most one operation with a timeout. May block.
157  ASIO_DECL std::size_t do_wait_one(mutex::scoped_lock& lock,
158  thread_info& this_thread, long usec, const asio::error_code& ec);
159 
160  // Poll for at most one operation.
161  ASIO_DECL std::size_t do_poll_one(mutex::scoped_lock& lock,
162  thread_info& this_thread, const asio::error_code& ec);
163 
164  // Stop the task and all idle threads.
165  ASIO_DECL void stop_all_threads(mutex::scoped_lock& lock);
166 
167  // Wake a single idle thread, or the task, and always unlock the mutex.
168  ASIO_DECL void wake_one_thread_and_unlock(
169  mutex::scoped_lock& lock);
170 
171  // Helper class to run the scheduler in its own thread.
172  class thread_function;
173  friend class thread_function;
174 
175  // Helper class to perform task-related operations on block exit.
176  struct task_cleanup;
177  friend struct task_cleanup;
178 
179  // Helper class to call work-related operations on block exit.
180  struct work_cleanup;
181  friend struct work_cleanup;
182 
183  // Whether to optimise for single-threaded use cases.
184  const bool one_thread_;
185 
186  // Mutex to protect access to internal data.
187  mutable mutex mutex_;
188 
189  // Event to wake up blocked threads.
190  event wakeup_event_;
191 
192  // The task to be run by this service.
193  reactor* task_;
194 
195  // Operation object to represent the position of the task in the queue.
196  struct task_operation : operation
197  {
198  task_operation() : operation(0) {}
199  } task_operation_;
200 
201  // Whether the task has been interrupted.
202  bool task_interrupted_;
203 
204  // The count of unfinished work.
205  atomic_count outstanding_work_;
206 
207  // The queue of handlers that are ready to be delivered.
208  op_queue<operation> op_queue_;
209 
210  // Flag to indicate that the dispatcher has been stopped.
211  bool stopped_;
212 
213  // Flag to indicate that the dispatcher has been shut down.
214  bool shutdown_;
215 
216  // The concurrency hint used to initialise the scheduler.
217  const int concurrency_hint_;
218 
219  // The thread that is running the scheduler.
220  asio::detail::thread* thread_;
221 };
222 
223 } // namespace detail
224 } // namespace asio
225 
226 #include "asio/detail/pop_options.hpp"
227 
228 #if defined(ASIO_HEADER_ONLY)
229 # include "asio/detail/impl/scheduler.ipp"
230 #endif // defined(ASIO_HEADER_ONLY)
231 
232 #endif // ASIO_DETAIL_SCHEDULER_HPP
Definition: scheduler.ipp:33
Definition: conditionally_enabled_event.hpp:31
Definition: scheduler.ipp:51
Definition: scheduler_thread_info.hpp:29
Definition: execution_context.hpp:386
A context for function object execution.
Definition: execution_context.hpp:105
ASIO_DECL void capture_current_exception()
Capture the current exception so it can be rethrown from a run function.
Definition: scheduler.ipp:327
Definition: thread_context.hpp:30
Definition: conditionally_enabled_mutex.hpp:29
Definition: chrono.h:284
Definition: conditionally_enabled_mutex.hpp:34
Class to represent an error code value.
Definition: error_code.hpp:80
ASIO_DECL void shutdown()
Destroy all user-defined handler objects owned by the service.
Definition: scheduler.ipp:147
Definition: scheduler.ipp:76
Definition: null_thread.hpp:31
Definition: any_io_executor.hpp:28
Definition: scheduler.hpp:38