319 changes: 275 additions & 44 deletions link/asio/async_result.hpp
Expand Up @@ -2,7 +2,7 @@
// async_result.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand All @@ -17,109 +17,340 @@

#include "asio/detail/config.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/handler_type.hpp"
#include "asio/detail/variadic_templates.hpp"

#include "asio/detail/push_options.hpp"

namespace asio {

/// An interface for customising the behaviour of an initiating function.
/**
* This template may be specialised for user-defined handler types.
* The async_result traits class is used for determining:
*
* @li the concrete completion handler type to be called at the end of the
* asynchronous operation;
*
* @li the initiating function return type; and
*
* @li how the return value of the initiating function is obtained.
*
* The trait allows the handler and return types to be determined at the point
* where the specific completion handler signature is known.
*
* This template may be specialised for user-defined completion token types.
* The primary template assumes that the CompletionToken is the completion
* handler.
*/
template <typename Handler>
template <typename CompletionToken, typename Signature>
class async_result
{
public:
/// The concrete completion handler type for the specific signature.
typedef CompletionToken completion_handler_type;

/// The return type of the initiating function.
typedef void type;
typedef void return_type;

/// Construct an async result from a given handler.
/**
* When using a specalised async_result, the constructor has an opportunity
* to initialise some state associated with the handler, which is then
* returned from the initiating function.
* to initialise some state associated with the completion handler, which is
* then returned from the initiating function.
*/
explicit async_result(Handler&)
explicit async_result(completion_handler_type& h)
{
(void)h;
}

/// Obtain the value to be returned from the initiating function.
type get()
return_type get()
{
}

#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \
|| defined(GENERATING_DOCUMENTATION)

/// Initiate the asynchronous operation that will produce the result, and
/// obtain the value to be returned from the initiating function.
template <typename Initiation, typename RawCompletionToken, typename... Args>
static return_type initiate(
ASIO_MOVE_ARG(Initiation) initiation,
ASIO_MOVE_ARG(RawCompletionToken) token,
ASIO_MOVE_ARG(Args)... args)
{
ASIO_MOVE_CAST(Initiation)(initiation)(
ASIO_MOVE_CAST(RawCompletionToken)(token),
ASIO_MOVE_CAST(Args)(args)...);
}

#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
// || defined(GENERATING_DOCUMENTATION)

template <typename Initiation, typename RawCompletionToken>
static return_type initiate(
ASIO_MOVE_ARG(Initiation) initiation,
ASIO_MOVE_ARG(RawCompletionToken) token)
{
ASIO_MOVE_CAST(Initiation)(initiation)(
ASIO_MOVE_CAST(RawCompletionToken)(token));
}

#define ASIO_PRIVATE_INITIATE_DEF(n) \
template <typename Initiation, typename RawCompletionToken, \
ASIO_VARIADIC_TPARAMS(n)> \
static return_type initiate( \
ASIO_MOVE_ARG(Initiation) initiation, \
ASIO_MOVE_ARG(RawCompletionToken) token, \
ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
ASIO_MOVE_CAST(Initiation)(initiation)( \
ASIO_MOVE_CAST(RawCompletionToken)(token), \
ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)
#undef ASIO_PRIVATE_INITIATE_DEF

#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
// || defined(GENERATING_DOCUMENTATION)

private:
async_result(const async_result&) ASIO_DELETED;
async_result& operator=(const async_result&) ASIO_DELETED;
};

/// Helper template to deduce the real type of a handler, capture a local copy
/// of the handler, and then create an async_result for the handler.
template <typename Handler, typename Signature>
/// Helper template to deduce the handler type from a CompletionToken, capture
/// a local copy of the handler, and then create an async_result for the
/// handler.
template <typename CompletionToken, typename Signature>
struct async_completion
{
/// The real handler type to be used for the asynchronous operation.
typedef typename asio::handler_type<
Handler, Signature>::type handler_type;
typedef typename asio::async_result<
typename decay<CompletionToken>::type,
Signature>::completion_handler_type completion_handler_type;

#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Constructor.
/**
* The constructor creates the concrete handler and makes the link between
* the handler and the asynchronous result.
* The constructor creates the concrete completion handler and makes the link
* between the handler and the asynchronous result.
*/
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
explicit async_completion(
Handler& orig_handler)
: handler(static_cast<typename conditional<
is_same<Handler, handler_type>::value,
handler_type&, Handler&&>::type>(orig_handler)),
result(handler)
explicit async_completion(CompletionToken& token)
: completion_handler(static_cast<typename conditional<
is_same<CompletionToken, completion_handler_type>::value,
completion_handler_type&, CompletionToken&&>::type>(token)),
result(completion_handler)
{
}
#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
explicit async_completion(const Handler& orig_handler)
: handler(orig_handler),
result(handler)
explicit async_completion(typename decay<CompletionToken>::type& token)
: completion_handler(token),
result(completion_handler)
{
}

explicit async_completion(const typename decay<CompletionToken>::type& token)
: completion_handler(token),
result(completion_handler)
{
}
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)

/// A copy of, or reference to, a real handler object.
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
typename conditional<
is_same<Handler, handler_type>::value,
handler_type&, handler_type>::type handler;
is_same<CompletionToken, completion_handler_type>::value,
completion_handler_type&, completion_handler_type>::type completion_handler;
#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
typename asio::handler_type<Handler, Signature>::type handler;
completion_handler_type completion_handler;
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)

/// The result of the asynchronous operation's initiating function.
async_result<typename asio::handler_type<
Handler, Signature>::type> result;
async_result<typename decay<CompletionToken>::type, Signature> result;
};

namespace detail {

template <typename Handler, typename Signature>
struct async_result_type_helper
template <typename CompletionToken, typename Signature>
struct async_result_helper
: async_result<typename decay<CompletionToken>::type, Signature>
{
typedef typename async_result<
typename handler_type<Handler, Signature>::type
>::type type;
};

} // namespace detail
} // namespace asio
struct async_result_memfns_base
{
void initiate();
};

#include "asio/detail/pop_options.hpp"
template <typename T>
struct async_result_memfns_derived
: T, async_result_memfns_base
{
};

template <typename T, T>
struct async_result_memfns_check
{
};

template <typename>
char (&async_result_initiate_memfn_helper(...))[2];

template <typename T>
char async_result_initiate_memfn_helper(
async_result_memfns_check<
void (async_result_memfns_base::*)(),
&async_result_memfns_derived<T>::initiate>*);

template <typename CompletionToken, typename Signature>
struct async_result_has_initiate_memfn
: integral_constant<bool, sizeof(async_result_initiate_memfn_helper<
async_result<typename decay<CompletionToken>::type, Signature>
>(0)) != 1>
{
};

} // namespace detail

#if defined(GENERATING_DOCUMENTATION)
# define ASIO_INITFN_RESULT_TYPE(h, sig) \
# define ASIO_INITFN_RESULT_TYPE(ct, sig) \
void_or_deduced
#elif defined(_MSC_VER) && (_MSC_VER < 1500)
# define ASIO_INITFN_RESULT_TYPE(h, sig) \
typename ::asio::detail::async_result_type_helper<h, sig>::type
# define ASIO_INITFN_RESULT_TYPE(ct, sig) \
typename ::asio::detail::async_result_helper< \
ct, sig>::return_type
#define ASIO_HANDLER_TYPE(ct, sig) \
typename ::asio::detail::async_result_helper< \
ct, sig>::completion_handler_type
#else
# define ASIO_INITFN_RESULT_TYPE(h, sig) \
# define ASIO_INITFN_RESULT_TYPE(ct, sig) \
typename ::asio::async_result< \
typename ::asio::decay<ct>::type, sig>::return_type
#define ASIO_HANDLER_TYPE(ct, sig) \
typename ::asio::async_result< \
typename ::asio::handler_type<h, sig>::type>::type
typename ::asio::decay<ct>::type, sig>::completion_handler_type
#endif

#if defined(GENERATING_DOCUMENTATION)

template <typename CompletionToken, typename Signature,
typename Initiation, typename... Args>
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken),
ASIO_MOVE_ARG(Args)... args);

#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)

template <typename CompletionToken, typename Signature,
typename Initiation, typename... Args>
inline typename enable_if<
detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type
async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
ASIO_MOVE_ARG(Args)... args)
{
return async_result<typename decay<CompletionToken>::type,
Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),
ASIO_MOVE_CAST(CompletionToken)(token),
ASIO_MOVE_CAST(Args)(args)...);
}

template <typename CompletionToken, typename Signature,
typename Initiation, typename... Args>
inline typename enable_if<
!detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type
async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
ASIO_MOVE_ARG(Args)... args)
{
async_completion<CompletionToken, Signature> completion(token);

ASIO_MOVE_CAST(Initiation)(initiation)(
ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,
Signature))(completion.completion_handler),
ASIO_MOVE_CAST(Args)(args)...);

return completion.result.get();
}

#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)

template <typename CompletionToken, typename Signature, typename Initiation>
inline typename enable_if<
detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type
async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
{
return async_result<typename decay<CompletionToken>::type,
Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),
ASIO_MOVE_CAST(CompletionToken)(token));
}

