• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // detail/work_dispatcher.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 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_WORK_DISPATCHER_HPP
12 #define BOOST_ASIO_DETAIL_WORK_DISPATCHER_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 <boost/asio/detail/type_traits.hpp>
20 #include <boost/asio/associated_executor.hpp>
21 #include <boost/asio/associated_allocator.hpp>
22 #include <boost/asio/executor_work_guard.hpp>
23 #include <boost/asio/execution/executor.hpp>
24 #include <boost/asio/execution/allocator.hpp>
25 #include <boost/asio/execution/blocking.hpp>
26 #include <boost/asio/execution/outstanding_work.hpp>
27 #include <boost/asio/prefer.hpp>
28 
29 #include <boost/asio/detail/push_options.hpp>
30 
31 namespace boost {
32 namespace asio {
33 namespace detail {
34 
35 template <typename Handler, typename Executor, typename = void>
36 struct is_work_dispatcher_required : true_type
37 {
38 };
39 
40 template <typename Handler, typename Executor>
41 struct is_work_dispatcher_required<Handler, Executor,
42     typename enable_if<
43       is_same<
44         typename associated_executor<Handler,
45           Executor>::asio_associated_executor_is_unspecialised,
46         void
47       >::value
48     >::type> : false_type
49 {
50 };
51 
52 template <typename Handler, typename Executor, typename = void>
53 class work_dispatcher
54 {
55 public:
56   template <typename CompletionHandler>
work_dispatcher(BOOST_ASIO_MOVE_ARG (CompletionHandler)handler,const Executor & handler_ex)57   work_dispatcher(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
58       const Executor& handler_ex)
59     : handler_(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)),
60       executor_(boost::asio::prefer(handler_ex,
61           execution::outstanding_work.tracked))
62   {
63   }
64 
65 #if defined(BOOST_ASIO_HAS_MOVE)
work_dispatcher(const work_dispatcher & other)66   work_dispatcher(const work_dispatcher& other)
67     : handler_(other.handler_),
68       executor_(other.executor_)
69   {
70   }
71 
work_dispatcher(work_dispatcher && other)72   work_dispatcher(work_dispatcher&& other)
73     : handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
74       executor_(BOOST_ASIO_MOVE_CAST(work_executor_type)(other.executor_))
75   {
76   }
77 #endif // defined(BOOST_ASIO_HAS_MOVE)
78 
operator ()()79   void operator()()
80   {
81     execution::execute(
82         boost::asio::prefer(executor_,
83           execution::blocking.possibly,
84           execution::allocator((get_associated_allocator)(handler_))),
85         BOOST_ASIO_MOVE_CAST(Handler)(handler_));
86   }
87 
88 private:
89   typedef typename decay<
90       typename prefer_result<const Executor&,
91         execution::outstanding_work_t::tracked_t
92       >::type
93     >::type work_executor_type;
94 
95   Handler handler_;
96   work_executor_type executor_;
97 };
98 
99 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
100 
101 template <typename Handler, typename Executor>
102 class work_dispatcher<Handler, Executor,
103     typename enable_if<!execution::is_executor<Executor>::value>::type>
104 {
105 public:
106   template <typename CompletionHandler>
work_dispatcher(BOOST_ASIO_MOVE_ARG (CompletionHandler)handler,const Executor & handler_ex)107   work_dispatcher(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
108       const Executor& handler_ex)
109     : work_(handler_ex),
110       handler_(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler))
111   {
112   }
113 
114 #if defined(BOOST_ASIO_HAS_MOVE)
work_dispatcher(const work_dispatcher & other)115   work_dispatcher(const work_dispatcher& other)
116     : work_(other.work_),
117       handler_(other.handler_)
118   {
119   }
120 
work_dispatcher(work_dispatcher && other)121   work_dispatcher(work_dispatcher&& other)
122     : work_(BOOST_ASIO_MOVE_CAST(executor_work_guard<Executor>)(other.work_)),
123       handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_))
124   {
125   }
126 #endif // defined(BOOST_ASIO_HAS_MOVE)
127 
operator ()()128   void operator()()
129   {
130     typename associated_allocator<Handler>::type alloc(
131         (get_associated_allocator)(handler_));
132     work_.get_executor().dispatch(
133         BOOST_ASIO_MOVE_CAST(Handler)(handler_), alloc);
134     work_.reset();
135   }
136 
137 private:
138   executor_work_guard<Executor> work_;
139   Handler handler_;
140 };
141 
142 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
143 
144 } // namespace detail
145 } // namespace asio
146 } // namespace boost
147 
148 #include <boost/asio/detail/pop_options.hpp>
149 
150 #endif // BOOST_ASIO_DETAIL_WORK_DISPATCHER_HPP
151