summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/include/asio/experimental/impl/promise.hpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asio/include/asio/experimental/impl/promise.hpp')
-rw-r--r--3rdparty/asio/include/asio/experimental/impl/promise.hpp255
1 files changed, 255 insertions, 0 deletions
diff --git a/3rdparty/asio/include/asio/experimental/impl/promise.hpp b/3rdparty/asio/include/asio/experimental/impl/promise.hpp
new file mode 100644
index 00000000000..a80cf110baa
--- /dev/null
+++ b/3rdparty/asio/include/asio/experimental/impl/promise.hpp
@@ -0,0 +1,255 @@
+//
+// experimental/impl/promise.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2021-2023 Klemens D. Morgenstern
+// (klemens dot morgenstern at gmx dot net)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef ASIO_EXPERIMENTAL_IMPL_PROMISE_HPP
+#define ASIO_EXPERIMENTAL_IMPL_PROMISE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/cancellation_signal.hpp"
+#include "asio/detail/utility.hpp"
+#include "asio/error.hpp"
+#include "asio/system_error.hpp"
+#include <tuple>
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace experimental {
+
+template<typename Signature = void(),
+ typename Executor = asio::any_io_executor,
+ typename Allocator = std::allocator<void>>
+struct promise;
+
+namespace detail {
+
+template<typename Signature, typename Executor, typename Allocator>
+struct promise_impl;
+
+template<typename... Ts, typename Executor, typename Allocator>
+struct promise_impl<void(Ts...), Executor, Allocator>
+{
+ using result_type = std::tuple<Ts...>;
+
+ promise_impl(Allocator allocator, Executor executor)
+ : allocator(std::move(allocator)), executor(std::move(executor))
+ {
+ }
+
+ promise_impl(const promise_impl&) = delete;
+
+ ~promise_impl()
+ {
+ if (completion)
+ this->cancel_();
+
+ if (done)
+ reinterpret_cast<result_type*>(&result)->~result_type();
+ }
+
+ aligned_storage_t<sizeof(result_type), alignof(result_type)> result;
+ std::atomic<bool> done{false};
+ cancellation_signal cancel;
+ Allocator allocator;
+ Executor executor;
+
+ template<typename Func, std::size_t... Idx>
+ void apply_impl(Func f, asio::detail::index_sequence<Idx...>)
+ {
+ auto& result_type = *reinterpret_cast<promise_impl::result_type*>(&result);
+ f(std::get<Idx>(std::move(result_type))...);
+ }
+
+ using allocator_type = Allocator;
+ allocator_type get_allocator() {return allocator;}
+
+ using executor_type = Executor;
+ executor_type get_executor() {return executor;}
+
+ template<typename Func>
+ void apply(Func f)
+ {
+ apply_impl(std::forward<Func>(f),
+ asio::detail::make_index_sequence<sizeof...(Ts)>{});
+ }
+
+ struct completion_base
+ {
+ virtual void invoke(Ts&&...ts) = 0;
+ };
+
+ template<typename Alloc, typename WaitHandler_>
+ struct completion_impl final : completion_base
+ {
+ WaitHandler_ handler;
+ Alloc allocator;
+ void invoke(Ts&&... ts)
+ {
+ auto h = std::move(handler);
+
+ using alloc_t = typename std::allocator_traits<
+ typename asio::decay<Alloc>::type>::template
+ rebind_alloc<completion_impl>;
+
+ alloc_t alloc_{allocator};
+ this->~completion_impl();
+ std::allocator_traits<alloc_t>::deallocate(alloc_, this, 1u);
+ std::move(h)(std::forward<Ts>(ts)...);
+ }
+
+ template<typename Alloc_, typename Handler_>
+ completion_impl(Alloc_&& alloc, Handler_&& wh)
+ : handler(std::forward<Handler_>(wh)),
+ allocator(std::forward<Alloc_>(alloc))
+ {
+ }
+ };
+
+ completion_base* completion = nullptr;
+ typename asio::aligned_storage<sizeof(void*) * 4,
+ alignof(completion_base)>::type completion_opt;
+
+ template<typename Alloc, typename Handler>
+ void set_completion(Alloc&& alloc, Handler&& handler)
+ {
+ if (completion)
+ cancel_();
+
+ using impl_t = completion_impl<
+ typename asio::decay<Alloc>::type, Handler>;
+ using alloc_t = typename std::allocator_traits<
+ typename asio::decay<Alloc>::type>::template rebind_alloc<impl_t>;
+
+ alloc_t alloc_{alloc};
+ auto p = std::allocator_traits<alloc_t>::allocate(alloc_, 1u);
+ completion = new (p) impl_t(std::forward<Alloc>(alloc),
+ std::forward<Handler>(handler));
+ }
+
+ template<typename... T_>
+ void complete(T_&&... ts)
+ {
+ assert(completion);
+ std::exchange(completion, nullptr)->invoke(std::forward<T_>(ts)...);
+ }
+
+ template<std::size_t... Idx>
+ void complete_with_result_impl(asio::detail::index_sequence<Idx...>)
+ {
+ auto& result_type = *reinterpret_cast<promise_impl::result_type*>(&result);
+ this->complete(std::get<Idx>(std::move(result_type))...);
+ }
+
+ void complete_with_result()
+ {
+ complete_with_result_impl(
+ asio::detail::make_index_sequence<sizeof...(Ts)>{});
+ }
+
+ template<typename... T_>
+ void cancel_impl_(std::exception_ptr*, T_*...)
+ {
+ complete(
+ std::make_exception_ptr(
+ asio::system_error(
+ asio::error::operation_aborted)),
+ T_{}...);
+ }
+
+ template<typename... T_>
+ void cancel_impl_(asio::error_code*, T_*...)
+ {
+ complete(asio::error::operation_aborted, T_{}...);
+ }
+
+ template<typename... T_>
+ void cancel_impl_(T_*...)
+ {
+ complete(T_{}...);
+ }
+
+ void cancel_()
+ {
+ cancel_impl_(static_cast<Ts*>(nullptr)...);
+ }
+};
+
+template<typename Signature = void(),
+ typename Executor = asio::any_io_executor,
+ typename Allocator = any_io_executor>
+struct promise_handler;
+
+template<typename... Ts, typename Executor, typename Allocator>
+struct promise_handler<void(Ts...), Executor, Allocator>
+{
+ using promise_type = promise<void(Ts...), Executor, Allocator>;
+
+ promise_handler(
+ Allocator allocator, Executor executor) // get_associated_allocator(exec)
+ : impl_(
+ std::allocate_shared<promise_impl<void(Ts...), Executor, Allocator>>(
+ allocator, allocator, executor))
+ {
+ }
+
+ std::shared_ptr<promise_impl<void(Ts...), Executor, Allocator>> impl_;
+
+ using cancellation_slot_type = cancellation_slot;
+
+ cancellation_slot_type get_cancellation_slot() const noexcept
+ {
+ return impl_->cancel.slot();
+ }
+
+ using allocator_type = Allocator;
+
+ allocator_type get_allocator() const noexcept
+ {
+ return impl_->get_allocator();
+ }
+
+ using executor_type = Executor;
+
+ Executor get_executor() const noexcept
+ {
+ return impl_->get_executor();
+ }
+
+ auto make_promise() -> promise<void(Ts...), executor_type, allocator_type>
+ {
+ return promise<void(Ts...), executor_type, allocator_type>{impl_};
+ }
+
+ void operator()(std::remove_reference_t<Ts>... ts)
+ {
+ assert(impl_);
+
+ using result_type = typename promise_impl<
+ void(Ts...), allocator_type, executor_type>::result_type ;
+
+ new (&impl_->result) result_type(std::move(ts)...);
+ impl_->done = true;
+
+ if (impl_->completion)
+ impl_->complete_with_result();
+ }
+};
+
+} // namespace detail
+} // namespace experimental
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_EXPERIMENTAL_IMPL_PROMISE_HPP