From 76fbcb2f4505faea9ea78cd58ea64ec4e3ac9dbf Mon Sep 17 00:00:00 2001 From: Christopher Kohlhoff Date: Wed, 8 Mar 2023 21:05:14 +1100 Subject: [PATCH] Fix channels to support C++14 and (partially) C++11. C++11 support is limited to channels with a single completion signature, or channels with a void() signature (plus the error signature added by the channel traits). --- include/boost/asio/detail/config.hpp | 24 +++++ .../experimental/detail/channel_message.hpp | 11 ++- .../experimental/detail/channel_payload.hpp | 92 ++++++++++++++----- .../detail/channel_send_functions.hpp | 12 +++ .../experimental/detail/channel_service.hpp | 3 +- 5 files changed, 116 insertions(+), 26 deletions(-) diff --git a/include/boost/asio/detail/config.hpp b/include/boost/asio/detail/config.hpp index 0ff7f58a..928ee123 100644 --- a/include/boost/asio/detail/config.hpp +++ b/include/boost/asio/detail/config.hpp @@ -1443,6 +1443,30 @@ # endif // !defined(BOOST_ASIO_DISABLE_STD_ANY) #endif // !defined(BOOST_ASIO_HAS_STD_ANY) +// Standard library support for std::variant. +#if !defined(BOOST_ASIO_HAS_STD_VARIANT) +# if !defined(BOOST_ASIO_DISABLE_STD_VARIANT) +# if defined(__clang__) +# if (__cplusplus >= 201703) +# if __has_include() +# define BOOST_ASIO_HAS_STD_VARIANT 1 +# endif // __has_include() +# endif // (__cplusplus >= 201703) +# elif defined(__GNUC__) +# if (__GNUC__ >= 7) +# if (__cplusplus >= 201703) +# define BOOST_ASIO_HAS_STD_VARIANT 1 +# endif // (__cplusplus >= 201703) +# endif // (__GNUC__ >= 7) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1910) && (_MSVC_LANG >= 201703) +# define BOOST_ASIO_HAS_STD_VARIANT 1 +# endif // (_MSC_VER >= 1910) && (_MSVC_LANG >= 201703) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_STD_VARIANT) +#endif // !defined(BOOST_ASIO_HAS_STD_VARIANT) + // Standard library support for std::source_location. #if !defined(BOOST_ASIO_HAS_STD_SOURCE_LOCATION) # if !defined(BOOST_ASIO_DISABLE_STD_SOURCE_LOCATION) diff --git a/include/boost/asio/experimental/detail/channel_message.hpp b/include/boost/asio/experimental/detail/channel_message.hpp index 047aadf0..3d81af5c 100644 --- a/include/boost/asio/experimental/detail/channel_message.hpp +++ b/include/boost/asio/experimental/detail/channel_message.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -105,11 +106,17 @@ public: template void receive(Handler& h) { - std::apply(BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h), - BOOST_ASIO_MOVE_CAST(args_type)(args_)); + this->do_receive(h, boost::asio::detail::index_sequence_for()); } private: + template + void do_receive(Handler& h, boost::asio::detail::index_sequence) + { + BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)( + std::get(BOOST_ASIO_MOVE_CAST(args_type)(args_))...); + } + typedef std::tuple::type...> args_type; args_type args_; }; diff --git a/include/boost/asio/experimental/detail/channel_payload.hpp b/include/boost/asio/experimental/detail/channel_payload.hpp index 0621ce16..83ccb2eb 100644 --- a/include/boost/asio/experimental/detail/channel_payload.hpp +++ b/include/boost/asio/experimental/detail/channel_payload.hpp @@ -16,10 +16,14 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include -#include #include +#include #include +#if defined(BOOST_ASIO_HAS_STD_VARIANT) +# include +#endif // defined(BOOST_ASIO_HAS_STD_VARIANT) + #include namespace boost { @@ -28,28 +32,7 @@ namespace experimental { namespace detail { template -class channel_payload -{ -public: - template - channel_payload(BOOST_ASIO_MOVE_ARG(channel_message) m) - : message_(BOOST_ASIO_MOVE_CAST(channel_message)(m)) - { - } - - template - void receive(Handler& handler) - { - std::visit( - [&](auto& message) - { - message.receive(handler); - }, message_); - } - -private: - std::variant...> message_; -}; +class channel_payload; template class channel_payload @@ -85,6 +68,69 @@ private: channel_message message_; }; +#if defined(BOOST_ASIO_HAS_STD_VARIANT) + +template +class channel_payload +{ +public: + template + channel_payload(BOOST_ASIO_MOVE_ARG(channel_message) m) + : message_(BOOST_ASIO_MOVE_CAST(channel_message)(m)) + { + } + + template + void receive(Handler& handler) + { + std::visit( + [&](auto& message) + { + message.receive(handler); + }, message_); + } + +private: + std::variant...> message_; +}; + +#else // defined(BOOST_ASIO_HAS_STD_VARIANT) + +template +class channel_payload +{ +public: + typedef channel_message void_message_type; + typedef channel_message error_message_type; + + channel_payload(BOOST_ASIO_MOVE_ARG(void_message_type)) + : message_(0, boost::system::error_code()), + empty_(true) + { + } + + channel_payload(BOOST_ASIO_MOVE_ARG(error_message_type) m) + : message_(BOOST_ASIO_MOVE_CAST(error_message_type)(m)), + empty_(false) + { + } + + template + void receive(Handler& handler) + { + if (empty_) + channel_message(0).receive(handler); + else + message_.receive(handler); + } + +private: + error_message_type message_; + bool empty_; +}; + +#endif // defined(BOOST_ASIO_HAS_STD_VARIANT) + } // namespace detail } // namespace experimental } // namespace asio diff --git a/include/boost/asio/experimental/detail/channel_send_functions.hpp b/include/boost/asio/experimental/detail/channel_send_functions.hpp index d54400a9..f4fb588c 100644 --- a/include/boost/asio/experimental/detail/channel_send_functions.hpp +++ b/include/boost/asio/experimental/detail/channel_send_functions.hpp @@ -65,6 +65,12 @@ public: auto async_send(Args... args, BOOST_ASIO_MOVE_ARG(CompletionToken) token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor)) + -> decltype( + async_initiate( + declval::type::initiate_async_send>(), token, + declval::type::payload_type>())) { typedef typename Derived::payload_type payload_type; typedef typename detail::channel_message message_type; @@ -114,6 +120,12 @@ public: auto async_send(Args... args, BOOST_ASIO_MOVE_ARG(CompletionToken) token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor)) + -> decltype( + async_initiate( + declval::type::initiate_async_send>(), token, + declval::type::payload_type>())) { typedef typename Derived::payload_type payload_type; typedef typename detail::channel_message message_type; diff --git a/include/boost/asio/experimental/detail/channel_service.hpp b/include/boost/asio/experimental/detail/channel_service.hpp index e55e1f06..970144c6 100644 --- a/include/boost/asio/experimental/detail/channel_service.hpp +++ b/include/boost/asio/experimental/detail/channel_service.hpp @@ -537,6 +537,7 @@ struct channel_service::implementation_type< implementation_type() : size_(0) { + first_.count_ = 0; } // Move from another buffer. @@ -637,7 +638,7 @@ private: struct buffered_value { boost::system::error_code value_; - std::size_t count_ = 0; + std::size_t count_; }; struct value_handler