1 // 2 // execution/set_done.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_SET_DONE_HPP 12 #define BOOST_ASIO_EXECUTION_SET_DONE_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/type_traits.hpp> 20 #include <boost/asio/traits/set_done_member.hpp> 21 #include <boost/asio/traits/set_done_free.hpp> 22 23 #include <boost/asio/detail/push_options.hpp> 24 25 #if defined(GENERATING_DOCUMENTATION) 26 27 namespace boost { 28 namespace asio { 29 namespace execution { 30 31 /// A customisation point that delivers a done notification to a receiver. 32 /** 33 * The name <tt>execution::set_done</tt> denotes a customisation point object. 34 * The expression <tt>execution::set_done(R)</tt> for some subexpression 35 * <tt>R</tt> is expression-equivalent to: 36 * 37 * @li <tt>R.set_done()</tt>, if that expression is valid. If the function 38 * selected does not signal the receiver <tt>R</tt>'s done channel, the 39 * program is ill-formed with no diagnostic required. 40 * 41 * @li Otherwise, <tt>set_done(R)</tt>, if that expression is valid, with 42 * overload resolution performed in a context that includes the declaration 43 * <tt>void set_done();</tt> and that does not include a declaration of 44 * <tt>execution::set_done</tt>. If the function selected by overload 45 * resolution does not signal the receiver <tt>R</tt>'s done channel, the 46 * program is ill-formed with no diagnostic required. 47 * 48 * @li Otherwise, <tt>execution::set_done(R)</tt> is ill-formed. 49 */ 50 inline constexpr unspecified set_done = unspecified; 51 52 /// A type trait that determines whether a @c set_done expression is 53 /// well-formed. 54 /** 55 * Class template @c can_set_done is a trait that is derived from 56 * @c true_type if the expression <tt>execution::set_done(std::declval<R>(), 57 * std::declval<E>())</tt> is well formed; otherwise @c false_type. 58 */ 59 template <typename R> 60 struct can_set_done : 61 integral_constant<bool, automatically_determined> 62 { 63 }; 64 65 } // namespace execution 66 } // namespace asio 67 } // namespace boost 68 69 #else // defined(GENERATING_DOCUMENTATION) 70 71 namespace asio_execution_set_done_fn { 72 73 using boost::asio::decay; 74 using boost::asio::declval; 75 using boost::asio::enable_if; 76 using boost::asio::traits::set_done_free; 77 using boost::asio::traits::set_done_member; 78 79 void set_done(); 80 81 enum overload_type 82 { 83 call_member, 84 call_free, 85 ill_formed 86 }; 87 88 template <typename R, typename = void, typename = void> 89 struct call_traits 90 { 91 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); 92 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 93 typedef void result_type; 94 }; 95 96 template <typename R> 97 struct call_traits<R, 98 typename enable_if< 99 set_done_member<R>::is_valid 100 >::type> : 101 set_done_member<R> 102 { 103 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); 104 }; 105 106 template <typename R> 107 struct call_traits<R, 108 typename enable_if< 109 !set_done_member<R>::is_valid 110 >::type, 111 typename enable_if< 112 set_done_free<R>::is_valid 113 >::type> : 114 set_done_free<R> 115 { 116 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); 117 }; 118 119 struct impl 120 { 121 #if defined(BOOST_ASIO_HAS_MOVE) 122 template <typename R> 123 BOOST_ASIO_CONSTEXPR typename enable_if< 124 call_traits<R>::overload == call_member, 125 typename call_traits<R>::result_type 126 >::type operator ()asio_execution_set_done_fn::impl127 operator()(R&& r) const 128 BOOST_ASIO_NOEXCEPT_IF(( 129 call_traits<R>::is_noexcept)) 130 { 131 return BOOST_ASIO_MOVE_CAST(R)(r).set_done(); 132 } 133 134 template <typename R> 135 BOOST_ASIO_CONSTEXPR typename enable_if< 136 call_traits<R>::overload == call_free, 137 typename call_traits<R>::result_type 138 >::type operator ()asio_execution_set_done_fn::impl139 operator()(R&& r) const 140 BOOST_ASIO_NOEXCEPT_IF(( 141 call_traits<R>::is_noexcept)) 142 { 143 return set_done(BOOST_ASIO_MOVE_CAST(R)(r)); 144 } 145 #else // defined(BOOST_ASIO_HAS_MOVE) 146 template <typename R> 147 BOOST_ASIO_CONSTEXPR typename enable_if< 148 call_traits<R&>::overload == call_member, 149 typename call_traits<R&>::result_type 150 >::type 151 operator()(R& r) const 152 BOOST_ASIO_NOEXCEPT_IF(( 153 call_traits<R&>::is_noexcept)) 154 { 155 return r.set_done(); 156 } 157 158 template <typename R> 159 BOOST_ASIO_CONSTEXPR typename enable_if< 160 call_traits<const R&>::overload == call_member, 161 typename call_traits<const R&>::result_type 162 >::type 163 operator()(const R& r) const 164 BOOST_ASIO_NOEXCEPT_IF(( 165 call_traits<const R&>::is_noexcept)) 166 { 167 return r.set_done(); 168 } 169 170 template <typename R> 171 BOOST_ASIO_CONSTEXPR typename enable_if< 172 call_traits<R&>::overload == call_free, 173 typename call_traits<R&>::result_type 174 >::type 175 operator()(R& r) const 176 BOOST_ASIO_NOEXCEPT_IF(( 177 call_traits<R&>::is_noexcept)) 178 { 179 return set_done(r); 180 } 181 182 template <typename R> 183 BOOST_ASIO_CONSTEXPR typename enable_if< 184 call_traits<const R&>::overload == call_free, 185 typename call_traits<const R&>::result_type 186 >::type 187 operator()(const R& r) const 188 BOOST_ASIO_NOEXCEPT_IF(( 189 call_traits<const R&>::is_noexcept)) 190 { 191 return set_done(r); 192 } 193 #endif // defined(BOOST_ASIO_HAS_MOVE) 194 }; 195 196 template <typename T = impl> 197 struct static_instance 198 { 199 static const T instance; 200 }; 201 202 template <typename T> 203 const T static_instance<T>::instance = {}; 204 205 } // namespace asio_execution_set_done_fn 206 namespace boost { 207 namespace asio { 208 namespace execution { 209 namespace { 210 211 static BOOST_ASIO_CONSTEXPR const asio_execution_set_done_fn::impl& 212 set_done = asio_execution_set_done_fn::static_instance<>::instance; 213 214 } // namespace 215 216 template <typename R> 217 struct can_set_done : 218 integral_constant<bool, 219 asio_execution_set_done_fn::call_traits<R>::overload != 220 asio_execution_set_done_fn::ill_formed> 221 { 222 }; 223 224 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 225 226 template <typename R> 227 constexpr bool can_set_done_v = can_set_done<R>::value; 228 229 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 230 231 template <typename R> 232 struct is_nothrow_set_done : 233 integral_constant<bool, 234 asio_execution_set_done_fn::call_traits<R>::is_noexcept> 235 { 236 }; 237 238 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 239 240 template <typename R> 241 constexpr bool is_nothrow_set_done_v 242 = is_nothrow_set_done<R>::value; 243 244 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 245 246 } // namespace execution 247 } // namespace asio 248 } // namespace boost 249 250 #endif // defined(GENERATING_DOCUMENTATION) 251 252 #include <boost/asio/detail/pop_options.hpp> 253 254 #endif // BOOST_ASIO_EXECUTION_SET_DONE_HPP 255