template <typename CompletionToken, typename Signature, typename Initiation>
inline typename enable_if<
!detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type
async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
{
async_completion<CompletionToken, Signature> completion(token);

ASIO_MOVE_CAST(Initiation)(initiation)(
ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,
Signature))(completion.completion_handler));

return completion.result.get();
}

#define ASIO_PRIVATE_INITIATE_DEF(n) \
template <typename CompletionToken, typename Signature, \
typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \
inline typename enable_if< \
detail::async_result_has_initiate_memfn< \
CompletionToken, Signature>::value, \
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type \
async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
return async_result<typename decay<CompletionToken>::type, \
Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation), \
ASIO_MOVE_CAST(CompletionToken)(token), \
ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
\
template <typename CompletionToken, typename Signature, \
typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \
inline typename enable_if< \
!detail::async_result_has_initiate_memfn< \
CompletionToken, Signature>::value, \
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type \
async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
async_completion<CompletionToken, Signature> completion(token); \
\
ASIO_MOVE_CAST(Initiation)(initiation)( \
ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, \
Signature))(completion.completion_handler), \
ASIO_VARIADIC_MOVE_ARGS(n)); \
\
return completion.result.get(); \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)
#undef ASIO_PRIVATE_INITIATE_DEF

#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)

} // namespace asio

#include "asio/detail/pop_options.hpp"

#endif // ASIO_ASYNC_RESULT_HPP
123 changes: 123 additions & 0 deletions link/asio/awaitable.hpp
@@ -0,0 +1,123 @@
//
// awaitable.hpp
// ~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 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_AWAITABLE_HPP
#define ASIO_AWAITABLE_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include "asio/detail/config.hpp"

#if defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)

#include <experimental/coroutine>
#include "asio/executor.hpp"

#include "asio/detail/push_options.hpp"

namespace asio {
namespace detail {

using std::experimental::coroutine_handle;
using std::experimental::suspend_always;

template <typename> class awaitable_thread;
template <typename, typename> class awaitable_frame;

} // namespace detail

/// The return type of a coroutine or asynchronous operation.
template <typename T, typename Executor = executor>
class awaitable
{
public:
/// The type of the awaited value.
typedef T value_type;

/// The executor type that will be used for the coroutine.
typedef Executor executor_type;

/// Default constructor.
constexpr awaitable() noexcept
: frame_(nullptr)
{
}

/// Move constructor.
awaitable(awaitable&& other) noexcept
: frame_(std::exchange(other.frame_, nullptr))
{
}

/// Destructor
~awaitable()
{
if (frame_)
frame_->destroy();
}

/// Checks if the awaitable refers to a future result.
bool valid() const noexcept
{
return !!frame_;
}

#if !defined(GENERATING_DOCUMENTATION)

// Support for co_await keyword.
bool await_ready() const noexcept
{
return false;
}

// Support for co_await keyword.
template <class U>
void await_suspend(
detail::coroutine_handle<detail::awaitable_frame<U, Executor>> h)
{
frame_->push_frame(&h.promise());
}

// Support for co_await keyword.
T await_resume()
{
return frame_->get();
}

#endif // !defined(GENERATING_DOCUMENTATION)

private:
template <typename> friend class detail::awaitable_thread;
template <typename, typename> friend class detail::awaitable_frame;

// Not copy constructible or copy assignable.
awaitable(const awaitable&) = delete;
awaitable& operator=(const awaitable&) = delete;

// Construct the awaitable from a coroutine's frame object.
explicit awaitable(detail::awaitable_frame<T, Executor>* a)
: frame_(a)
{
}

detail::awaitable_frame<T, Executor>* frame_;
};

} // namespace asio

#include "asio/detail/pop_options.hpp"

#include "asio/impl/awaitable.hpp"

#endif // defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)

#endif // ASIO_AWAITABLE_HPP
470 changes: 320 additions & 150 deletions link/asio/basic_datagram_socket.hpp

Large diffs are not rendered by default.

243 changes: 194 additions & 49 deletions link/asio/basic_deadline_timer.hpp

Large diffs are not rendered by default.

24 changes: 20 additions & 4 deletions link/asio/basic_io_object.hpp
Expand Up @@ -2,7 +2,7 @@
// basic_io_object.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down Expand Up @@ -34,12 +34,13 @@ namespace detail
typedef typename service_type::implementation_type implementation_type;

template <typename T, typename U>
static auto eval(T* t, U* u) -> decltype(t->move_construct(*u, *u), char());
static char (&eval(...))[2];
static auto asio_service_has_move_eval(T* t, U* u)
-> decltype(t->move_construct(*u, *u), char());
static char (&asio_service_has_move_eval(...))[2];

public:
static const bool value =
sizeof(service_has_move::eval(
sizeof(asio_service_has_move_eval(
static_cast<service_type*>(0),
static_cast<implementation_type*>(0))) == 1;
};
Expand Down Expand Up @@ -137,6 +138,11 @@ class basic_io_object
* @note Available only for services that support movability,
*/
basic_io_object& operator=(basic_io_object&& other);

/// Perform a converting move-construction of a basic_io_object.
template <typename IoObjectService1>
basic_io_object(IoObjectService1& other_service,
typename IoObjectService1::implementation_type& other_implementation);
#endif // defined(GENERATING_DOCUMENTATION)

/// Protected destructor to prevent deletion through this type.
Expand Down Expand Up @@ -225,6 +231,16 @@ class basic_io_object<IoObjectService, true>
service_->move_construct(implementation_, other.implementation_);
}

template <typename IoObjectService1>
basic_io_object(IoObjectService1& other_service,
typename IoObjectService1::implementation_type& other_implementation)
: service_(&asio::use_service<IoObjectService>(
other_service.get_io_context()))
{
service_->converting_move_construct(implementation_,
other_service, other_implementation);
}

