1    	//
2    	// executor.hpp
3    	// ~~~~~~~~~~~~
4    	//
5    	// Copyright (c) 2003-2018 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_EXECUTOR_HPP
12   	#define BOOST_ASIO_EXECUTOR_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   	#include <typeinfo>
20   	#include <boost/asio/detail/cstddef.hpp>
21   	#include <boost/asio/detail/memory.hpp>
22   	#include <boost/asio/detail/throw_exception.hpp>
23   	#include <boost/asio/execution_context.hpp>
24   	
25   	#include <boost/asio/detail/push_options.hpp>
26   	
27   	namespace boost {
28   	namespace asio {
29   	
30   	/// Exception thrown when trying to access an empty polymorphic executor.
31   	class bad_executor
32   	  : public std::exception
33   	{
34   	public:
35   	  /// Constructor.
36   	  BOOST_ASIO_DECL bad_executor() BOOST_ASIO_NOEXCEPT;
37   	
38   	  /// Obtain message associated with exception.
39   	  BOOST_ASIO_DECL virtual const char* what() const
40   	    BOOST_ASIO_NOEXCEPT_OR_NOTHROW;
41   	};
42   	
43   	/// Polymorphic wrapper for executors.
44   	class executor
45   	{
46   	public:
47   	  /// Default constructor.
48   	  executor() BOOST_ASIO_NOEXCEPT
49   	    : impl_(0)
50   	  {
51   	  }
52   	
53   	  /// Construct from nullptr.
54   	  executor(nullptr_t) BOOST_ASIO_NOEXCEPT
55   	    : impl_(0)
56   	  {
57   	  }
58   	
59   	  /// Copy constructor.
60   	  executor(const executor& other) BOOST_ASIO_NOEXCEPT
61   	    : impl_(other.clone())
62   	  {
63   	  }
64   	
65   	#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
66   	  /// Move constructor.
67   	  executor(executor&& other) BOOST_ASIO_NOEXCEPT
68   	    : impl_(other.impl_)
69   	  {
70   	    other.impl_ = 0;
71   	  }
72   	#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
73   	
74   	  /// Construct a polymorphic wrapper for the specified executor.
75   	  template <typename Executor>
76   	  executor(Executor e);
77   	
78   	  /// Allocator-aware constructor to create a polymorphic wrapper for the
79   	  /// specified executor.
80   	  template <typename Executor, typename Allocator>
81   	  executor(allocator_arg_t, const Allocator& a, Executor e);
82   	
83   	  /// Destructor.
84   	  ~executor()
85   	  {
86   	    destroy();
87   	  }
88   	
89   	  /// Assignment operator.
90   	  executor& operator=(const executor& other) BOOST_ASIO_NOEXCEPT
91   	  {
92   	    destroy();
93   	    impl_ = other.clone();
94   	    return *this;
95   	  }
96   	
97   	#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
98   	  // Move assignment operator.
99   	  executor& operator=(executor&& other) BOOST_ASIO_NOEXCEPT
100  	  {
101  	    destroy();
102  	    impl_ = other.impl_;
103  	    other.impl_ = 0;
104  	    return *this;
105  	  }
106  	#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
107  	
108  	  /// Assignment operator for nullptr_t.
109  	  executor& operator=(nullptr_t) BOOST_ASIO_NOEXCEPT
110  	  {
111  	    destroy();
112  	    impl_ = 0;
113  	    return *this;
114  	  }
115  	
116  	  /// Assignment operator to create a polymorphic wrapper for the specified
117  	  /// executor.
118  	  template <typename Executor>
119  	  executor& operator=(BOOST_ASIO_MOVE_ARG(Executor) e) BOOST_ASIO_NOEXCEPT
120  	  {
121  	    executor tmp(BOOST_ASIO_MOVE_CAST(Executor)(e));
122  	    destroy();
123  	    impl_ = tmp.impl_;
124  	    tmp.impl_ = 0;
125  	    return *this;
126  	  }
127  	
128  	  /// Obtain the underlying execution context.
129  	  execution_context& context() const BOOST_ASIO_NOEXCEPT
130  	  {
131  	    return get_impl()->context();
132  	  }
133  	
134  	  /// Inform the executor that it has some outstanding work to do.
135  	  void on_work_started() const BOOST_ASIO_NOEXCEPT
136  	  {
137  	    get_impl()->on_work_started();
138  	  }
139  	
140  	  /// Inform the executor that some work is no longer outstanding.
(1) Event exn_spec_violation: An exception of type "boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::asio::bad_executor> >" is thrown but the throw list "throw()" doesn't allow it to be thrown. This will cause a call to unexpected() which usually calls terminate().
Also see events: [fun_call_w_exception]
141  	  void on_work_finished() const BOOST_ASIO_NOEXCEPT
142  	  {
(2) Event fun_call_w_exception: Called function throws an exception of type "boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::asio::bad_executor> >". [details]
Also see events: [exn_spec_violation]
143  	    get_impl()->on_work_finished();
144  	  }
145  	
146  	  /// Request the executor to invoke the given function object.
147  	  /**
148  	   * This function is used to ask the executor to execute the given function
149  	   * object. The function object is executed according to the rules of the
150  	   * target executor object.
151  	   *
152  	   * @param f The function object to be called. The executor will make a copy
153  	   * of the handler object as required. The function signature of the function
154  	   * object must be: @code void function(); @endcode
155  	   *
156  	   * @param a An allocator that may be used by the executor to allocate the
157  	   * internal storage needed for function invocation.
158  	   */
159  	  template <typename Function, typename Allocator>
160  	  void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
161  	
162  	  /// Request the executor to invoke the given function object.
163  	  /**
164  	   * This function is used to ask the executor to execute the given function
165  	   * object. The function object is executed according to the rules of the
166  	   * target executor object.
167  	   *
168  	   * @param f The function object to be called. The executor will make
169  	   * a copy of the handler object as required. The function signature of the
170  	   * function object must be: @code void function(); @endcode
171  	   *
172  	   * @param a An allocator that may be used by the executor to allocate the
173  	   * internal storage needed for function invocation.
174  	   */
175  	  template <typename Function, typename Allocator>
176  	  void post(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
177  	
178  	  /// Request the executor to invoke the given function object.
179  	  /**
180  	   * This function is used to ask the executor to execute the given function
181  	   * object. The function object is executed according to the rules of the
182  	   * target executor object.
183  	   *
184  	   * @param f The function object to be called. The executor will make
185  	   * a copy of the handler object as required. The function signature of the
186  	   * function object must be: @code void function(); @endcode
187  	   *
188  	   * @param a An allocator that may be used by the executor to allocate the
189  	   * internal storage needed for function invocation.
190  	   */
191  	  template <typename Function, typename Allocator>
192  	  void defer(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
193  	
194  	  struct unspecified_bool_type_t {};
195  	  typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
196  	  static void unspecified_bool_true(unspecified_bool_type_t) {}
197  	
198  	  /// Operator to test if the executor contains a valid target.
199  	  operator unspecified_bool_type() const BOOST_ASIO_NOEXCEPT
200  	  {
201  	    return impl_ ? &executor::unspecified_bool_true : 0;
202  	  }
203  	
204  	  /// Obtain type information for the target executor object.
205  	  /**
206  	   * @returns If @c *this has a target type of type @c T, <tt>typeid(T)</tt>;
207  	   * otherwise, <tt>typeid(void)</tt>.
208  	   */
209  	#if !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
210  	  const std::type_info& target_type() const BOOST_ASIO_NOEXCEPT
211  	  {
212  	    return impl_ ? impl_->target_type() : typeid(void);
213  	  }
214  	#else // !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
215  	  const void* target_type() const BOOST_ASIO_NOEXCEPT
216  	  {
217  	    return impl_ ? impl_->target_type() : 0;
218  	  }
219  	#endif // !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
220  	
221  	  /// Obtain a pointer to the target executor object.
222  	  /**
223  	   * @returns If <tt>target_type() == typeid(T)</tt>, a pointer to the stored
224  	   * executor target; otherwise, a null pointer.
225  	   */
226  	  template <typename Executor>
227  	  Executor* target() BOOST_ASIO_NOEXCEPT;
228  	
229  	  /// Obtain a pointer to the target executor object.
230  	  /**
231  	   * @returns If <tt>target_type() == typeid(T)</tt>, a pointer to the stored
232  	   * executor target; otherwise, a null pointer.
233  	   */
234  	  template <typename Executor>
235  	  const Executor* target() const BOOST_ASIO_NOEXCEPT;
236  	
237  	  /// Compare two executors for equality.
238  	  friend bool operator==(const executor& a,
239  	      const executor& b) BOOST_ASIO_NOEXCEPT
240  	  {
241  	    if (a.impl_ == b.impl_)
242  	      return true;
243  	    if (!a.impl_ || !b.impl_)
244  	      return false;
245  	    return a.impl_->equals(b.impl_);
246  	  }
247  	
248  	  /// Compare two executors for inequality.
249  	  friend bool operator!=(const executor& a,
250  	      const executor& b) BOOST_ASIO_NOEXCEPT
251  	  {
252  	    return !(a == b);
253  	  }
254  	
255  	private:
256  	#if !defined(GENERATING_DOCUMENTATION)
257  	  class function;
258  	  template <typename, typename> class impl;
259  	
260  	#if !defined(BOOST_ASIO_NO_TYPEID)
261  	  typedef const std::type_info& type_id_result_type;
262  	#else // !defined(BOOST_ASIO_NO_TYPEID)
263  	  typedef const void* type_id_result_type;
264  	#endif // !defined(BOOST_ASIO_NO_TYPEID)
265  	
266  	  template <typename T>
267  	  static type_id_result_type type_id()
268  	  {
269  	#if !defined(BOOST_ASIO_NO_TYPEID)
270  	    return typeid(T);
271  	#else // !defined(BOOST_ASIO_NO_TYPEID)
272  	    static int unique_id;
273  	    return &unique_id;
274  	#endif // !defined(BOOST_ASIO_NO_TYPEID)
275  	  }
276  	
277  	  // Base class for all polymorphic executor implementations.
278  	  class impl_base
279  	  {
280  	  public:
281  	    virtual impl_base* clone() const BOOST_ASIO_NOEXCEPT = 0;
282  	    virtual void destroy() BOOST_ASIO_NOEXCEPT = 0;
283  	    virtual execution_context& context() BOOST_ASIO_NOEXCEPT = 0;
284  	    virtual void on_work_started() BOOST_ASIO_NOEXCEPT = 0;
285  	    virtual void on_work_finished() BOOST_ASIO_NOEXCEPT = 0;
286  	    virtual void dispatch(BOOST_ASIO_MOVE_ARG(function)) = 0;
287  	    virtual void post(BOOST_ASIO_MOVE_ARG(function)) = 0;
288  	    virtual void defer(BOOST_ASIO_MOVE_ARG(function)) = 0;
289  	    virtual type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT = 0;
290  	    virtual void* target() BOOST_ASIO_NOEXCEPT = 0;
291  	    virtual const void* target() const BOOST_ASIO_NOEXCEPT = 0;
292  	    virtual bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT = 0;
293  	
294  	  protected:
295  	    impl_base(bool fast_dispatch) : fast_dispatch_(fast_dispatch) {}
296  	    virtual ~impl_base() {}
297  	
298  	  private:
299  	    friend class executor;
300  	    const bool fast_dispatch_;
301  	  };
302  	
303  	  // Helper function to check and return the implementation pointer.
304  	  impl_base* get_impl() const
305  	  {
306  	    if (!impl_)
307  	    {
308  	      bad_executor ex;
(1) Event fun_call_w_exception: Called function throws an exception of type "boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::asio::bad_executor> >". [details]
309  	      boost::asio::detail::throw_exception(ex);
310  	    }
311  	    return impl_;
312  	  }
313  	
314  	  // Helper function to clone another implementation.
315  	  impl_base* clone() const BOOST_ASIO_NOEXCEPT
316  	  {
317  	    return impl_ ? impl_->clone() : 0;
318  	  }
319  	
320  	  // Helper function to destroy an implementation.
321  	  void destroy() BOOST_ASIO_NOEXCEPT
322  	  {
323  	    if (impl_)
324  	      impl_->destroy();
325  	  }
326  	
327  	  impl_base* impl_;
328  	#endif // !defined(GENERATING_DOCUMENTATION)
329  	};
330  	
331  	} // namespace asio
332  	} // namespace boost
333  	
334  	BOOST_ASIO_USES_ALLOCATOR(boost::asio::executor)
335  	
336  	#include <boost/asio/detail/pop_options.hpp>
337  	
338  	#include <boost/asio/impl/executor.hpp>
339  	#if defined(BOOST_ASIO_HEADER_ONLY)
340  	# include <boost/asio/impl/executor.ipp>
341  	#endif // defined(BOOST_ASIO_HEADER_ONLY)
342  	
343  	#endif // BOOST_ASIO_EXECUTOR_HPP
344