executor_function.hpp 4.7 KB

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