~basic_io_object()
{
service_->destroy(implementation_);
Expand Down
473 changes: 322 additions & 151 deletions link/asio/basic_raw_socket.hpp

Large diffs are not rendered by default.

329 changes: 240 additions & 89 deletions link/asio/basic_seq_packet_socket.hpp

Large diffs are not rendered by default.

366 changes: 273 additions & 93 deletions link/asio/basic_serial_port.hpp

Large diffs are not rendered by default.

279 changes: 217 additions & 62 deletions link/asio/basic_signal_set.hpp

Large diffs are not rendered by default.

595 changes: 426 additions & 169 deletions link/asio/basic_socket.hpp

Large diffs are not rendered by default.

1,224 changes: 934 additions & 290 deletions link/asio/basic_socket_acceptor.hpp

Large diffs are not rendered by default.

172 changes: 127 additions & 45 deletions link/asio/basic_socket_iostream.hpp
Expand Up @@ -2,7 +2,7 @@
// basic_socket_iostream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand All @@ -22,7 +22,6 @@
#include <istream>
#include <ostream>
#include "asio/basic_socket_streambuf.hpp"
#include "asio/stream_socket_service.hpp"

#if !defined(ASIO_HAS_VARIADIC_TEMPLATES)

Expand All @@ -33,8 +32,7 @@
// explicit basic_socket_iostream(T1 x1, ..., Tn xn)
// : std::basic_iostream<char>(
// &this->detail::socket_iostream_base<
// Protocol, StreamSocketService, Time,
// TimeTraits, TimerService>::streambuf_)
// Protocol, Clock, WaitTraits>::streambuf_)
// {
// if (rdbuf()->connect(x1, ..., xn) == 0)
// this->setstate(std::ios_base::failbit);
Expand All @@ -46,8 +44,7 @@
explicit basic_socket_iostream(ASIO_VARIADIC_BYVAL_PARAMS(n)) \
: std::basic_iostream<char>( \
&this->detail::socket_iostream_base< \
Protocol, StreamSocketService, Time, \
TimeTraits, TimerService>::streambuf_) \
Protocol, Clock, WaitTraits>::streambuf_) \
{ \
this->setf(std::ios_base::unitbuf); \
if (rdbuf()->connect(ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \
Expand Down Expand Up @@ -82,60 +79,102 @@ namespace detail {

// A separate base class is used to ensure that the streambuf is initialised
// prior to the basic_socket_iostream's basic_iostream base class.
template <typename Protocol, typename StreamSocketService,
typename Time, typename TimeTraits, typename TimerService>
template <typename Protocol, typename Clock, typename WaitTraits>
class socket_iostream_base
{
protected:
basic_socket_streambuf<Protocol, StreamSocketService,
Time, TimeTraits, TimerService> streambuf_;
socket_iostream_base()
{
}

#if defined(ASIO_HAS_MOVE)
socket_iostream_base(socket_iostream_base&& other)
: streambuf_(std::move(other.streambuf_))
{
}

socket_iostream_base(basic_stream_socket<Protocol> s)
: streambuf_(std::move(s))
{
}

socket_iostream_base& operator=(socket_iostream_base&& other)
{
streambuf_ = std::move(other.streambuf_);
return *this;
}
#endif // defined(ASIO_HAS_MOVE)

basic_socket_streambuf<Protocol, Clock, WaitTraits> streambuf_;
};

}
} // namespace detail

/// Iostream interface for a socket.
#if !defined(ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
#define ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL

// Forward declaration with defaulted arguments.
template <typename Protocol,
typename StreamSocketService = stream_socket_service<Protocol>,
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
|| defined(GENERATING_DOCUMENTATION)
typename Time = boost::posix_time::ptime,
typename TimeTraits = asio::time_traits<Time>,
typename TimerService = deadline_timer_service<Time, TimeTraits> >
#else
typename Time = steady_timer::clock_type,
typename TimeTraits = steady_timer::traits_type,
typename TimerService = steady_timer::service_type>
#endif
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
typename Clock = boost::posix_time::ptime,
typename WaitTraits = time_traits<Clock> >
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
typename Clock = chrono::steady_clock,
typename WaitTraits = wait_traits<Clock> >
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
class basic_socket_iostream;

#endif // !defined(ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)

/// Iostream interface for a socket.
#if defined(GENERATING_DOCUMENTATION)
template <typename Protocol,
typename Clock = chrono::steady_clock,
typename WaitTraits = wait_traits<Clock> >
#else // defined(GENERATING_DOCUMENTATION)
template <typename Protocol, typename Clock, typename WaitTraits>
#endif // defined(GENERATING_DOCUMENTATION)
class basic_socket_iostream
: private detail::socket_iostream_base<Protocol,
StreamSocketService, Time, TimeTraits, TimerService>,
: private detail::socket_iostream_base<Protocol, Clock, WaitTraits>,
public std::basic_iostream<char>
{
private:
// These typedefs are intended keep this class's implementation independent
// of whether it's using Boost.DateTime, Boost.Chrono or std::chrono.
#if defined(ASIO_HAS_BOOST_DATE_TIME)
typedef TimeTraits traits_helper;
#else
typedef detail::chrono_time_traits<Time, TimeTraits> traits_helper;
#endif
// of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
typedef WaitTraits traits_helper;
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)

public:
/// The protocol type.
typedef Protocol protocol_type;

/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;

/// The clock type.
typedef Clock clock_type;

#if defined(GENERATING_DOCUMENTATION)
/// (Deprecated: Use time_point.) The time type.
typedef typename TimeTraits::time_type time_type;
typedef typename WaitTraits::time_type time_type;

/// The time type.
typedef typename TimeTraits::time_point time_point;
typedef typename WaitTraits::time_point time_point;

/// (Deprecated: Use duration.) The duration type.
typedef typename TimeTraits::duration_type duration_type;
typedef typename WaitTraits::duration_type duration_type;

/// The duration type.
typedef typename TimeTraits::duration duration;
typedef typename WaitTraits::duration duration;
#else
# if !defined(ASIO_NO_DEPRECATED)
typedef typename traits_helper::time_type time_type;
Expand All @@ -149,12 +188,47 @@ class basic_socket_iostream
basic_socket_iostream()
: std::basic_iostream<char>(
&this->detail::socket_iostream_base<
Protocol, StreamSocketService, Time,
TimeTraits, TimerService>::streambuf_)
Protocol, Clock, WaitTraits>::streambuf_)
{
this->setf(std::ios_base::unitbuf);
}

#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Construct a basic_socket_iostream from the supplied socket.
explicit basic_socket_iostream(basic_stream_socket<protocol_type> s)
: detail::socket_iostream_base<
Protocol, Clock, WaitTraits>(std::move(s)),
std::basic_iostream<char>(
&this->detail::socket_iostream_base<
Protocol, Clock, WaitTraits>::streambuf_)
{
this->setf(std::ios_base::unitbuf);
}

#if defined(ASIO_HAS_STD_IOSTREAM_MOVE) \
|| defined(GENERATING_DOCUMENTATION)
/// Move-construct a basic_socket_iostream from another.
basic_socket_iostream(basic_socket_iostream&& other)
: detail::socket_iostream_base<
Protocol, Clock, WaitTraits>(std::move(other)),
std::basic_iostream<char>(std::move(other))
{
this->set_rdbuf(&this->detail::socket_iostream_base<
Protocol, Clock, WaitTraits>::streambuf_);
}

/// Move-assign a basic_socket_iostream from another.
basic_socket_iostream& operator=(basic_socket_iostream&& other)
{
std::basic_iostream<char>::operator=(std::move(other));
detail::socket_iostream_base<
Protocol, Clock, WaitTraits>::operator=(std::move(other));
return *this;
}
#endif // defined(ASIO_HAS_STD_IOSTREAM_MOVE)
// || defined(GENERATING_DOCUMENTATION)
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)

#if defined(GENERATING_DOCUMENTATION)
/// Establish a connection to an endpoint corresponding to a resolver query.
/**
Expand All @@ -169,8 +243,7 @@ class basic_socket_iostream
explicit basic_socket_iostream(T... x)
: std::basic_iostream<char>(
&this->detail::socket_iostream_base<
Protocol, StreamSocketService, Time,
TimeTraits, TimerService>::streambuf_)
Protocol, Clock, WaitTraits>::streambuf_)
{
this->setf(std::ios_base::unitbuf);
if (rdbuf()->connect(x...) == 0)
Expand Down Expand Up @@ -208,14 +281,17 @@ class basic_socket_iostream
}

/// Return a pointer to the underlying streambuf.
basic_socket_streambuf<Protocol, StreamSocketService,
Time, TimeTraits, TimerService>* rdbuf() const
basic_socket_streambuf<Protocol, Clock, WaitTraits>* rdbuf() const
{
return const_cast<basic_socket_streambuf<Protocol, StreamSocketService,
Time, TimeTraits, TimerService>*>(
return const_cast<basic_socket_streambuf<Protocol, Clock, WaitTraits>*>(
&this->detail::socket_iostream_base<
Protocol, StreamSocketService, Time,
TimeTraits, TimerService>::streambuf_);
Protocol, Clock, WaitTraits>::streambuf_);
}

/// Get a reference to the underlying socket.
basic_socket<Protocol>& socket()
{
return rdbuf()->socket();
}

/// Get the last error associated with the stream.
Expand All @@ -232,7 +308,7 @@ class basic_socket_iostream
*/
const asio::error_code& error() const
{
return rdbuf()->puberror();
return rdbuf()->error();
}

#if !defined(ASIO_NO_DEPRECATED)
Expand Down Expand Up @@ -309,6 +385,12 @@ class basic_socket_iostream
rdbuf()->expires_from_now(expiry_time);
}
#endif // !defined(ASIO_NO_DEPRECATED)

private:
// Disallow copying and assignment.
basic_socket_iostream(const basic_socket_iostream&) ASIO_DELETED;
basic_socket_iostream& operator=(
const basic_socket_iostream&) ASIO_DELETED;
};

} // namespace asio
Expand Down
673 changes: 357 additions & 316 deletions link/asio/basic_socket_streambuf.hpp

Large diffs are not rendered by default.

383 changes: 264 additions & 119 deletions link/asio/basic_stream_socket.hpp

Large diffs are not rendered by default.

9 changes: 4 additions & 5 deletions link/asio/basic_streambuf.hpp
Expand Up @@ -2,7 +2,7 @@
// basic_streambuf.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down Expand Up @@ -119,8 +119,8 @@ class basic_streambuf
/// The type used to represent the output sequence as a list of buffers.
typedef implementation_defined mutable_buffers_type;
#else
typedef asio::const_buffers_1 const_buffers_type;
typedef asio::mutable_buffers_1 mutable_buffers_type;
typedef ASIO_CONST_BUFFER const_buffers_type;
typedef ASIO_MUTABLE_BUFFER mutable_buffers_type;
#endif

/// Construct a basic_streambuf object.
Expand Down Expand Up @@ -232,8 +232,7 @@ class basic_streambuf
*/
void commit(std::size_t n)
{
if (pptr() + n > epptr())
n = epptr() - pptr();
n = std::min<std::size_t>(n, epptr() - pptr());
pbump(static_cast<int>(n));
setg(eback(), gptr(), pptr());
}
Expand Down
2 changes: 1 addition & 1 deletion link/asio/basic_streambuf_fwd.hpp
Expand Up @@ -2,7 +2,7 @@
// basic_streambuf_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
292 changes: 197 additions & 95 deletions link/asio/basic_waitable_timer.hpp

Large diffs are not rendered by default.

38 changes: 20 additions & 18 deletions link/asio/bind_executor.hpp
Expand Up @@ -2,7 +2,7 @@
// bind_executor.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand All @@ -18,9 +18,11 @@
#include "asio/detail/config.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/detail/variadic_templates.hpp"
#include "asio/associated_executor.hpp"
#include "asio/associated_allocator.hpp"
#include "asio/async_result.hpp"
#include "asio/handler_type.hpp"
#include "asio/execution_context.hpp"
#include "asio/is_executor.hpp"
#include "asio/uses_executor.hpp"

#include "asio/detail/push_options.hpp"
Expand Down Expand Up @@ -166,27 +168,27 @@ class executor_binder_base<T, Executor, true>
protected:
template <typename E, typename U>
executor_binder_base(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(U) u)
: Executor(ASIO_MOVE_CAST(E)(e)),
target_(executor_arg_t(), static_cast<const Executor&>(*this),
ASIO_MOVE_CAST(U)(u))
: executor_(ASIO_MOVE_CAST(E)(e)),
target_(executor_arg_t(), executor_, ASIO_MOVE_CAST(U)(u))
{
}

