as_invocable.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. //
  2. // execution/detail/as_invocable.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_EXECUTION_DETAIL_AS_INVOCABLE_HPP
  11. #define ASIO_EXECUTION_DETAIL_AS_INVOCABLE_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/atomic_count.hpp"
  17. #include "asio/detail/memory.hpp"
  18. #include "asio/detail/type_traits.hpp"
  19. #include "asio/execution/receiver_invocation_error.hpp"
  20. #include "asio/execution/set_done.hpp"
  21. #include "asio/execution/set_error.hpp"
  22. #include "asio/execution/set_value.hpp"
  23. #include "asio/detail/push_options.hpp"
  24. namespace asio {
  25. namespace execution {
  26. namespace detail {
  27. #if defined(ASIO_HAS_MOVE)
  28. template <typename Receiver, typename>
  29. struct as_invocable
  30. {
  31. Receiver* receiver_;
  32. explicit as_invocable(Receiver& r) ASIO_NOEXCEPT
  33. : receiver_(asio::detail::addressof(r))
  34. {
  35. }
  36. as_invocable(as_invocable&& other) ASIO_NOEXCEPT
  37. : receiver_(other.receiver_)
  38. {
  39. other.receiver_ = 0;
  40. }
  41. ~as_invocable()
  42. {
  43. if (receiver_)
  44. execution::set_done(ASIO_MOVE_OR_LVALUE(Receiver)(*receiver_));
  45. }
  46. void operator()() ASIO_LVALUE_REF_QUAL ASIO_NOEXCEPT
  47. {
  48. #if !defined(ASIO_NO_EXCEPTIONS)
  49. try
  50. {
  51. #endif // !defined(ASIO_NO_EXCEPTIONS)
  52. execution::set_value(ASIO_MOVE_CAST(Receiver)(*receiver_));
  53. receiver_ = 0;
  54. #if !defined(ASIO_NO_EXCEPTIONS)
  55. }
  56. catch (...)
  57. {
  58. #if defined(ASIO_HAS_STD_EXCEPTION_PTR)
  59. execution::set_error(ASIO_MOVE_CAST(Receiver)(*receiver_),
  60. std::make_exception_ptr(receiver_invocation_error()));
  61. receiver_ = 0;
  62. #else // defined(ASIO_HAS_STD_EXCEPTION_PTR)
  63. std::terminate();
  64. #endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)
  65. }
  66. #endif // !defined(ASIO_NO_EXCEPTIONS)
  67. }
  68. };
  69. #else // defined(ASIO_HAS_MOVE)
  70. template <typename Receiver, typename>
  71. struct as_invocable
  72. {
  73. Receiver* receiver_;
  74. asio::detail::shared_ptr<asio::detail::atomic_count> ref_count_;
  75. explicit as_invocable(Receiver& r,
  76. const asio::detail::shared_ptr<
  77. asio::detail::atomic_count>& c) ASIO_NOEXCEPT
  78. : receiver_(asio::detail::addressof(r)),
  79. ref_count_(c)
  80. {
  81. }
  82. as_invocable(const as_invocable& other) ASIO_NOEXCEPT
  83. : receiver_(other.receiver_),
  84. ref_count_(other.ref_count_)
  85. {
  86. ++(*ref_count_);
  87. }
  88. ~as_invocable()
  89. {
  90. if (--(*ref_count_) == 0)
  91. execution::set_done(*receiver_);
  92. }
  93. void operator()() ASIO_LVALUE_REF_QUAL ASIO_NOEXCEPT
  94. {
  95. #if !defined(ASIO_NO_EXCEPTIONS)
  96. try
  97. {
  98. #endif // !defined(ASIO_NO_EXCEPTIONS)
  99. execution::set_value(*receiver_);
  100. ++(*ref_count_);
  101. }
  102. #if !defined(ASIO_NO_EXCEPTIONS)
  103. catch (...)
  104. {
  105. #if defined(ASIO_HAS_STD_EXCEPTION_PTR)
  106. execution::set_error(*receiver_,
  107. std::make_exception_ptr(receiver_invocation_error()));
  108. ++(*ref_count_);
  109. #else // defined(ASIO_HAS_STD_EXCEPTION_PTR)
  110. std::terminate();
  111. #endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)
  112. }
  113. #endif // !defined(ASIO_NO_EXCEPTIONS)
  114. }
  115. };
  116. #endif // defined(ASIO_HAS_MOVE)
  117. template <typename T>
  118. struct is_as_invocable : false_type
  119. {
  120. };
  121. template <typename Function, typename T>
  122. struct is_as_invocable<as_invocable<Function, T> > : true_type
  123. {
  124. };
  125. } // namespace detail
  126. } // namespace execution
  127. } // namespace asio
  128. #include "asio/detail/pop_options.hpp"
  129. #endif // ASIO_EXECUTION_DETAIL_AS_INVOCABLE_HPP