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 11 #ifndef BOOST_ASIO_EXECUTION_DETAIL_AS_INVOCABLE_HPP 12 #define BOOST_ASIO_EXECUTION_DETAIL_AS_INVOCABLE_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/config.hpp> 19 #include <boost/asio/detail/atomic_count.hpp> 20 #include <boost/asio/detail/memory.hpp> 21 #include <boost/asio/detail/type_traits.hpp> 22 #include <boost/asio/execution/receiver_invocation_error.hpp> 23 #include <boost/asio/execution/set_done.hpp> 24 #include <boost/asio/execution/set_error.hpp> 25 #include <boost/asio/execution/set_value.hpp> 26 27 #include <boost/asio/detail/push_options.hpp> 28 29 namespace boost { 30 namespace asio { 31 namespace execution { 32 namespace detail { 33 34 #if defined(BOOST_ASIO_HAS_MOVE) 35 36 template <typename Receiver, typename> 37 struct as_invocable 38 { 39 Receiver* receiver_; 40 as_invocableboost::asio::execution::detail::as_invocable41 explicit as_invocable(Receiver& r) BOOST_ASIO_NOEXCEPT 42 : receiver_(boost::asio::detail::addressof(r)) 43 { 44 } 45 as_invocableboost::asio::execution::detail::as_invocable46 as_invocable(as_invocable&& other) BOOST_ASIO_NOEXCEPT 47 : receiver_(other.receiver_) 48 { 49 other.receiver_ = 0; 50 } 51 ~as_invocableboost::asio::execution::detail::as_invocable52 ~as_invocable() 53 { 54 if (receiver_) 55 execution::set_done(BOOST_ASIO_MOVE_OR_LVALUE(Receiver)(*receiver_)); 56 } 57 operator ()boost::asio::execution::detail::as_invocable58 void operator()() BOOST_ASIO_LVALUE_REF_QUAL BOOST_ASIO_NOEXCEPT 59 { 60 #if !defined(BOOST_ASIO_NO_EXCEPTIONS) 61 try 62 { 63 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS) 64 execution::set_value(BOOST_ASIO_MOVE_CAST(Receiver)(*receiver_)); 65 receiver_ = 0; 66 #if !defined(BOOST_ASIO_NO_EXCEPTIONS) 67 } 68 catch (...) 69 { 70 #if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) 71 execution::set_error(BOOST_ASIO_MOVE_CAST(Receiver)(*receiver_), 72 std::make_exception_ptr(receiver_invocation_error())); 73 receiver_ = 0; 74 #else // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) 75 std::terminate(); 76 #endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) 77 } 78 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS) 79 } 80 }; 81 82 #else // defined(BOOST_ASIO_HAS_MOVE) 83 84 template <typename Receiver, typename> 85 struct as_invocable 86 { 87 Receiver* receiver_; 88 boost::asio::detail::shared_ptr<boost::asio::detail::atomic_count> ref_count_; 89 90 explicit as_invocable(Receiver& r, 91 const boost::asio::detail::shared_ptr< 92 boost::asio::detail::atomic_count>& c) BOOST_ASIO_NOEXCEPT 93 : receiver_(boost::asio::detail::addressof(r)), 94 ref_count_(c) 95 { 96 } 97 98 as_invocable(const as_invocable& other) BOOST_ASIO_NOEXCEPT 99 : receiver_(other.receiver_), 100 ref_count_(other.ref_count_) 101 { 102 ++(*ref_count_); 103 } 104 105 ~as_invocable() 106 { 107 if (--(*ref_count_) == 0) 108 execution::set_done(*receiver_); 109 } 110 111 void operator()() BOOST_ASIO_LVALUE_REF_QUAL BOOST_ASIO_NOEXCEPT 112 { 113 #if !defined(BOOST_ASIO_NO_EXCEPTIONS) 114 try 115 { 116 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS) 117 execution::set_value(*receiver_); 118 ++(*ref_count_); 119 } 120 #if !defined(BOOST_ASIO_NO_EXCEPTIONS) 121 catch (...) 122 { 123 #if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) 124 execution::set_error(*receiver_, 125 std::make_exception_ptr(receiver_invocation_error())); 126 ++(*ref_count_); 127 #else // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) 128 std::terminate(); 129 #endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) 130 } 131 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS) 132 } 133 }; 134 135 #endif // defined(BOOST_ASIO_HAS_MOVE) 136 137 template <typename T> 138 struct is_as_invocable : false_type 139 { 140 }; 141 142 template <typename Function, typename T> 143 struct is_as_invocable<as_invocable<Function, T> > : true_type 144 { 145 }; 146 147 } // namespace detail 148 } // namespace execution 149 } // namespace asio 150 } // namespace boost 151 152 #include <boost/asio/detail/pop_options.hpp> 153 154 #endif // BOOST_ASIO_EXECUTION_DETAIL_AS_INVOCABLE_HPP 155