Executor executor_;
T target_;
};

template <typename T, typename Executor>
class executor_binder_base<T, Executor, false>
: protected Executor
{
protected:
template <typename E, typename U>
executor_binder_base(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(U) u)
: Executor(ASIO_MOVE_CAST(E)(e)),
: executor_(ASIO_MOVE_CAST(E)(e)),
target_(ASIO_MOVE_CAST(U)(u))
{
}

Executor executor_;
T target_;
};

Expand Down Expand Up @@ -393,7 +395,7 @@ class executor_binder
/// Obtain the associated executor.
executor_type get_executor() const ASIO_NOEXCEPT
{
return static_cast<const Executor&>(*this);
return this->executor_;
}

#if defined(GENERATING_DOCUMENTATION)
Expand Down Expand Up @@ -519,30 +521,30 @@ struct uses_executor<executor_binder<T, Executor>, Executor>
: true_type {};

template <typename T, typename Executor, typename Signature>
struct handler_type<executor_binder<T, Executor>, Signature>
class async_result<executor_binder<T, Executor>, Signature>
{
public:
typedef executor_binder<
typename handler_type<T, Signature>::type, Executor> type;
};
typename async_result<T, Signature>::completion_handler_type, Executor>
completion_handler_type;

template <typename T, typename Executor>
class async_result<executor_binder<T, Executor> >
{
public:
typedef typename async_result<T>::type type;
typedef typename async_result<T, Signature>::return_type return_type;

explicit async_result(executor_binder<T, Executor>& b)
: target_(b.get())
{
}

type get()
return_type get()
{
return target_.get();
}

private:
async_result<T> target_;
async_result(const async_result&) ASIO_DELETED;
async_result& operator=(const async_result&) ASIO_DELETED;

async_result<T, Signature> target_;
};

template <typename T, typename Executor, typename Allocator>
Expand Down
2,393 changes: 1,081 additions & 1,312 deletions link/asio/buffer.hpp

Large diffs are not rendered by default.

34 changes: 6 additions & 28 deletions link/asio/buffered_read_stream.hpp
Expand Up @@ -2,7 +2,7 @@
// buffered_read_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand All @@ -26,7 +26,6 @@
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/error.hpp"
#include "asio/io_context.hpp"

#include "asio/detail/push_options.hpp"

Expand Down Expand Up @@ -105,32 +104,17 @@ class buffered_read_stream
return next_layer_.lowest_layer().get_executor();
}

#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
asio::io_context& get_io_context()
{
return next_layer_.get_io_context();
}

/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
asio::io_context& get_io_service()
{
return next_layer_.get_io_service();
}
#endif // !defined(ASIO_NO_DEPRECATED)

/// Close the stream.
void close()
{
next_layer_.close();
}

/// Close the stream.
asio::error_code close(asio::error_code& ec)
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
{
return next_layer_.close(ec);
next_layer_.close(ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}

/// Write the given data to the stream. Returns the number of bytes written.
Expand Down Expand Up @@ -158,14 +142,8 @@ class buffered_read_stream
async_write_some(const ConstBufferSequence& buffers,
ASIO_MOVE_ARG(WriteHandler) handler)
{
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);

next_layer_.async_write_some(buffers,
ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(WriteHandler,
void (asio::error_code, std::size_t)))(init.handler));

return init.result.get();
return next_layer_.async_write_some(buffers,
ASIO_MOVE_CAST(WriteHandler)(handler));
}

/// Fill the buffer with some data. Returns the number of bytes placed in the
Expand Down
2 changes: 1 addition & 1 deletion link/asio/buffered_read_stream_fwd.hpp
Expand Up @@ -2,7 +2,7 @@
// buffered_read_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
24 changes: 4 additions & 20 deletions link/asio/buffered_stream.hpp
Expand Up @@ -2,7 +2,7 @@
// buffered_stream.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand All @@ -23,7 +23,6 @@
#include "asio/buffered_stream_fwd.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/error.hpp"
#include "asio/io_context.hpp"

#include "asio/detail/push_options.hpp"

Expand Down Expand Up @@ -96,32 +95,17 @@ class buffered_stream
return stream_impl_.lowest_layer().get_executor();
}

#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
asio::io_context& get_io_context()
{
return stream_impl_.get_io_context();
}

/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
asio::io_context& get_io_service()
{
return stream_impl_.get_io_service();
}
#endif // !defined(ASIO_NO_DEPRECATED)

/// Close the stream.
void close()
{
stream_impl_.close();
}

/// Close the stream.
asio::error_code close(asio::error_code& ec)
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
{
return stream_impl_.close(ec);
stream_impl_.close(ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}

/// Flush all data from the buffer to the next layer. Returns the number of
Expand Down
2 changes: 1 addition & 1 deletion link/asio/buffered_stream_fwd.hpp
Expand Up @@ -2,7 +2,7 @@
// buffered_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
34 changes: 6 additions & 28 deletions link/asio/buffered_write_stream.hpp
Expand Up @@ -2,7 +2,7 @@
// buffered_write_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand All @@ -25,7 +25,6 @@
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/error.hpp"
#include "asio/io_context.hpp"
#include "asio/write.hpp"

#include "asio/detail/push_options.hpp"
Expand Down Expand Up @@ -105,32 +104,17 @@ class buffered_write_stream
return next_layer_.lowest_layer().get_executor();
}

#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
asio::io_context& get_io_context()
{
return next_layer_.get_io_context();
}

/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
asio::io_context& get_io_service()
{
return next_layer_.get_io_service();
}
#endif // !defined(ASIO_NO_DEPRECATED)

/// Close the stream.
void close()
{
next_layer_.close();
}

/// Close the stream.
asio::error_code close(asio::error_code& ec)
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
{
return next_layer_.close(ec);
next_layer_.close(ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}

/// Flush all data from the buffer to the next layer. Returns the number of
Expand Down Expand Up @@ -193,14 +177,8 @@ class buffered_write_stream
async_read_some(const MutableBufferSequence& buffers,
ASIO_MOVE_ARG(ReadHandler) handler)
{
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);

next_layer_.async_read_some(buffers,
ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(ReadHandler,
void (asio::error_code, std::size_t)))(init.handler));

return init.result.get();
return next_layer_.async_read_some(buffers,
ASIO_MOVE_CAST(ReadHandler)(handler));
}

/// Peek at the incoming data on the stream. Returns the number of bytes read.
Expand Down
2 changes: 1 addition & 1 deletion link/asio/buffered_write_stream_fwd.hpp
Expand Up @@ -2,7 +2,7 @@
// buffered_write_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
64 changes: 52 additions & 12 deletions link/asio/buffers_iterator.hpp
Expand Up @@ -2,7 +2,7 @@
// buffers_iterator.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down Expand Up @@ -65,7 +65,44 @@ namespace detail
typedef buffers_iterator_types_helper<is_mutable> helper;
typedef typename helper::buffer_type buffer_type;
typedef typename helper::template byte_type<ByteType>::type byte_type;
typedef typename BufferSequence::const_iterator const_iterator;
};

template <typename ByteType>
struct buffers_iterator_types<mutable_buffer, ByteType>
{
typedef mutable_buffer buffer_type;
typedef ByteType byte_type;
typedef const mutable_buffer* const_iterator;
};

template <typename ByteType>
struct buffers_iterator_types<const_buffer, ByteType>
{
typedef const_buffer buffer_type;
typedef typename add_const<ByteType>::type byte_type;
typedef const const_buffer* const_iterator;
};

#if !defined(ASIO_NO_DEPRECATED)

template <typename ByteType>
struct buffers_iterator_types<mutable_buffers_1, ByteType>
{
typedef mutable_buffer buffer_type;
typedef ByteType byte_type;
typedef const mutable_buffer* const_iterator;
};

template <typename ByteType>
struct buffers_iterator_types<const_buffers_1, ByteType>
{
typedef const_buffer buffer_type;
typedef typename add_const<ByteType>::type byte_type;
typedef const const_buffer* const_iterator;
};

#endif // !defined(ASIO_NO_DEPRECATED)
}

/// A random access iterator over the bytes in a buffer sequence.
Expand All @@ -76,6 +113,9 @@ class buffers_iterator
typedef typename detail::buffers_iterator_types<
BufferSequence, ByteType>::buffer_type buffer_type;

typedef typename detail::buffers_iterator_types<BufferSequence,
ByteType>::const_iterator buffer_sequence_iterator_type;

