executor_function.hpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. //
  2. // detail/executor_function.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2024 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 BOOST_ASIO_DETAIL_EXECUTOR_FUNCTION_HPP
  11. #define BOOST_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 <boost/asio/detail/config.hpp>
  16. #include <boost/asio/detail/handler_alloc_helpers.hpp>
  17. #include <boost/asio/detail/memory.hpp>
  18. #include <boost/asio/detail/push_options.hpp>
  19. namespace boost {
  20. namespace asio {
  21. namespace detail {
  22. // Lightweight, move-only function object wrapper.
  23. class executor_function
  24. {
  25. public:
  26. template <typename F, typename Alloc>
  27. explicit executor_function(F f, const Alloc& a)
  28. {
  29. // Allocate and construct an object to wrap the function.
  30. typedef impl<F, Alloc> impl_type;
  31. typename impl_type::ptr p = {
  32. detail::addressof(a), impl_type::ptr::allocate(a), 0 };
  33. impl_ = new (p.v) impl_type(static_cast<F&&>(f), a);
  34. p.v = 0;
  35. }
  36. executor_function(executor_function&& other) noexcept
  37. : impl_(other.impl_)
  38. {
  39. other.impl_ = 0;
  40. }
  41. ~executor_function()
  42. {
  43. if (impl_)
  44. impl_->complete_(impl_, false);
  45. }
  46. void operator()()
  47. {
  48. if (impl_)
  49. {
  50. impl_base* i = impl_;
  51. impl_ = 0;
  52. i->complete_(i, true);
  53. }
  54. }
  55. private:
  56. // Base class for polymorphic function implementations.
  57. struct impl_base
  58. {
  59. void (*complete_)(impl_base*, bool);
  60. };
  61. // Polymorphic function implementation.
  62. template <typename Function, typename Alloc>
  63. struct impl : impl_base
  64. {
  65. BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(
  66. thread_info_base::executor_function_tag, impl);
  67. template <typename F>
  68. impl(F&& f, const Alloc& a)
  69. : function_(static_cast<F&&>(f)),
  70. allocator_(a)
  71. {
  72. complete_ = &executor_function::complete<Function, Alloc>;
  73. }
  74. Function function_;
  75. Alloc allocator_;
  76. };
  77. // Helper to complete function invocation.
  78. template <typename Function, typename Alloc>
  79. static void complete(impl_base* base, bool call)
  80. {
  81. // Take ownership of the function object.
  82. impl<Function, Alloc>* i(static_cast<impl<Function, Alloc>*>(base));
  83. Alloc allocator(i->allocator_);
  84. typename impl<Function, Alloc>::ptr p = {
  85. detail::addressof(allocator), i, i };
  86. // Make a copy of the function so that the memory can be deallocated before
  87. // the upcall is made. Even if we're not about to make an upcall, a
  88. // sub-object of the function may be the true owner of the memory
  89. // associated with the function. Consequently, a local copy of the function
  90. // is required to ensure that any owning sub-object remains valid until
  91. // after we have deallocated the memory here.
  92. Function function(static_cast<Function&&>(i->function_));
  93. p.reset();
  94. // Make the upcall if required.
  95. if (call)
  96. {
  97. static_cast<Function&&>(function)();
  98. }
  99. }
  100. impl_base* impl_;
  101. };
  102. // Lightweight, non-owning, copyable function object wrapper.
  103. class executor_function_view
  104. {
  105. public:
  106. template <typename F>
  107. explicit executor_function_view(F& f) noexcept
  108. : complete_(&executor_function_view::complete<F>),
  109. function_(&f)
  110. {
  111. }
  112. void operator()()
  113. {
  114. complete_(function_);
  115. }
  116. private:
  117. // Helper to complete function invocation.
  118. template <typename F>
  119. static void complete(void* f)
  120. {
  121. (*static_cast<F*>(f))();
  122. }
  123. void (*complete_)(void*);
  124. void* function_;
  125. };
  126. } // namespace detail
  127. } // namespace asio
  128. } // namespace boost
  129. #include <boost/asio/detail/pop_options.hpp>
  130. #endif // BOOST_ASIO_DETAIL_EXECUTOR_FUNCTION_HPP