diff options
Diffstat (limited to '3rdparty/asio/include/asio/cancellation_signal.hpp')
-rw-r--r-- | 3rdparty/asio/include/asio/cancellation_signal.hpp | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/3rdparty/asio/include/asio/cancellation_signal.hpp b/3rdparty/asio/include/asio/cancellation_signal.hpp new file mode 100644 index 00000000000..afbaecdaf40 --- /dev/null +++ b/3rdparty/asio/include/asio/cancellation_signal.hpp @@ -0,0 +1,359 @@ +// +// cancellation_signal.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// 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_CANCELLATION_SIGNAL_HPP +#define ASIO_CANCELLATION_SIGNAL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <cassert> +#include <new> +#include <utility> +#include "asio/cancellation_type.hpp" +#include "asio/detail/cstddef.hpp" +#include "asio/detail/thread_context.hpp" +#include "asio/detail/thread_info_base.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/detail/variadic_templates.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class cancellation_handler_base +{ +public: + virtual void call(cancellation_type_t) = 0; + virtual std::pair<void*, std::size_t> destroy() ASIO_NOEXCEPT = 0; + +protected: + ~cancellation_handler_base() {} +}; + +template <typename Handler> +class cancellation_handler + : public cancellation_handler_base +{ +public: +#if defined(ASIO_HAS_VARIADIC_TEMPLATES) + template <typename... Args> + cancellation_handler(std::size_t size, ASIO_MOVE_ARG(Args)... args) + : handler_(ASIO_MOVE_CAST(Args)(args)...), + size_(size) + { + } +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + cancellation_handler(std::size_t size) + : handler_(), + size_(size) + { + } + +#define ASIO_PRIVATE_HANDLER_CTOR_DEF(n) \ + template <ASIO_VARIADIC_TPARAMS(n)> \ + cancellation_handler(std::size_t size, ASIO_VARIADIC_MOVE_PARAMS(n)) \ + : handler_(ASIO_VARIADIC_MOVE_ARGS(n)), \ + size_(size) \ + { \ + } \ + /**/ + ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_CTOR_DEF) +#undef ASIO_PRIVATE_HANDLER_CTOR_DEF +#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) + + void call(cancellation_type_t type) + { + handler_(type); + } + + std::pair<void*, std::size_t> destroy() ASIO_NOEXCEPT + { + std::pair<void*, std::size_t> mem(this, size_); + this->cancellation_handler::~cancellation_handler(); + return mem; + } + + Handler& handler() ASIO_NOEXCEPT + { + return handler_; + } + +private: + ~cancellation_handler() + { + } + + Handler handler_; + std::size_t size_; +}; + +} // namespace detail + +class cancellation_slot; + +/// A cancellation signal with a single slot. +class cancellation_signal +{ +public: + ASIO_CONSTEXPR cancellation_signal() + : handler_(0) + { + } + + ~cancellation_signal() + { + if (handler_) + { + std::pair<void*, std::size_t> mem = handler_->destroy(); + detail::thread_info_base::deallocate( + detail::thread_info_base::cancellation_signal_tag(), + detail::thread_context::top_of_thread_call_stack(), + mem.first, mem.second); + } + } + + /// Emits the signal and causes invocation of the slot's handler, if any. + void emit(cancellation_type_t type) + { + if (handler_) + handler_->call(type); + } + + /// Returns the single slot associated with the signal. + /** + * The signal object must remain valid for as long the slot may be used. + * Destruction of the signal invalidates the slot. + */ + cancellation_slot slot() ASIO_NOEXCEPT; + +private: + cancellation_signal(const cancellation_signal&) ASIO_DELETED; + cancellation_signal& operator=(const cancellation_signal&) ASIO_DELETED; + + detail::cancellation_handler_base* handler_; +}; + +/// A slot associated with a cancellation signal. +class cancellation_slot +{ +public: + /// Creates a slot that is not connected to any cancellation signal. + ASIO_CONSTEXPR cancellation_slot() + : handler_(0) + { + } + +#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \ + || defined(GENERATING_DOCUMENTATION) + /// Installs a handler into the slot, constructing the new object directly. + /** + * Destroys any existing handler in the slot, then installs the new handler, + * constructing it with the supplied @c args. + * + * The handler is a function object to be called when the signal is emitted. + * The signature of the handler must be + * @code void handler(asio::cancellation_type_t); @endcode + * + * @param args Arguments to be passed to the @c CancellationHandler object's + * constructor. + * + * @returns A reference to the newly installed handler. + * + * @note Handlers installed into the slot via @c emplace are not required to + * be copy constructible or move constructible. + */ + template <typename CancellationHandler, typename... Args> + CancellationHandler& emplace(ASIO_MOVE_ARG(Args)... args) + { + typedef detail::cancellation_handler<CancellationHandler> + cancellation_handler_type; + auto_delete_helper del = { prepare_memory( + sizeof(cancellation_handler_type), + ASIO_ALIGNOF(CancellationHandler)) }; + cancellation_handler_type* handler_obj = + new (del.mem.first) cancellation_handler_type( + del.mem.second, ASIO_MOVE_CAST(Args)(args)...); + del.mem.first = 0; + *handler_ = handler_obj; + return handler_obj->handler(); + } +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + // || defined(GENERATING_DOCUMENTATION) + template <typename CancellationHandler> + CancellationHandler& emplace() + { + typedef detail::cancellation_handler<CancellationHandler> + cancellation_handler_type; + auto_delete_helper del = { prepare_memory( + sizeof(cancellation_handler_type), + ASIO_ALIGNOF(CancellationHandler)) }; + cancellation_handler_type* handler_obj = + new (del.mem.first) cancellation_handler_type(del.mem.second); + del.mem.first = 0; + *handler_ = handler_obj; + return handler_obj->handler(); + } + +#define ASIO_PRIVATE_HANDLER_EMPLACE_DEF(n) \ + template <typename CancellationHandler, ASIO_VARIADIC_TPARAMS(n)> \ + CancellationHandler& emplace(ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + typedef detail::cancellation_handler<CancellationHandler> \ + cancellation_handler_type; \ + auto_delete_helper del = { prepare_memory( \ + sizeof(cancellation_handler_type), \ + ASIO_ALIGNOF(CancellationHandler)) }; \ + cancellation_handler_type* handler_obj = \ + new (del.mem.first) cancellation_handler_type( \ + del.mem.second, ASIO_VARIADIC_MOVE_ARGS(n)); \ + del.mem.first = 0; \ + *handler_ = handler_obj; \ + return handler_obj->handler(); \ + } \ + /**/ + ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_EMPLACE_DEF) +#undef ASIO_PRIVATE_HANDLER_EMPLACE_DEF +#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) + + /// Installs a handler into the slot. + /** + * Destroys any existing handler in the slot, then installs the new handler, + * constructing it as a decay-copy of the supplied handler. + * + * The handler is a function object to be called when the signal is emitted. + * The signature of the handler must be + * @code void handler(asio::cancellation_type_t); @endcode + * + * @param handler The handler to be installed. + * + * @returns A reference to the newly installed handler. + */ + template <typename CancellationHandler> + typename decay<CancellationHandler>::type& assign( + ASIO_MOVE_ARG(CancellationHandler) handler) + { + return this->emplace<typename decay<CancellationHandler>::type>( + ASIO_MOVE_CAST(CancellationHandler)(handler)); + } + + /// Clears the slot. + /** + * Destroys any existing handler in the slot. + */ + void clear() + { + if (handler_ != 0 && *handler_ != 0) + { + std::pair<void*, std::size_t> mem = (*handler_)->destroy(); + detail::thread_info_base::deallocate( + detail::thread_info_base::cancellation_signal_tag(), + detail::thread_context::top_of_thread_call_stack(), + mem.first, mem.second); + *handler_ = 0; + } + } + + /// Returns whether the slot is connected to a signal. + ASIO_CONSTEXPR bool is_connected() const ASIO_NOEXCEPT + { + return handler_ != 0; + } + + /// Returns whether the slot is connected and has an installed handler. + ASIO_CONSTEXPR bool has_handler() const ASIO_NOEXCEPT + { + return handler_ != 0 && *handler_ != 0; + } + + /// Compare two slots for equality. + friend ASIO_CONSTEXPR bool operator==(const cancellation_slot& lhs, + const cancellation_slot& rhs) ASIO_NOEXCEPT + { + return lhs.handler_ == rhs.handler_; + } + + /// Compare two slots for inequality. + friend ASIO_CONSTEXPR bool operator!=(const cancellation_slot& lhs, + const cancellation_slot& rhs) ASIO_NOEXCEPT + { + return lhs.handler_ != rhs.handler_; + } + +private: + friend class cancellation_signal; + + ASIO_CONSTEXPR cancellation_slot(int, + detail::cancellation_handler_base** handler) + : handler_(handler) + { + } + + std::pair<void*, std::size_t> prepare_memory( + std::size_t size, std::size_t align) + { + assert(handler_); + std::pair<void*, std::size_t> mem; + if (*handler_) + { + mem = (*handler_)->destroy(); + *handler_ = 0; + } + if (size > mem.second + || reinterpret_cast<std::size_t>(mem.first) % align != 0) + { + if (mem.first) + { + detail::thread_info_base::deallocate( + detail::thread_info_base::cancellation_signal_tag(), + detail::thread_context::top_of_thread_call_stack(), + mem.first, mem.second); + } + mem.first = detail::thread_info_base::allocate( + detail::thread_info_base::cancellation_signal_tag(), + detail::thread_context::top_of_thread_call_stack(), + size, align); + mem.second = size; + } + return mem; + } + + struct auto_delete_helper + { + std::pair<void*, std::size_t> mem; + + ~auto_delete_helper() + { + if (mem.first) + { + detail::thread_info_base::deallocate( + detail::thread_info_base::cancellation_signal_tag(), + detail::thread_context::top_of_thread_call_stack(), + mem.first, mem.second); + } + } + }; + + detail::cancellation_handler_base** handler_; +}; + +inline cancellation_slot cancellation_signal::slot() ASIO_NOEXCEPT +{ + return cancellation_slot(0, &handler_); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_CANCELLATION_SIGNAL_HPP |