public:
/// The type used for the distance between two iterators.
typedef std::ptrdiff_t difference_type;
Expand Down Expand Up @@ -130,9 +170,9 @@ class buffers_iterator
#endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
{
buffers_iterator new_iter;
new_iter.begin_ = buffers.begin();
new_iter.current_ = buffers.begin();
new_iter.end_ = buffers.end();
new_iter.begin_ = asio::buffer_sequence_begin(buffers);
new_iter.current_ = asio::buffer_sequence_begin(buffers);
new_iter.end_ = asio::buffer_sequence_end(buffers);
while (new_iter.current_ != new_iter.end_)
{
new_iter.current_buffer_ = *new_iter.current_;
Expand All @@ -150,9 +190,9 @@ class buffers_iterator
#endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
{
buffers_iterator new_iter;
new_iter.begin_ = buffers.begin();
new_iter.current_ = buffers.begin();
new_iter.end_ = buffers.end();
new_iter.begin_ = asio::buffer_sequence_begin(buffers);
new_iter.current_ = asio::buffer_sequence_begin(buffers);
new_iter.end_ = asio::buffer_sequence_end(buffers);
while (new_iter.current_ != new_iter.end_)
{
buffer_type buffer = *new_iter.current_;
Expand Down Expand Up @@ -347,7 +387,7 @@ class buffers_iterator
}

// Find the previous non-empty buffer.
typename BufferSequence::const_iterator iter = current_;
buffer_sequence_iterator_type iter = current_;
while (iter != begin_)
{
--iter;
Expand Down Expand Up @@ -426,7 +466,7 @@ class buffers_iterator
}

// Find the previous non-empty buffer.
typename BufferSequence::const_iterator iter = current_;
buffer_sequence_iterator_type iter = current_;
while (iter != begin_)
{
--iter;
Expand All @@ -452,9 +492,9 @@ class buffers_iterator

buffer_type current_buffer_;
std::size_t current_buffer_position_;
typename BufferSequence::const_iterator begin_;
typename BufferSequence::const_iterator current_;
typename BufferSequence::const_iterator end_;
buffer_sequence_iterator_type begin_;
buffer_sequence_iterator_type current_;
buffer_sequence_iterator_type end_;
std::size_t position_;
};

Expand Down
88 changes: 88 additions & 0 deletions link/asio/co_spawn.hpp
@@ -0,0 +1,88 @@
//
// co_spawn.hpp
// ~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 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_CO_SPAWN_HPP
#define ASIO_CO_SPAWN_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include "asio/detail/config.hpp"

#if defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)

#include "asio/awaitable.hpp"
#include "asio/execution_context.hpp"
#include "asio/is_executor.hpp"

#include "asio/detail/push_options.hpp"

namespace asio {
namespace detail {

template <typename T>
struct awaitable_signature;

template <typename T, typename Executor>
struct awaitable_signature<awaitable<T, Executor>>
{
typedef void type(std::exception_ptr, T);
};

template <typename Executor>
struct awaitable_signature<awaitable<void, Executor>>
{
typedef void type(std::exception_ptr);
};

} // namespace detail

/// Spawn a new thread of execution.
/**
* The entry point function object @c f must have the signature:
*
* @code awaitable<void, E> f(); @endcode
*
* where @c E is convertible from @c Executor.
*/
template <typename Executor, typename F, typename CompletionToken>
ASIO_INITFN_RESULT_TYPE(CompletionToken,
typename detail::awaitable_signature<typename result_of<F()>::type>::type)
co_spawn(const Executor& ex, F&& f, CompletionToken&& token,
typename enable_if<
is_executor<Executor>::value
>::type* = 0);

/// Spawn a new thread of execution.
/**
* The entry point function object @c f must have the signature:
*
* @code awaitable<void, E> f(); @endcode
*
* where @c E is convertible from @c ExecutionContext::executor_type.
*/
template <typename ExecutionContext, typename F, typename CompletionToken>
ASIO_INITFN_RESULT_TYPE(CompletionToken,
typename detail::awaitable_signature<typename result_of<F()>::type>::type)
co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0);

} // namespace asio

#include "asio/detail/pop_options.hpp"

#include "asio/impl/co_spawn.hpp"

#endif // defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)

#endif // ASIO_CO_SPAWN_HPP
2 changes: 1 addition & 1 deletion link/asio/completion_condition.hpp
Expand Up @@ -2,7 +2,7 @@
// completion_condition.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
136 changes: 136 additions & 0 deletions link/asio/compose.hpp
@@ -0,0 +1,136 @@
//
// compose.hpp
// ~~~~~~~~~~~
//
// Copyright (c) 2003-2019 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_COMPOSE_HPP
#define ASIO_COMPOSE_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include "asio/detail/config.hpp"
#include "asio/async_result.hpp"

#include "asio/detail/push_options.hpp"

namespace asio {

#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \
|| defined(GENERATING_DOCUMENTATION)

/// Launch an asynchronous operation with a stateful implementation.
/**
* The async_compose function simplifies the implementation of composed
* asynchronous operations automatically wrapping a stateful function object
* with a conforming intermediate completion handler.
*
* @param implementation A function object that contains the implementation of
* the composed asynchronous operation. The first argument to the function
* object is a non-const reference to the enclosing intermediate completion
* handler. The remaining arguments are any arguments that originate from the
* completion handlers of any asynchronous operations performed by the
* implementation.
* @param token The completion token.
*
* @param io_objects_or_executors Zero or more I/O objects or I/O executors for
* which outstanding work must be maintained.
*
* @par Example:
*
* @code struct async_echo_implementation
* {
* tcp::socket& socket_;
* asio::mutable_buffer buffer_;
* enum { starting, reading, writing } state_;
*
* template <typename Self>
* void operator()(Self& self,
* asio::error_code error = {},
* std::size_t n = 0)
* {
* switch (state_)
* {
* case starting:
* state_ = reading;
* socket_.async_read_some(
* buffer_, std::move(self));
* break;
* case reading:
* if (error)
* {
* self.complete(error, 0);
* }
* else
* {
* state_ = writing;
* asio::async_write(socket_, buffer_,
* asio::transfer_exactly(n),
* std::move(self));
* }
* break;
* case writing:
* self.complete(error, n);
* break;
* }
* }
* };
*
* template <typename CompletionToken>
* auto async_echo(tcp::socket& socket,
* asio::mutable_buffer buffer,
* CompletionToken&& token) ->
* typename asio::async_result<
* typename std::decay<CompletionToken>::type,
* void(asio::error_code, std::size_t)>::return_type
* {
* return asio::async_compose<CompletionToken,
* void(asio::error_code, std::size_t)>(
* async_echo_implementation{socket, buffer,
* async_echo_implementation::starting},
* token, socket);
* } @endcode
*/
template <typename CompletionToken, typename Signature,
typename Implementation, typename... IoObjectsOrExecutors>
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
async_compose(ASIO_MOVE_ARG(Implementation) implementation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors);

#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
// || defined(GENERATING_DOCUMENTATION)

template <typename CompletionToken, typename Signature, typename Implementation>
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
async_compose(ASIO_MOVE_ARG(Implementation) implementation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token);

#define ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \
template <typename CompletionToken, typename Signature, \
typename Implementation, ASIO_VARIADIC_TPARAMS(n)> \
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) \
async_compose(ASIO_MOVE_ARG(Implementation) implementation, \
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
ASIO_VARIADIC_MOVE_PARAMS(n));
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_COMPOSE_DEF)
#undef ASIO_PRIVATE_ASYNC_COMPOSE_DEF

#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
// || defined(GENERATING_DOCUMENTATION)

} // namespace asio

#include "asio/detail/pop_options.hpp"

#include "asio/impl/compose.hpp"

#endif // ASIO_COMPOSE_HPP
192 changes: 96 additions & 96 deletions link/asio/connect.hpp

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions link/asio/coroutine.hpp
Expand Up @@ -2,7 +2,7 @@
// coroutine.hpp
// ~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down Expand Up @@ -205,7 +205,7 @@ class coroutine_ref;
* {
* do
* {
* socket_.reset(new tcp::socket(io_context_));
* socket_.reset(new tcp::socket(my_context_));
* yield acceptor->async_accept(*socket_, *this);
* fork server(*this)();
* } while (is_parent());
Expand All @@ -227,7 +227,7 @@ class coroutine_ref;
* Note that @c fork doesn't do the actual forking by itself. It is the
* application's responsibility to create a clone of the coroutine and call it.
* The clone can be called immediately, as above, or scheduled for delayed
* execution using something like io_context::post().
* execution using something like asio::post().
*
* @par Alternate macro names
*
Expand Down Expand Up @@ -289,7 +289,7 @@ class coroutine_ref
bail_out_of_coroutine: \
break; \
} \
else case 0:
else /* fall-through */ case 0:

#define ASIO_CORO_YIELD_IMPL(n) \
for (_coro_value = (n);;) \
Expand All @@ -301,12 +301,12 @@ class coroutine_ref
else \
switch (_coro_value ? 0 : 1) \
for (;;) \
case -1: if (_coro_value) \
/* fall-through */ case -1: if (_coro_value) \
goto terminate_coroutine; \
else for (;;) \
case 1: if (_coro_value) \
/* fall-through */ case 1: if (_coro_value) \
goto bail_out_of_coroutine; \
else case 0:
else /* fall-through */ case 0:

#define ASIO_CORO_FORK_IMPL(n) \
for (_coro_value = -(n);; _coro_value = (n)) \
Expand Down
438 changes: 0 additions & 438 deletions link/asio/datagram_socket_service.hpp

This file was deleted.

