Clementine
executor_work_guard.hpp
1 //
2 // executor_work_guard.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_EXECUTOR_WORK_GUARD_HPP
12 #define ASIO_EXECUTOR_WORK_GUARD_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 #if !defined(ASIO_NO_TS_EXECUTORS)
21 
22 #include "asio/associated_executor.hpp"
23 #include "asio/detail/type_traits.hpp"
24 #include "asio/execution.hpp"
25 #include "asio/is_executor.hpp"
26 
27 #include "asio/detail/push_options.hpp"
28 
29 namespace asio {
30 
31 #if !defined(ASIO_EXECUTOR_WORK_GUARD_DECL)
32 #define ASIO_EXECUTOR_WORK_GUARD_DECL
33 
34 template <typename Executor, typename = void>
36 
37 #endif // !defined(ASIO_EXECUTOR_WORK_GUARD_DECL)
38 
41 #if defined(GENERATING_DOCUMENTATION)
42 template <typename Executor>
43 #else // defined(GENERATING_DOCUMENTATION)
44 template <typename Executor, typename>
45 #endif // defined(GENERATING_DOCUMENTATION)
47 {
48 public:
50  typedef Executor executor_type;
51 
53 
56  explicit executor_work_guard(const executor_type& e) ASIO_NOEXCEPT
57  : executor_(e),
58  owns_(true)
59  {
60  executor_.on_work_started();
61  }
62 
64  executor_work_guard(const executor_work_guard& other) ASIO_NOEXCEPT
65  : executor_(other.executor_),
66  owns_(other.owns_)
67  {
68  if (owns_)
69  executor_.on_work_started();
70  }
71 
72 #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
73  executor_work_guard(executor_work_guard&& other) ASIO_NOEXCEPT
75  : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)),
76  owns_(other.owns_)
77  {
78  other.owns_ = false;
79  }
80 #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
81 
83 
88  {
89  if (owns_)
90  executor_.on_work_finished();
91  }
92 
94  executor_type get_executor() const ASIO_NOEXCEPT
95  {
96  return executor_;
97  }
98 
100  bool owns_work() const ASIO_NOEXCEPT
101  {
102  return owns_;
103  }
104 
106 
110  void reset() ASIO_NOEXCEPT
111  {
112  if (owns_)
113  {
114  executor_.on_work_finished();
115  owns_ = false;
116  }
117  }
118 
119 private:
120  // Disallow assignment.
121  executor_work_guard& operator=(const executor_work_guard&);
122 
123  executor_type executor_;
124  bool owns_;
125 };
126 
127 #if !defined(GENERATING_DOCUMENTATION)
128 
129 template <typename Executor>
130 class executor_work_guard<Executor,
131  typename enable_if<
132  !is_executor<Executor>::value && execution::is_executor<Executor>::value
133  >::type>
134 {
135 public:
136  typedef Executor executor_type;
137 
138  explicit executor_work_guard(const executor_type& e) ASIO_NOEXCEPT
139  : executor_(e),
140  owns_(true)
141  {
142  new (&work_) work_type(asio::prefer(executor_,
143  execution::outstanding_work.tracked));
144  }
145 
146  executor_work_guard(const executor_work_guard& other) ASIO_NOEXCEPT
147  : executor_(other.executor_),
148  owns_(other.owns_)
149  {
150  if (owns_)
151  {
152  new (&work_) work_type(asio::prefer(executor_,
153  execution::outstanding_work.tracked));
154  }
155  }
156 
157 #if defined(ASIO_HAS_MOVE)
158  executor_work_guard(executor_work_guard&& other) ASIO_NOEXCEPT
159  : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)),
160  owns_(other.owns_)
161  {
162  if (owns_)
163  {
164  new (&work_) work_type(
165  ASIO_MOVE_CAST(work_type)(
166  *static_cast<work_type*>(
167  static_cast<void*>(&other.work_))));
168  other.owns_ = false;
169  }
170  }
171 #endif // defined(ASIO_HAS_MOVE)
172 
174  {
175  if (owns_)
176  static_cast<work_type*>(static_cast<void*>(&work_))->~work_type();
177  }
178 
179  executor_type get_executor() const ASIO_NOEXCEPT
180  {
181  return executor_;
182  }
183 
184  bool owns_work() const ASIO_NOEXCEPT
185  {
186  return owns_;
187  }
188 
189  void reset() ASIO_NOEXCEPT
190  {
191  if (owns_)
192  {
193  static_cast<work_type*>(static_cast<void*>(&work_))->~work_type();
194  owns_ = false;
195  }
196  }
197 
198 private:
199  // Disallow assignment.
200  executor_work_guard& operator=(const executor_work_guard&);
201 
202  typedef typename decay<
203  typename prefer_result<
204  const executor_type&,
206  >::type
207  >::type work_type;
208 
209  executor_type executor_;
210  typename aligned_storage<sizeof(work_type),
211  alignment_of<work_type>::value>::type work_;
212  bool owns_;
213 };
214 
215 #endif // !defined(GENERATING_DOCUMENTATION)
216 
218 template <typename Executor>
219 inline executor_work_guard<Executor> make_work_guard(const Executor& ex,
220  typename enable_if<
222  >::type* = 0)
223 {
225 }
226 
228 template <typename ExecutionContext>
230 make_work_guard(ExecutionContext& ctx,
231  typename enable_if<
232  is_convertible<ExecutionContext&, execution_context&>::value
233  >::type* = 0)
234 {
236  ctx.get_executor());
237 }
238 
240 template <typename T>
242 make_work_guard(const T& t,
243  typename enable_if<
245  && !is_convertible<T&, execution_context&
246  >::value>::type* = 0)
247 {
250 }
251 
253 template <typename T, typename Executor>
255 make_work_guard(const T& t, const Executor& ex,
256  typename enable_if<
258  >::type* = 0)
259 {
262 }
263 
265 template <typename T, typename ExecutionContext>
266 inline executor_work_guard<typename associated_executor<T,
267  typename ExecutionContext::executor_type>::type>
268 make_work_guard(const T& t, ExecutionContext& ctx,
269  typename enable_if<
271  && !is_convertible<T&, execution_context&>::value
272  && is_convertible<ExecutionContext&, execution_context&>::value
273  >::type* = 0)
274 {
275  return executor_work_guard<typename associated_executor<T,
276  typename ExecutionContext::executor_type>::type>(
278  t, ctx.get_executor()));
279 }
280 
281 } // namespace asio
282 
283 #include "asio/detail/pop_options.hpp"
284 
285 #endif // !defined(ASIO_NO_TS_EXECUTORS)
286 
287 #endif // ASIO_EXECUTOR_WORK_GUARD_HPP
executor_type get_executor() const ASIO_NOEXCEPT
Obtain the associated executor.
Definition: executor_work_guard.hpp:94
bool owns_work() const ASIO_NOEXCEPT
Whether the executor_work_guard object owns some outstanding work.
Definition: executor_work_guard.hpp:100
executor_work_guard(const executor_type &e) ASIO_NOEXCEPT
Constructs a executor_work_guard object for the specified executor.
Definition: executor_work_guard.hpp:56
A context for function object execution.
Definition: execution_context.hpp:105
Definition: type_traits.hpp:97
The is_executor trait detects whether a type T meets the Executor type requirements.
Definition: is_executor.hpp:33
Definition: outstanding_work.hpp:153
Executor executor_type
The underlying executor type.
Definition: executor_work_guard.hpp:50
An object of type executor_work_guard controls ownership of executor work within a scope...
Definition: executor_work_guard.hpp:35
Traits type used to obtain the executor associated with an object.
Definition: associated_executor.hpp:76
Definition: prefer.hpp:623
void reset() ASIO_NOEXCEPT
Indicate that the work is no longer outstanding.
Definition: executor_work_guard.hpp:110
~executor_work_guard()
Destructor.
Definition: executor_work_guard.hpp:87
Definition: any_io_executor.hpp:28
executor_work_guard(const executor_work_guard &other) ASIO_NOEXCEPT
Copy constructor.
Definition: executor_work_guard.hpp:64
The is_executor trait detects whether a type T satisfies the execution::executor concept.
Definition: executor.hpp:109