executor_function.hpp 3.7 KB

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