as_invocable.hpp 3.9 KB

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