2 changes: 1 addition & 1 deletion link/asio/deadline_timer.hpp
Expand Up @@ -2,7 +2,7 @@
// deadline_timer.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
170 changes: 0 additions & 170 deletions link/asio/deadline_timer_service.hpp

This file was deleted.

12 changes: 11 additions & 1 deletion link/asio/defer.hpp
Expand Up @@ -2,7 +2,7 @@
// defer.hpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down Expand Up @@ -31,6 +31,11 @@ namespace asio {
* executor. The function object is queued for execution, and is never called
* from the current thread prior to returning from <tt>defer()</tt>.
*
* The use of @c defer(), rather than @ref post(), indicates the caller's
* preference that the executor defer the queueing of the function object. This
* may allow the executor to optimise queueing for cases when the function
* object represents a continuation of the current call context.
*
* This function has the following effects:
*
* @li Constructs a function object handler of type @c Handler, initialized
Expand Down Expand Up @@ -59,6 +64,11 @@ ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
* The function object is queued for execution, and is never called from the
* current thread prior to returning from <tt>defer()</tt>.
*
* The use of @c defer(), rather than @ref post(), indicates the caller's
* preference that the executor defer the queueing of the function object. This
* may allow the executor to optimise queueing for cases when the function
* object represents a continuation of the current call context.
*
* This function has the following effects:
*
* @li Constructs a function object handler of type @c Handler, initialized
Expand Down
62 changes: 62 additions & 0 deletions link/asio/detached.hpp
@@ -0,0 +1,62 @@
//
// detached.hpp
// ~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 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_DETACHED_HPP
#define ASIO_DETACHED_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include "asio/detail/config.hpp"
#include <memory>

#include "asio/detail/push_options.hpp"

namespace asio {

/// Class used to specify that an asynchronous operation is detached.
/**
* The detached_t class is used to indicate that an asynchronous operation is
* detached. That is, there is no completion handler waiting for the
* operation's result. A detached_t object may be passed as a handler to an
* asynchronous operation, typically using the special value
* @c asio::detached. For example:
* @code my_socket.async_send(my_buffer, asio::detached);
* @endcode
*/
class detached_t
{
public:
/// Constructor.
ASIO_CONSTEXPR detached_t()
{
}
};

/// A special value, similar to std::nothrow.
/**
* See the documentation for asio::detached_t for a usage example.
*/
#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
constexpr detached_t detached;
#elif defined(ASIO_MSVC)
__declspec(selectany) detached_t detached;
#endif

} // namespace asio

#include "asio/detail/pop_options.hpp"

#include "asio/impl/detached.hpp"

#endif // ASIO_DETACHED_HPP
2 changes: 1 addition & 1 deletion link/asio/detail/array.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/array.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
2 changes: 1 addition & 1 deletion link/asio/detail/array_fwd.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/array_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
2 changes: 1 addition & 1 deletion link/asio/detail/assert.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/assert.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
2 changes: 1 addition & 1 deletion link/asio/detail/atomic_count.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/atomic_count.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
7 changes: 4 additions & 3 deletions link/asio/detail/base_from_completion_cond.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/base_from_completion_cond.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand All @@ -27,8 +27,9 @@ template <typename CompletionCondition>
class base_from_completion_cond
{
protected:
explicit base_from_completion_cond(CompletionCondition completion_condition)
: completion_condition_(completion_condition)
explicit base_from_completion_cond(CompletionCondition& completion_condition)
: completion_condition_(
ASIO_MOVE_CAST(CompletionCondition)(completion_condition))
{
}

Expand Down
359 changes: 358 additions & 1 deletion link/asio/detail/bind_handler.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/bind_handler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down Expand Up @@ -223,6 +223,363 @@ inline binder2<typename decay<Handler>::type, Arg1, Arg2> bind_handler(
ASIO_MOVE_CAST(Handler)(handler), arg1, arg2);
}

template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
class binder3
{
public:
template <typename T>
binder3(int, ASIO_MOVE_ARG(T) handler, const Arg1& arg1,
const Arg2& arg2, const Arg3& arg3)
: handler_(ASIO_MOVE_CAST(T)(handler)),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3)
{
}

binder3(Handler& handler, const Arg1& arg1,
const Arg2& arg2, const Arg3& arg3)
: handler_(ASIO_MOVE_CAST(Handler)(handler)),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3)
{
}

#if defined(ASIO_HAS_MOVE)
binder3(const binder3& other)
: handler_(other.handler_),
arg1_(other.arg1_),
arg2_(other.arg2_),
arg3_(other.arg3_)
{
}

binder3(binder3&& other)
: handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),
arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)),
arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_)),
arg3_(ASIO_MOVE_CAST(Arg3)(other.arg3_))
{
}
#endif // defined(ASIO_HAS_MOVE)

void operator()()
{
handler_(static_cast<const Arg1&>(arg1_),
static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_));
}

void operator()() const
{
handler_(arg1_, arg2_, arg3_);
}

//private:
Handler handler_;
Arg1 arg1_;
Arg2 arg2_;
Arg3 arg3_;
};

template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
inline void* asio_handler_allocate(std::size_t size,
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}

template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}

template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
inline bool asio_handler_is_continuation(
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
{
return asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}

template <typename Function, typename Handler,
typename Arg1, typename Arg2, typename Arg3>
inline void asio_handler_invoke(Function& function,
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}

template <typename Function, typename Handler,
typename Arg1, typename Arg2, typename Arg3>
inline void asio_handler_invoke(const Function& function,
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}

template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
inline binder3<typename decay<Handler>::type, Arg1, Arg2, Arg3> bind_handler(
ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1, const Arg2& arg2,
const Arg3& arg3)
{
return binder3<typename decay<Handler>::type, Arg1, Arg2, Arg3>(0,
ASIO_MOVE_CAST(Handler)(handler), arg1, arg2, arg3);
}

template <typename Handler, typename Arg1,
typename Arg2, typename Arg3, typename Arg4>
class binder4
{
public:
template <typename T>
binder4(int, ASIO_MOVE_ARG(T) handler, const Arg1& arg1,
const Arg2& arg2, const Arg3& arg3, const Arg4& arg4)
: handler_(ASIO_MOVE_CAST(T)(handler)),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3),
arg4_(arg4)
{
}

binder4(Handler& handler, const Arg1& arg1,
const Arg2& arg2, const Arg3& arg3, const Arg4& arg4)
: handler_(ASIO_MOVE_CAST(Handler)(handler)),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3),
arg4_(arg4)
{
}

#if defined(ASIO_HAS_MOVE)
binder4(const binder4& other)
: handler_(other.handler_),
arg1_(other.arg1_),
arg2_(other.arg2_),
arg3_(other.arg3_),
arg4_(other.arg4_)
{
}

binder4(binder4&& other)
: handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),
arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)),
arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_)),
arg3_(ASIO_MOVE_CAST(Arg3)(other.arg3_)),
arg4_(ASIO_MOVE_CAST(Arg4)(other.arg4_))
{
}
#endif // defined(ASIO_HAS_MOVE)

void operator()()
{
handler_(static_cast<const Arg1&>(arg1_),
static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),
static_cast<const Arg4&>(arg4_));
}

void operator()() const
{
handler_(arg1_, arg2_, arg3_, arg4_);
}

//private:
Handler handler_;
Arg1 arg1_;
Arg2 arg2_;
Arg3 arg3_;
Arg4 arg4_;
};

template <typename Handler, typename Arg1,
typename Arg2, typename Arg3, typename Arg4>
inline void* asio_handler_allocate(std::size_t size,
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}

template <typename Handler, typename Arg1,
typename Arg2, typename Arg3, typename Arg4>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}

template <typename Handler, typename Arg1,
typename Arg2, typename Arg3, typename Arg4>
inline bool asio_handler_is_continuation(
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
return asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}

template <typename Function, typename Handler, typename Arg1,
typename Arg2, typename Arg3, typename Arg4>
inline void asio_handler_invoke(Function& function,
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}

template <typename Function, typename Handler, typename Arg1,
typename Arg2, typename Arg3, typename Arg4>
inline void asio_handler_invoke(const Function& function,
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}

template <typename Handler, typename Arg1,
typename Arg2, typename Arg3, typename Arg4>
inline binder4<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4>
bind_handler(ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1,
const Arg2& arg2, const Arg3& arg3, const Arg4& arg4)
{
return binder4<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4>(0,
ASIO_MOVE_CAST(Handler)(handler), arg1, arg2, arg3, arg4);
}

template <typename Handler, typename Arg1, typename Arg2,
typename Arg3, typename Arg4, typename Arg5>
class binder5
{
public:
template <typename T>
binder5(int, ASIO_MOVE_ARG(T) handler, const Arg1& arg1,
const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
: handler_(ASIO_MOVE_CAST(T)(handler)),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3),
arg4_(arg4),
arg5_(arg5)
{
}

binder5(Handler& handler, const Arg1& arg1, const Arg2& arg2,
const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
: handler_(ASIO_MOVE_CAST(Handler)(handler)),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3),
arg4_(arg4),
arg5_(arg5)
{
}

#if defined(ASIO_HAS_MOVE)
binder5(const binder5& other)
: handler_(other.handler_),
arg1_(other.arg1_),
arg2_(other.arg2_),
arg3_(other.arg3_),
arg4_(other.arg4_),
arg5_(other.arg5_)
{
}

binder5(binder5&& other)
: handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),
arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)),
arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_)),
arg3_(ASIO_MOVE_CAST(Arg3)(other.arg3_)),
arg4_(ASIO_MOVE_CAST(Arg4)(other.arg4_)),
arg5_(ASIO_MOVE_CAST(Arg5)(other.arg5_))
{
}
#endif // defined(ASIO_HAS_MOVE)

