File indexing completed on 2025-07-12 08:08:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_ASIO_EXPERIMENTAL_PROMISE_HPP
0013 #define BOOST_ASIO_EXPERIMENTAL_PROMISE_HPP
0014
0015 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0016 # pragma once
0017 #endif
0018
0019 #include <boost/asio/detail/config.hpp>
0020 #include <boost/asio/detail/type_traits.hpp>
0021 #include <boost/asio/any_io_executor.hpp>
0022 #include <boost/asio/associated_cancellation_slot.hpp>
0023 #include <boost/asio/associated_executor.hpp>
0024 #include <boost/asio/bind_executor.hpp>
0025 #include <boost/asio/cancellation_signal.hpp>
0026 #include <boost/asio/dispatch.hpp>
0027 #include <boost/asio/experimental/impl/promise.hpp>
0028 #include <boost/asio/post.hpp>
0029
0030 #include <algorithm>
0031
0032 #include <boost/asio/detail/push_options.hpp>
0033
0034 namespace boost {
0035 namespace asio {
0036 namespace experimental {
0037
0038 template <typename T>
0039 struct is_promise : std::false_type {};
0040
0041 template <typename ... Ts>
0042 struct is_promise<promise<Ts...>> : std::true_type {};
0043
0044 template <typename T>
0045 constexpr bool is_promise_v = is_promise<T>::value;
0046
0047 template <typename ... Ts>
0048 struct promise_value_type
0049 {
0050 using type = std::tuple<Ts...>;
0051 };
0052
0053 template <typename T>
0054 struct promise_value_type<T>
0055 {
0056 using type = T;
0057 };
0058
0059 template <>
0060 struct promise_value_type<>
0061 {
0062 using type = std::tuple<>;
0063 };
0064
0065 #if defined(GENERATING_DOCUMENTATION)
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 template<typename Signature = void(),
0096 typename Executor = boost::asio::any_io_executor,
0097 typename Allocator = std::allocator<void>>
0098 struct promise
0099 #else
0100 template <typename ... Ts, typename Executor, typename Allocator>
0101 struct promise<void(Ts...), Executor, Allocator>
0102 #endif
0103 {
0104
0105 using value_type = typename promise_value_type<Ts...>::type;
0106
0107
0108 void cancel(cancellation_type level = cancellation_type::all)
0109 {
0110 if (impl_ && !impl_->done)
0111 {
0112 boost::asio::dispatch(impl_->executor,
0113 [level, impl = impl_]{ impl->cancel.emit(level); });
0114 }
0115 }
0116
0117
0118 bool completed() const noexcept
0119 {
0120 return impl_ && impl_->done;
0121 }
0122
0123
0124 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(Ts...)) CompletionToken>
0125 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(Ts...))
0126 operator()(CompletionToken&& token)
0127 {
0128 assert(impl_);
0129
0130 return async_initiate<CompletionToken, void(Ts...)>(
0131 initiate_async_wait{impl_}, token);
0132 }
0133
0134 promise() = delete;
0135 promise(const promise& ) = delete;
0136 promise(promise&& ) noexcept = default;
0137
0138
0139
0140
0141
0142 ~promise() { cancel(); }
0143
0144 private:
0145 #if !defined(GENERATING_DOCUMENTATION)
0146 template <typename, typename, typename> friend struct promise;
0147 friend struct detail::promise_handler<void(Ts...), Executor, Allocator>;
0148 #endif
0149
0150 std::shared_ptr<detail::promise_impl<
0151 void(Ts...), Executor, Allocator>> impl_;
0152
0153 promise(
0154 std::shared_ptr<detail::promise_impl<
0155 void(Ts...), Executor, Allocator>> impl)
0156 : impl_(impl)
0157 {
0158 }
0159
0160 struct initiate_async_wait
0161 {
0162 std::shared_ptr<detail::promise_impl<
0163 void(Ts...), Executor, Allocator>> self_;
0164
0165 template <typename WaitHandler>
0166 void operator()(WaitHandler&& handler) const
0167 {
0168 const auto alloc = get_associated_allocator(
0169 handler, self_->get_allocator());
0170
0171 auto cancel = get_associated_cancellation_slot(handler);
0172
0173 if (self_->done)
0174 {
0175 auto exec = boost::asio::get_associated_executor(
0176 handler, self_->get_executor());
0177
0178 boost::asio::post(exec,
0179 [self = std::move(self_),
0180 handler = std::forward<WaitHandler>(handler)]() mutable
0181 {
0182 self->apply(std::move(handler));
0183 });
0184 }
0185 else
0186 {
0187 if (cancel.is_connected())
0188 {
0189 struct cancel_handler
0190 {
0191 std::weak_ptr<detail::promise_impl<
0192 void(Ts...), Executor, Allocator>> self;
0193
0194 cancel_handler(
0195 std::weak_ptr<detail::promise_impl<
0196 void(Ts...), Executor, Allocator>> self)
0197 : self(std::move(self))
0198 {
0199 }
0200
0201 void operator()(cancellation_type level) const
0202 {
0203 if (auto p = self.lock())
0204 {
0205 p->cancel.emit(level);
0206 p->cancel_();
0207 }
0208 }
0209 };
0210 cancel.template emplace<cancel_handler>(self_);
0211 }
0212
0213 self_->set_completion(alloc, std::forward<WaitHandler>(handler));
0214 }
0215 }
0216 };
0217 };
0218
0219 }
0220
0221 }
0222 }
0223
0224 #include <boost/asio/detail/pop_options.hpp>
0225
0226 #endif