2
0
mirror of https://github.com/boostorg/asio.git synced 2026-01-25 05:52:09 +00:00

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).
This commit is contained in:
Christopher Kohlhoff
2023-03-08 21:05:14 +11:00
parent 076089ec77
commit 76fbcb2f45
5 changed files with 116 additions and 26 deletions

View File

@@ -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(<variant>)
# define BOOST_ASIO_HAS_STD_VARIANT 1
# endif // __has_include(<variant>)
# 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)

View File

@@ -18,6 +18,7 @@
#include <boost/asio/detail/config.hpp>
#include <tuple>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/utility.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -105,11 +106,17 @@ public:
template <typename Handler>
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<Args...>());
}
private:
template <typename Handler, std::size_t... I>
void do_receive(Handler& h, boost::asio::detail::index_sequence<I...>)
{
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(
std::get<I>(BOOST_ASIO_MOVE_CAST(args_type)(args_))...);
}
typedef std::tuple<typename decay<Args>::type...> args_type;
args_type args_;
};

View File

@@ -16,10 +16,14 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <variant>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/system/error_code.hpp>
#include <boost/asio/experimental/detail/channel_message.hpp>
#if defined(BOOST_ASIO_HAS_STD_VARIANT)
# include <variant>
#endif // defined(BOOST_ASIO_HAS_STD_VARIANT)
#include <boost/asio/detail/push_options.hpp>
namespace boost {
@@ -28,28 +32,7 @@ namespace experimental {
namespace detail {
template <typename... Signatures>
class channel_payload
{
public:
template <typename Signature>
channel_payload(BOOST_ASIO_MOVE_ARG(channel_message<Signature>) m)
: message_(BOOST_ASIO_MOVE_CAST(channel_message<Signature>)(m))
{
}
template <typename Handler>
void receive(Handler& handler)
{
std::visit(
[&](auto& message)
{
message.receive(handler);
}, message_);
}
private:
std::variant<channel_message<Signatures>...> message_;
};
class channel_payload;
template <typename R>
class channel_payload<R()>
@@ -85,6 +68,69 @@ private:
channel_message<Signature> message_;
};
#if defined(BOOST_ASIO_HAS_STD_VARIANT)
template <typename... Signatures>
class channel_payload
{
public:
template <typename Signature>
channel_payload(BOOST_ASIO_MOVE_ARG(channel_message<Signature>) m)
: message_(BOOST_ASIO_MOVE_CAST(channel_message<Signature>)(m))
{
}
template <typename Handler>
void receive(Handler& handler)
{
std::visit(
[&](auto& message)
{
message.receive(handler);
}, message_);
}
private:
std::variant<channel_message<Signatures>...> message_;
};
#else // defined(BOOST_ASIO_HAS_STD_VARIANT)
template <typename R1, typename R2>
class channel_payload<R1(), R2(boost::system::error_code)>
{
public:
typedef channel_message<R1()> void_message_type;
typedef channel_message<R2(boost::system::error_code)> 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 <typename Handler>
void receive(Handler& handler)
{
if (empty_)
channel_message<R1()>(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

View File

@@ -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<CompletionToken, void (boost::system::error_code)>(
declval<typename conditional<false, CompletionToken,
Derived>::type::initiate_async_send>(), token,
declval<typename conditional<false, CompletionToken,
Derived>::type::payload_type>()))
{
typedef typename Derived::payload_type payload_type;
typedef typename detail::channel_message<R(Args...)> 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<CompletionToken, void (boost::system::error_code)>(
declval<typename conditional<false, CompletionToken,
Derived>::type::initiate_async_send>(), token,
declval<typename conditional<false, CompletionToken,
Derived>::type::payload_type>()))
{
typedef typename Derived::payload_type payload_type;
typedef typename detail::channel_message<R(Args...)> message_type;

View File

@@ -537,6 +537,7 @@ struct channel_service<Mutex>::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