void operator()()
{
handler_(static_cast<const Arg1&>(arg1_),
static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),
static_cast<const Arg4&>(arg4_), static_cast<const Arg5&>(arg5_));
}

void operator()() const
{
handler_(arg1_, arg2_, arg3_, arg4_, arg5_);
}

//private:
Handler handler_;
Arg1 arg1_;
Arg2 arg2_;
Arg3 arg3_;
Arg4 arg4_;
Arg5 arg5_;
};

template <typename Handler, typename Arg1, typename Arg2,
typename Arg3, typename Arg4, typename Arg5>
inline void* asio_handler_allocate(std::size_t size,
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}

template <typename Handler, typename Arg1, typename Arg2,
typename Arg3, typename Arg4, typename Arg5>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}

template <typename Handler, typename Arg1, typename Arg2,
typename Arg3, typename Arg4, typename Arg5>
inline bool asio_handler_is_continuation(
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
return asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}

template <typename Function, typename Handler, typename Arg1,
typename Arg2, typename Arg3, typename Arg4, typename Arg5>
inline void asio_handler_invoke(Function& function,
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}

template <typename Function, typename Handler, typename Arg1,
typename Arg2, typename Arg3, typename Arg4, typename Arg5>
inline void asio_handler_invoke(const Function& function,
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}

template <typename Handler, typename Arg1, typename Arg2,
typename Arg3, typename Arg4, typename Arg5>
inline binder5<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4, Arg5>
bind_handler(ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1,
const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
{
return binder5<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4, Arg5>(0,
ASIO_MOVE_CAST(Handler)(handler), arg1, arg2, arg3, arg4, arg5);
}

#if defined(ASIO_HAS_MOVE)

template <typename Handler, typename Arg1>
Expand Down
2 changes: 1 addition & 1 deletion link/asio/detail/buffer_resize_guard.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/buffer_resize_guard.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
204 changes: 185 additions & 19 deletions link/asio/detail/buffer_sequence_adapter.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/buffer_sequence_adapter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand All @@ -27,11 +27,12 @@ namespace detail {

class buffer_sequence_adapter_base
{
protected:
#if defined(ASIO_WINDOWS_RUNTIME)
public:
// The maximum number of buffers to support in a single operation.
enum { max_buffers = 1 };

protected:
typedef Windows::Storage::Streams::IBuffer^ native_buffer_type;

ASIO_DECL static void init_native_buffer(
Expand All @@ -42,9 +43,11 @@ class buffer_sequence_adapter_base
native_buffer_type& buf,
const asio::const_buffer& buffer);
#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)
public:
// The maximum number of buffers to support in a single operation.
enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };

protected:
typedef WSABUF native_buffer_type;

static void init_native_buffer(WSABUF& buf,
Expand All @@ -61,9 +64,11 @@ class buffer_sequence_adapter_base
buf.len = static_cast<ULONG>(buffer.size());
}
#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
public:
// The maximum number of buffers to support in a single operation.
enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };

protected:
typedef iovec native_buffer_type;

static void init_iov_base(void*& base, void* addr)
Expand Down Expand Up @@ -102,14 +107,9 @@ class buffer_sequence_adapter
explicit buffer_sequence_adapter(const Buffers& buffer_sequence)
: count_(0), total_buffer_size_(0)
{
typename Buffers::const_iterator iter = buffer_sequence.begin();
typename Buffers::const_iterator end = buffer_sequence.end();
for (; iter != end && count_ < max_buffers; ++iter, ++count_)
{
Buffer buffer(*iter);
init_native_buffer(buffers_[count_], buffer);
total_buffer_size_ += buffer.size();
}
buffer_sequence_adapter::init(
asio::buffer_sequence_begin(buffer_sequence),
asio::buffer_sequence_end(buffer_sequence));
}

native_buffer_type* buffers()
Expand All @@ -122,37 +122,76 @@ class buffer_sequence_adapter
return count_;
}

std::size_t total_size() const
{
return total_buffer_size_;
}

bool all_empty() const
{
return total_buffer_size_ == 0;
}

static bool all_empty(const Buffers& buffer_sequence)
{
typename Buffers::const_iterator iter = buffer_sequence.begin();
typename Buffers::const_iterator end = buffer_sequence.end();
return buffer_sequence_adapter::all_empty(
asio::buffer_sequence_begin(buffer_sequence),
asio::buffer_sequence_end(buffer_sequence));
}

static void validate(const Buffers& buffer_sequence)
{
buffer_sequence_adapter::validate(
asio::buffer_sequence_begin(buffer_sequence),
asio::buffer_sequence_end(buffer_sequence));
}

static Buffer first(const Buffers& buffer_sequence)
{
return buffer_sequence_adapter::first(
asio::buffer_sequence_begin(buffer_sequence),
asio::buffer_sequence_end(buffer_sequence));
}

private:
template <typename Iterator>
void init(Iterator begin, Iterator end)
{
Iterator iter = begin;
for (; iter != end && count_ < max_buffers; ++iter, ++count_)
{
Buffer buffer(*iter);
init_native_buffer(buffers_[count_], buffer);
total_buffer_size_ += buffer.size();
}
}

template <typename Iterator>
static bool all_empty(Iterator begin, Iterator end)
{
Iterator iter = begin;
std::size_t i = 0;
for (; iter != end && i < max_buffers; ++iter, ++i)
if (Buffer(*iter).size() > 0)
return false;
return true;
}

static void validate(const Buffers& buffer_sequence)
template <typename Iterator>
static void validate(Iterator begin, Iterator end)
{
typename Buffers::const_iterator iter = buffer_sequence.begin();
typename Buffers::const_iterator end = buffer_sequence.end();
Iterator iter = begin;
for (; iter != end; ++iter)
{
Buffer buffer(*iter);
buffer.data();
}
}

static Buffer first(const Buffers& buffer_sequence)
template <typename Iterator>
static Buffer first(Iterator begin, Iterator end)
{
typename Buffers::const_iterator iter = buffer_sequence.begin();
typename Buffers::const_iterator end = buffer_sequence.end();
Iterator iter = begin;
for (; iter != end; ++iter)
{
Buffer buffer(*iter);
Expand All @@ -162,12 +201,117 @@ class buffer_sequence_adapter
return Buffer();
}

private:
native_buffer_type buffers_[max_buffers];
std::size_t count_;
std::size_t total_buffer_size_;
};

template <typename Buffer>
class buffer_sequence_adapter<Buffer, asio::mutable_buffer>
: buffer_sequence_adapter_base
{
public:
explicit buffer_sequence_adapter(
const asio::mutable_buffer& buffer_sequence)
{
init_native_buffer(buffer_, Buffer(buffer_sequence));
total_buffer_size_ = buffer_sequence.size();
}

native_buffer_type* buffers()
{
return &buffer_;
}

std::size_t count() const
{
return 1;
}

std::size_t total_size() const
{
return total_buffer_size_;
}

bool all_empty() const
{
return total_buffer_size_ == 0;
}

static bool all_empty(const asio::mutable_buffer& buffer_sequence)
{
return buffer_sequence.size() == 0;
}

static void validate(const asio::mutable_buffer& buffer_sequence)
{
buffer_sequence.data();
}

static Buffer first(const asio::mutable_buffer& buffer_sequence)
{
return Buffer(buffer_sequence);
}

private:
native_buffer_type buffer_;
std::size_t total_buffer_size_;
};

template <typename Buffer>
class buffer_sequence_adapter<Buffer, asio::const_buffer>
: buffer_sequence_adapter_base
{
public:
explicit buffer_sequence_adapter(
const asio::const_buffer& buffer_sequence)
{
init_native_buffer(buffer_, Buffer(buffer_sequence));
total_buffer_size_ = buffer_sequence.size();
}

native_buffer_type* buffers()
{
return &buffer_;
}

std::size_t count() const
{
return 1;
}

std::size_t total_size() const
{
return total_buffer_size_;
}

bool all_empty() const
{
return total_buffer_size_ == 0;
}

static bool all_empty(const asio::const_buffer& buffer_sequence)
{
return buffer_sequence.size() == 0;
}

static void validate(const asio::const_buffer& buffer_sequence)
{
buffer_sequence.data();
}

static Buffer first(const asio::const_buffer& buffer_sequence)
{
return Buffer(buffer_sequence);
}

private:
native_buffer_type buffer_;
std::size_t total_buffer_size_;
};

#if !defined(ASIO_NO_DEPRECATED)

template <typename Buffer>
class buffer_sequence_adapter<Buffer, asio::mutable_buffers_1>
: buffer_sequence_adapter_base
Expand All @@ -190,6 +334,11 @@ class buffer_sequence_adapter<Buffer, asio::mutable_buffers_1>
return 1;
}

