Clementine
executor_function.hpp
1 //
2 // detail/executor_function.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_EXECUTOR_FUNCTION_HPP
12 #define ASIO_DETAIL_EXECUTOR_FUNCTION_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 #include "asio/detail/handler_alloc_helpers.hpp"
20 #include "asio/detail/handler_invoke_helpers.hpp"
21 #include "asio/detail/memory.hpp"
22 
23 #include "asio/detail/push_options.hpp"
24 
25 namespace asio {
26 namespace detail {
27 
28 #if defined(ASIO_HAS_MOVE)
29 
30 // Lightweight, move-only function object wrapper.
31 class executor_function
32 {
33 public:
34  template <typename F, typename Alloc>
35  explicit executor_function(F f, const Alloc& a)
36  {
37  // Allocate and construct an object to wrap the function.
38  typedef impl<F, Alloc> impl_type;
39  typename impl_type::ptr p = {
40  detail::addressof(a), impl_type::ptr::allocate(a), 0 };
41  impl_ = new (p.v) impl_type(ASIO_MOVE_CAST(F)(f), a);
42  p.v = 0;
43  }
44 
45  executor_function(executor_function&& other) ASIO_NOEXCEPT
46  : impl_(other.impl_)
47  {
48  other.impl_ = 0;
49  }
50 
51  ~executor_function()
52  {
53  if (impl_)
54  impl_->complete_(impl_, false);
55  }
56 
57  void operator()()
58  {
59  if (impl_)
60  {
61  impl_base* i = impl_;
62  impl_ = 0;
63  i->complete_(i, true);
64  }
65  }
66 
67 private:
68  // Base class for polymorphic function implementations.
69  struct impl_base
70  {
71  void (*complete_)(impl_base*, bool);
72  };
73 
74  // Polymorphic function implementation.
75  template <typename Function, typename Alloc>
76  struct impl : impl_base
77  {
78  ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(
79  thread_info_base::executor_function_tag, impl);
80 
81  template <typename F>
82  impl(ASIO_MOVE_ARG(F) f, const Alloc& a)
83  : function_(ASIO_MOVE_CAST(F)(f)),
84  allocator_(a)
85  {
86  complete_ = &executor_function::complete<Function, Alloc>;
87  }
88 
89  Function function_;
90  Alloc allocator_;
91  };
92 
93  // Helper to complete function invocation.
94  template <typename Function, typename Alloc>
95  static void complete(impl_base* base, bool call)
96  {
97  // Take ownership of the function object.
98  impl<Function, Alloc>* i(static_cast<impl<Function, Alloc>*>(base));
99  Alloc allocator(i->allocator_);
100  typename impl<Function, Alloc>::ptr p = {
101  detail::addressof(allocator), i, i };
102 
103  // Make a copy of the function so that the memory can be deallocated before
104  // the upcall is made. Even if we're not about to make an upcall, a
105  // sub-object of the function may be the true owner of the memory
106  // associated with the function. Consequently, a local copy of the function
107  // is required to ensure that any owning sub-object remains valid until
108  // after we have deallocated the memory here.
109  Function function(ASIO_MOVE_CAST(Function)(i->function_));
110  p.reset();
111 
112  // Make the upcall if required.
113  if (call)
114  {
115  asio_handler_invoke_helpers::invoke(function, function);
116  }
117  }
118 
119  impl_base* impl_;
120 };
121 
122 #else // defined(ASIO_HAS_MOVE)
123 
124 // Not so lightweight, copyable function object wrapper.
126 {
127 public:
128  template <typename F, typename Alloc>
129  explicit executor_function(const F& f, const Alloc&)
130  : impl_(new impl<typename decay<F>::type>(f))
131  {
132  }
133 
134  void operator()()
135  {
136  impl_->complete_(impl_.get());
137  }
138 
139 private:
140  // Base class for polymorphic function implementations.
141  struct impl_base
142  {
143  void (*complete_)(impl_base*);
144  };
145 
146  // Polymorphic function implementation.
147  template <typename F>
148  struct impl : impl_base
149  {
150  impl(const F& f)
151  : function_(f)
152  {
153  complete_ = &executor_function::complete<F>;
154  }
155 
156  F function_;
157  };
158 
159  // Helper to complete function invocation.
160  template <typename F>
161  static void complete(impl_base* i)
162  {
163  static_cast<impl<F>*>(i)->function_();
164  }
165 
166  shared_ptr<impl_base> impl_;
167 };
168 
169 #endif // defined(ASIO_HAS_MOVE)
170 
171 // Lightweight, non-owning, copyable function object wrapper.
173 {
174 public:
175  template <typename F>
176  explicit executor_function_view(F& f) ASIO_NOEXCEPT
177  : complete_(&executor_function_view::complete<F>),
178  function_(&f)
179  {
180  }
181 
182  void operator()()
183  {
184  complete_(function_);
185  }
186 
187 private:
188  // Helper to complete function invocation.
189  template <typename F>
190  static void complete(void* f)
191  {
192  (*static_cast<F*>(f))();
193  }
194 
195  void (*complete_)(void*);
196  void* function_;
197 };
198 
199 } // namespace detail
200 } // namespace asio
201 
202 #include "asio/detail/pop_options.hpp"
203 
204 #endif // ASIO_DETAIL_EXECUTOR_FUNCTION_HPP
Definition: allocator.hpp:17
Definition: chrono.h:284
Definition: executor_function.hpp:125
Definition: executor_function.hpp:172
Definition: any_io_executor.hpp:28