File indexing completed on 2024-11-15 09:03:04
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 template<typename Signature = void(),
0095 typename Executor = boost::asio::any_io_executor,
0096 typename Allocator = std::allocator<void>>
0097 struct promise
0098 #else
0099 template <typename ... Ts, typename Executor, typename Allocator>
0100 struct promise<void(Ts...), Executor, Allocator>
0101 #endif
0102 {
0103
0104 using value_type = typename promise_value_type<Ts...>::type;
0105
0106
0107 void cancel(cancellation_type level = cancellation_type::all)
0108 {
0109 if (impl_ && !impl_->done)
0110 {
0111 boost::asio::dispatch(impl_->executor,
0112 [level, impl = impl_]{ impl->cancel.emit(level); });
0113 }
0114 }
0115
0116
0117 bool completed() const noexcept
0118 {
0119 return impl_ && impl_->done;
0120 }
0121
0122
0123 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(Ts...)) CompletionToken>
0124 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(Ts...))
0125 operator()(CompletionToken&& token)
0126 {
0127 assert(impl_);
0128
0129 return async_initiate<CompletionToken, void(Ts...)>(
0130 initiate_async_wait{impl_}, token);
0131 }
0132
0133 promise() = delete;
0134 promise(const promise& ) = delete;
0135 promise(promise&& ) noexcept = default;
0136
0137
0138
0139
0140
0141 ~promise() { cancel(); }
0142
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