std::size_t total_size() const
{
return total_buffer_size_;
}

bool all_empty() const
{
return total_buffer_size_ == 0;
Expand Down Expand Up @@ -237,6 +386,11 @@ class buffer_sequence_adapter<Buffer, asio::const_buffers_1>
return 1;
}

std::size_t total_size() const
{
return total_buffer_size_;
}

bool all_empty() const
{
return total_buffer_size_ == 0;
Expand All @@ -262,6 +416,8 @@ class buffer_sequence_adapter<Buffer, asio::const_buffers_1>
std::size_t total_buffer_size_;
};

#endif // !defined(ASIO_NO_DEPRECATED)

template <typename Buffer, typename Elem>
class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> >
: buffer_sequence_adapter_base
Expand All @@ -285,6 +441,11 @@ class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> >
return 2;
}

std::size_t total_size() const
{
return total_buffer_size_;
}

bool all_empty() const
{
return total_buffer_size_ == 0;
Expand Down Expand Up @@ -337,6 +498,11 @@ class buffer_sequence_adapter<Buffer, std::array<Elem, 2> >
return 2;
}

std::size_t total_size() const
{
return total_buffer_size_;
}

bool all_empty() const
{
return total_buffer_size_ == 0;
Expand Down
2 changes: 1 addition & 1 deletion link/asio/detail/buffered_stream_storage.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/buffered_stream_storage.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
2 changes: 1 addition & 1 deletion link/asio/detail/call_stack.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/call_stack.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
8 changes: 4 additions & 4 deletions link/asio/detail/chrono.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/chrono.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down Expand Up @@ -38,11 +38,11 @@ using std::chrono::minutes;
using std::chrono::hours;
using std::chrono::time_point_cast;
#if defined(ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)
typedef std::chrono::monotonic_clock system_clock;
typedef std::chrono::monotonic_clock steady_clock;
#else // defined(ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)
using std::chrono::system_clock;
#endif // defined(ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)
using std::chrono::steady_clock;
#endif // defined(ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)
using std::chrono::system_clock;
using std::chrono::high_resolution_clock;
#elif defined(ASIO_HAS_BOOST_CHRONO)
using boost::chrono::duration;
Expand Down
2 changes: 1 addition & 1 deletion link/asio/detail/chrono_time_traits.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/chrono_time_traits.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
2 changes: 1 addition & 1 deletion link/asio/detail/completion_handler.hpp
Expand Up @@ -2,7 +2,7 @@
// detail/completion_handler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 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)
Expand Down
94 changes: 94 additions & 0 deletions link/asio/detail/concurrency_hint.hpp
@@ -0,0 +1,94 @@
//
// detail/concurrency_hint.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 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_DETAIL_CONCURRENCY_HINT_HPP
#define ASIO_DETAIL_CONCURRENCY_HINT_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include "asio/detail/config.hpp"
#include "asio/detail/noncopyable.hpp"

// The concurrency hint ID and mask are used to identify when a "well-known"
// concurrency hint value has been passed to the io_context.
#define ASIO_CONCURRENCY_HINT_ID 0xA5100000u
#define ASIO_CONCURRENCY_HINT_ID_MASK 0xFFFF0000u

// If set, this bit indicates that the scheduler should perform locking.
#define ASIO_CONCURRENCY_HINT_LOCKING_SCHEDULER 0x1u

// If set, this bit indicates that the reactor should perform locking when
// managing descriptor registrations.
#define ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_REGISTRATION 0x2u

// If set, this bit indicates that the reactor should perform locking for I/O.
#define ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_IO 0x4u

// Helper macro to determine if we have a special concurrency hint.
#define ASIO_CONCURRENCY_HINT_IS_SPECIAL(hint) \
((static_cast<unsigned>(hint) \
& ASIO_CONCURRENCY_HINT_ID_MASK) \
== ASIO_CONCURRENCY_HINT_ID)

// Helper macro to determine if locking is enabled for a given facility.
#define ASIO_CONCURRENCY_HINT_IS_LOCKING(facility, hint) \
(((static_cast<unsigned>(hint) \
& (ASIO_CONCURRENCY_HINT_ID_MASK \
| ASIO_CONCURRENCY_HINT_LOCKING_ ## facility)) \
^ ASIO_CONCURRENCY_HINT_ID) != 0)

// This special concurrency hint disables locking in both the scheduler and
// reactor I/O. This hint has the following restrictions:
//
// - Care must be taken to ensure that all operations on the io_context and any
// of its associated I/O objects (such as sockets and timers) occur in only
// one thread at a time.
//
// - Asynchronous resolve operations fail with operation_not_supported.
//
// - If a signal_set is used with the io_context, signal_set objects cannot be
// used with any other io_context in the program.
#define ASIO_CONCURRENCY_HINT_UNSAFE \
static_cast<int>(ASIO_CONCURRENCY_HINT_ID)

// This special concurrency hint disables locking in the reactor I/O. This hint
// has the following restrictions:
//
// - Care must be taken to ensure that run functions on the io_context, and all
// operations on the io_context's associated I/O objects (such as sockets and
// timers), occur in only one thread at a time.
#define ASIO_CONCURRENCY_HINT_UNSAFE_IO \
static_cast<int>(ASIO_CONCURRENCY_HINT_ID \
| ASIO_CONCURRENCY_HINT_LOCKING_SCHEDULER \
| ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_REGISTRATION)

// The special concurrency hint provides full thread safety.
#define ASIO_CONCURRENCY_HINT_SAFE \
static_cast<int>(ASIO_CONCURRENCY_HINT_ID \
| ASIO_CONCURRENCY_HINT_LOCKING_SCHEDULER \
| ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_REGISTRATION \
| ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_IO)

// This #define may be overridden at compile time to specify a program-wide
// default concurrency hint, used by the zero-argument io_context constructor.
#if !defined(ASIO_CONCURRENCY_HINT_DEFAULT)
# define ASIO_CONCURRENCY_HINT_DEFAULT -1
#endif // !defined(ASIO_CONCURRENCY_HINT_DEFAULT)

// This #define may be overridden at compile time to specify a program-wide
// concurrency hint, used by the one-argument io_context constructor when
// passed a value of 1.
#if !defined(ASIO_CONCURRENCY_HINT_1)
# define ASIO_CONCURRENCY_HINT_1 1
#endif // !defined(ASIO_CONCURRENCY_HINT_DEFAULT)

#endif // ASIO_DETAIL_CONCURRENCY_HINT_HPP
112 changes: 112 additions & 0 deletions link/asio/detail/conditionally_enabled_event.hpp
@@ -0,0 +1,112 @@
//
// detail/conditionally_enabled_event.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 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_DETAIL_CONDITIONALLY_ENABLED_EVENT_HPP
#define ASIO_DETAIL_CONDITIONALLY_ENABLED_EVENT_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include "asio/detail/config.hpp"
#include "asio/detail/conditionally_enabled_mutex.hpp"
#include "asio/detail/event.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/null_event.hpp"
#include "asio/detail/scoped_lock.hpp"

#include "asio/detail/push_options.hpp"

namespace asio {
namespace detail {

// Mutex adapter used to conditionally enable or disable locking.
class conditionally_enabled_event
: private noncopyable
{
public:
// Constructor.
conditionally_enabled_event()
{
}

// Destructor.
~conditionally_enabled_event()
{
}

// Signal the event. (Retained for backward compatibility.)
void signal(conditionally_enabled_mutex::scoped_lock& lock)
{
if (lock.mutex_.enabled_)
event_.signal(lock);
}

// Signal all waiters.
void signal_all(conditionally_enabled_mutex::scoped_lock& lock)
{
if (lock.mutex_.enabled_)
event_.signal_all(lock);
}

// Unlock the mutex and signal one waiter.
void unlock_and_signal_one(
conditionally_enabled_mutex::scoped_lock& lock)
{
if (lock.mutex_.enabled_)
event_.unlock_and_signal_one(lock);
}

// If there's a waiter, unlock the mutex and signal it.
bool maybe_unlock_and_signal_one(
conditionally_enabled_mutex::scoped_lock& lock)
{
if (lock.mutex_.enabled_)
return event_.maybe_unlock_and_signal_one(lock);
else
return false;
}

// Reset the event.
void clear(conditionally_enabled_mutex::scoped_lock& lock)
{
if (lock.mutex_.enabled_)
event_.clear(lock);
}

// Wait for the event to become signalled.
void wait(conditionally_enabled_mutex::scoped_lock& lock)
{
if (lock.mutex_.enabled_)
event_.wait(lock);
else
null_event().wait(lock);
}

// Timed wait for the event to become signalled.
bool wait_for_usec(
conditionally_enabled_mutex::scoped_lock& lock, long usec)
{
if (lock.mutex_.enabled_)
return event_.wait_for_usec(lock, usec);
else
return null_event().wait_for_usec(lock, usec);
}

private:
asio::detail::event event_;
};

} // namespace detail
} // namespace asio

#include "asio/detail/pop_options.hpp"

#endif // ASIO_DETAIL_CONDITIONALLY_ENABLED_EVENT_HPP