1 // 2 // use_future.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_USE_FUTURE_HPP 12 #define BOOST_ASIO_USE_FUTURE_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/future.hpp> 20 21 #if defined(BOOST_ASIO_HAS_STD_FUTURE_CLASS) \ 22 || defined(GENERATING_DOCUMENTATION) 23 24 #include <memory> 25 #include <boost/asio/detail/type_traits.hpp> 26 27 #include <boost/asio/detail/push_options.hpp> 28 29 namespace boost { 30 namespace asio { 31 namespace detail { 32 33 template <typename Function, typename Allocator> 34 class packaged_token; 35 36 template <typename Function, typename Allocator, typename Result> 37 class packaged_handler; 38 39 } // namespace detail 40 41 /// Class used to specify that an asynchronous operation should return a future. 42 /** 43 * The use_future_t class is used to indicate that an asynchronous operation 44 * should return a std::future object. A use_future_t object may be passed as a 45 * handler to an asynchronous operation, typically using the special value @c 46 * boost::asio::use_future. For example: 47 * 48 * @code std::future<std::size_t> my_future 49 * = my_socket.async_read_some(my_buffer, boost::asio::use_future); @endcode 50 * 51 * The initiating function (async_read_some in the above example) returns a 52 * future that will receive the result of the operation. If the operation 53 * completes with an error_code indicating failure, it is converted into a 54 * system_error and passed back to the caller via the future. 55 */ 56 template <typename Allocator = std::allocator<void> > 57 class use_future_t 58 { 59 public: 60 /// The allocator type. The allocator is used when constructing the 61 /// @c std::promise object for a given asynchronous operation. 62 typedef Allocator allocator_type; 63 64 /// Construct using default-constructed allocator. use_future_t()65 BOOST_ASIO_CONSTEXPR use_future_t() 66 { 67 } 68 69 /// Construct using specified allocator. use_future_t(const Allocator & allocator)70 explicit use_future_t(const Allocator& allocator) 71 : allocator_(allocator) 72 { 73 } 74 75 #if !defined(BOOST_ASIO_NO_DEPRECATED) 76 /// (Deprecated: Use rebind().) Specify an alternate allocator. 77 template <typename OtherAllocator> operator [](const OtherAllocator & allocator) const78 use_future_t<OtherAllocator> operator[](const OtherAllocator& allocator) const 79 { 80 return use_future_t<OtherAllocator>(allocator); 81 } 82 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 83 84 /// Specify an alternate allocator. 85 template <typename OtherAllocator> rebind(const OtherAllocator & allocator) const86 use_future_t<OtherAllocator> rebind(const OtherAllocator& allocator) const 87 { 88 return use_future_t<OtherAllocator>(allocator); 89 } 90 91 /// Obtain allocator. get_allocator() const92 allocator_type get_allocator() const 93 { 94 return allocator_; 95 } 96 97 /// Wrap a function object in a packaged task. 98 /** 99 * The @c package function is used to adapt a function object as a packaged 100 * task. When this adapter is passed as a completion token to an asynchronous 101 * operation, the result of the function object is retuned via a std::future. 102 * 103 * @par Example 104 * 105 * @code std::future<std::size_t> fut = 106 * my_socket.async_read_some(buffer, 107 * use_future([](boost::system::error_code ec, std::size_t n) 108 * { 109 * return ec ? 0 : n; 110 * })); 111 * ... 112 * std::size_t n = fut.get(); @endcode 113 */ 114 template <typename Function> 115 #if defined(GENERATING_DOCUMENTATION) 116 unspecified 117 #else // defined(GENERATING_DOCUMENTATION) 118 detail::packaged_token<typename decay<Function>::type, Allocator> 119 #endif // defined(GENERATING_DOCUMENTATION) 120 operator()(BOOST_ASIO_MOVE_ARG(Function) f) const; 121 122 private: 123 // Helper type to ensure that use_future can be constexpr default-constructed 124 // even when std::allocator<void> can't be. 125 struct std_allocator_void 126 { std_allocator_voidboost::asio::use_future_t::std_allocator_void127 BOOST_ASIO_CONSTEXPR std_allocator_void() 128 { 129 } 130 operator std::allocator<void>boost::asio::use_future_t::std_allocator_void131 operator std::allocator<void>() const 132 { 133 return std::allocator<void>(); 134 } 135 }; 136 137 typename conditional< 138 is_same<std::allocator<void>, Allocator>::value, 139 std_allocator_void, Allocator>::type allocator_; 140 }; 141 142 /// A special value, similar to std::nothrow. 143 /** 144 * See the documentation for boost::asio::use_future_t for a usage example. 145 */ 146 #if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) 147 constexpr use_future_t<> use_future; 148 #elif defined(BOOST_ASIO_MSVC) 149 __declspec(selectany) use_future_t<> use_future; 150 #endif 151 152 } // namespace asio 153 } // namespace boost 154 155 #include <boost/asio/detail/pop_options.hpp> 156 157 #include <boost/asio/impl/use_future.hpp> 158 159 #endif // defined(BOOST_ASIO_HAS_STD_FUTURE_CLASS) 160 // || defined(GENERATING_DOCUMENTATION) 161 162 #endif // BOOST_ASIO_USE_FUTURE_HPP 163