update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -0,0 +1,132 @@
//
// impl/any_completion_executor.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2023 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 BOOST_ASIO_IMPL_ANY_COMPLETION_EXECUTOR_IPP
#define BOOST_ASIO_IMPL_ANY_COMPLETION_EXECUTOR_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#if !defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
#include <boost/asio/any_completion_executor.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
any_completion_executor::any_completion_executor() BOOST_ASIO_NOEXCEPT
: base_type()
{
}
any_completion_executor::any_completion_executor(nullptr_t) BOOST_ASIO_NOEXCEPT
: base_type(nullptr_t())
{
}
any_completion_executor::any_completion_executor(
const any_completion_executor& e) BOOST_ASIO_NOEXCEPT
: base_type(static_cast<const base_type&>(e))
{
}
any_completion_executor::any_completion_executor(std::nothrow_t,
const any_completion_executor& e) BOOST_ASIO_NOEXCEPT
: base_type(static_cast<const base_type&>(e))
{
}
#if defined(BOOST_ASIO_HAS_MOVE)
any_completion_executor::any_completion_executor(
any_completion_executor&& e) BOOST_ASIO_NOEXCEPT
: base_type(static_cast<base_type&&>(e))
{
}
any_completion_executor::any_completion_executor(std::nothrow_t,
any_completion_executor&& e) BOOST_ASIO_NOEXCEPT
: base_type(static_cast<base_type&&>(e))
{
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
any_completion_executor& any_completion_executor::operator=(
const any_completion_executor& e) BOOST_ASIO_NOEXCEPT
{
base_type::operator=(static_cast<const base_type&>(e));
return *this;
}
#if defined(BOOST_ASIO_HAS_MOVE)
any_completion_executor& any_completion_executor::operator=(
any_completion_executor&& e) BOOST_ASIO_NOEXCEPT
{
base_type::operator=(static_cast<base_type&&>(e));
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
any_completion_executor& any_completion_executor::operator=(nullptr_t)
{
base_type::operator=(nullptr_t());
return *this;
}
any_completion_executor::~any_completion_executor()
{
}
void any_completion_executor::swap(
any_completion_executor& other) BOOST_ASIO_NOEXCEPT
{
static_cast<base_type&>(*this).swap(static_cast<base_type&>(other));
}
template <>
any_completion_executor any_completion_executor::prefer(
const execution::outstanding_work_t::tracked_t& p, int) const
{
return static_cast<const base_type&>(*this).prefer(p);
}
template <>
any_completion_executor any_completion_executor::prefer(
const execution::outstanding_work_t::untracked_t& p, int) const
{
return static_cast<const base_type&>(*this).prefer(p);
}
template <>
any_completion_executor any_completion_executor::prefer(
const execution::relationship_t::fork_t& p, int) const
{
return static_cast<const base_type&>(*this).prefer(p);
}
template <>
any_completion_executor any_completion_executor::prefer(
const execution::relationship_t::continuation_t& p, int) const
{
return static_cast<const base_type&>(*this).prefer(p);
}
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // !defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
#endif // BOOST_ASIO_IMPL_ANY_COMPLETION_EXECUTOR_IPP

View File

@@ -0,0 +1,143 @@
//
// impl/any_io_executor.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2023 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 BOOST_ASIO_IMPL_ANY_IO_EXECUTOR_IPP
#define BOOST_ASIO_IMPL_ANY_IO_EXECUTOR_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#if !defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
any_io_executor::any_io_executor() BOOST_ASIO_NOEXCEPT
: base_type()
{
}
any_io_executor::any_io_executor(nullptr_t) BOOST_ASIO_NOEXCEPT
: base_type(nullptr_t())
{
}
any_io_executor::any_io_executor(const any_io_executor& e) BOOST_ASIO_NOEXCEPT
: base_type(static_cast<const base_type&>(e))
{
}
any_io_executor::any_io_executor(std::nothrow_t,
const any_io_executor& e) BOOST_ASIO_NOEXCEPT
: base_type(static_cast<const base_type&>(e))
{
}
#if defined(BOOST_ASIO_HAS_MOVE)
any_io_executor::any_io_executor(any_io_executor&& e) BOOST_ASIO_NOEXCEPT
: base_type(static_cast<base_type&&>(e))
{
}
any_io_executor::any_io_executor(std::nothrow_t,
any_io_executor&& e) BOOST_ASIO_NOEXCEPT
: base_type(static_cast<base_type&&>(e))
{
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
any_io_executor& any_io_executor::operator=(
const any_io_executor& e) BOOST_ASIO_NOEXCEPT
{
base_type::operator=(static_cast<const base_type&>(e));
return *this;
}
#if defined(BOOST_ASIO_HAS_MOVE)
any_io_executor& any_io_executor::operator=(
any_io_executor&& e) BOOST_ASIO_NOEXCEPT
{
base_type::operator=(static_cast<base_type&&>(e));
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
any_io_executor& any_io_executor::operator=(nullptr_t)
{
base_type::operator=(nullptr_t());
return *this;
}
any_io_executor::~any_io_executor()
{
}
void any_io_executor::swap(any_io_executor& other) BOOST_ASIO_NOEXCEPT
{
static_cast<base_type&>(*this).swap(static_cast<base_type&>(other));
}
template <>
any_io_executor any_io_executor::require(
const execution::blocking_t::never_t& p, int) const
{
return static_cast<const base_type&>(*this).require(p);
}
template <>
any_io_executor any_io_executor::prefer(
const execution::blocking_t::possibly_t& p, int) const
{
return static_cast<const base_type&>(*this).prefer(p);
}
template <>
any_io_executor any_io_executor::prefer(
const execution::outstanding_work_t::tracked_t& p, int) const
{
return static_cast<const base_type&>(*this).prefer(p);
}
template <>
any_io_executor any_io_executor::prefer(
const execution::outstanding_work_t::untracked_t& p, int) const
{
return static_cast<const base_type&>(*this).prefer(p);
}
template <>
any_io_executor any_io_executor::prefer(
const execution::relationship_t::fork_t& p, int) const
{
return static_cast<const base_type&>(*this).prefer(p);
}
template <>
any_io_executor any_io_executor::prefer(
const execution::relationship_t::continuation_t& p, int) const
{
return static_cast<const base_type&>(*this).prefer(p);
}
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // !defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
#endif // BOOST_ASIO_IMPL_ANY_IO_EXECUTOR_IPP

View File

@@ -0,0 +1,227 @@
//
// impl/append.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2023 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 BOOST_ASIO_IMPL_APPEND_HPP
#define BOOST_ASIO_IMPL_APPEND_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/associator.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/utility.hpp>
#include <boost/asio/detail/variadic_templates.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
// Class to adapt an append_t as a completion handler.
template <typename Handler, typename... Values>
class append_handler
{
public:
typedef void result_type;
template <typename H>
append_handler(BOOST_ASIO_MOVE_ARG(H) handler, std::tuple<Values...> values)
: handler_(BOOST_ASIO_MOVE_CAST(H)(handler)),
values_(BOOST_ASIO_MOVE_CAST(std::tuple<Values...>)(values))
{
}
template <typename... Args>
void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
{
this->invoke(
index_sequence_for<Values...>{},
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
template <std::size_t... I, typename... Args>
void invoke(index_sequence<I...>, BOOST_ASIO_MOVE_ARG(Args)... args)
{
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
BOOST_ASIO_MOVE_CAST(Args)(args)...,
BOOST_ASIO_MOVE_CAST(Values)(std::get<I>(values_))...);
}
//private:
Handler handler_;
std::tuple<Values...> values_;
};
template <typename Handler>
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
append_handler<Handler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Handler>
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
append_handler<Handler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Handler>
inline bool asio_handler_is_continuation(
append_handler<Handler>* this_handler)
{
return boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename Handler>
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
append_handler<Handler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename Handler>
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
append_handler<Handler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Signature, typename... Values>
struct append_signature;
template <typename R, typename... Args, typename... Values>
struct append_signature<R(Args...), Values...>
{
typedef R type(typename decay<Args>::type..., Values...);
};
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename CompletionToken, typename... Values, typename Signature>
struct async_result<
append_t<CompletionToken, Values...>, Signature>
: async_result<CompletionToken,
typename detail::append_signature<
Signature, Values...>::type>
{
typedef typename detail::append_signature<
Signature, Values...>::type signature;
template <typename Initiation>
struct init_wrapper
{
init_wrapper(Initiation init)
: initiation_(BOOST_ASIO_MOVE_CAST(Initiation)(init))
{
}
template <typename Handler, typename... Args>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler,
std::tuple<Values...> values,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
detail::append_handler<
typename decay<Handler>::type, Values...>(
BOOST_ASIO_MOVE_CAST(Handler)(handler),
BOOST_ASIO_MOVE_CAST(std::tuple<Values...>)(values)),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
Initiation initiation_;
};
template <typename Initiation, typename RawCompletionToken, typename... Args>
static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, signature,
(async_initiate<CompletionToken, signature>(
declval<init_wrapper<typename decay<Initiation>::type> >(),
declval<CompletionToken&>(),
declval<std::tuple<Values...> >(),
declval<BOOST_ASIO_MOVE_ARG(Args)>()...)))
initiate(
BOOST_ASIO_MOVE_ARG(Initiation) initiation,
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
return async_initiate<CompletionToken, signature>(
init_wrapper<typename decay<Initiation>::type>(
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.token_,
BOOST_ASIO_MOVE_CAST(std::tuple<Values...>)(token.values_),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
};
template <template <typename, typename> class Associator,
typename Handler, typename... Values, typename DefaultCandidate>
struct associator<Associator,
detail::append_handler<Handler, Values...>, DefaultCandidate>
: Associator<Handler, DefaultCandidate>
{
static typename Associator<Handler, DefaultCandidate>::type
get(const detail::append_handler<Handler, Values...>& h) BOOST_ASIO_NOEXCEPT
{
return Associator<Handler, DefaultCandidate>::get(h.handler_);
}
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<Handler, DefaultCandidate>::type)
get(const detail::append_handler<Handler, Values...>& h,
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
{
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_IMPL_APPEND_HPP

View File

@@ -0,0 +1,322 @@
//
// impl/as_tuple.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2023 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 BOOST_ASIO_IMPL_AS_TUPLE_HPP
#define BOOST_ASIO_IMPL_AS_TUPLE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <tuple>
#include <boost/asio/associator.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/variadic_templates.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
// Class to adapt a as_tuple_t as a completion handler.
template <typename Handler>
class as_tuple_handler
{
public:
typedef void result_type;
template <typename CompletionToken>
as_tuple_handler(as_tuple_t<CompletionToken> e)
: handler_(BOOST_ASIO_MOVE_CAST(CompletionToken)(e.token_))
{
}
template <typename RedirectedHandler>
as_tuple_handler(BOOST_ASIO_MOVE_ARG(RedirectedHandler) h)
: handler_(BOOST_ASIO_MOVE_CAST(RedirectedHandler)(h))
{
}
template <typename... Args>
void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
{
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
std::make_tuple(BOOST_ASIO_MOVE_CAST(Args)(args)...));
}
//private:
Handler handler_;
};
template <typename Handler>
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
as_tuple_handler<Handler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Handler>
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
as_tuple_handler<Handler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Handler>
inline bool asio_handler_is_continuation(
as_tuple_handler<Handler>* this_handler)
{
return boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename Handler>
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
as_tuple_handler<Handler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename Handler>
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
as_tuple_handler<Handler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Signature>
struct as_tuple_signature;
template <typename R, typename... Args>
struct as_tuple_signature<R(Args...)>
{
typedef R type(std::tuple<typename decay<Args>::type...>);
};
#if defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
template <typename R, typename... Args>
struct as_tuple_signature<R(Args...) &>
{
typedef R type(std::tuple<typename decay<Args>::type...>) &;
};
template <typename R, typename... Args>
struct as_tuple_signature<R(Args...) &&>
{
typedef R type(std::tuple<typename decay<Args>::type...>) &&;
};
# if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
template <typename R, typename... Args>
struct as_tuple_signature<R(Args...) noexcept>
{
typedef R type(std::tuple<typename decay<Args>::type...>) noexcept;
};
template <typename R, typename... Args>
struct as_tuple_signature<R(Args...) & noexcept>
{
typedef R type(std::tuple<typename decay<Args>::type...>) & noexcept;
};
template <typename R, typename... Args>
struct as_tuple_signature<R(Args...) && noexcept>
{
typedef R type(std::tuple<typename decay<Args>::type...>) && noexcept;
};
# endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
#endif // defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename CompletionToken, typename... Signatures>
struct async_result<as_tuple_t<CompletionToken>, Signatures...>
: async_result<CompletionToken,
typename detail::as_tuple_signature<Signatures>::type...>
{
template <typename Initiation>
struct init_wrapper
{
init_wrapper(Initiation init)
: initiation_(BOOST_ASIO_MOVE_CAST(Initiation)(init))
{
}
template <typename Handler, typename... Args>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
detail::as_tuple_handler<
typename decay<Handler>::type>(
BOOST_ASIO_MOVE_CAST(Handler)(handler)),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
Initiation initiation_;
};
template <typename Initiation, typename RawCompletionToken, typename... Args>
static BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,
typename detail::as_tuple_signature<Signatures>::type...)
initiate(
BOOST_ASIO_MOVE_ARG(Initiation) initiation,
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
BOOST_ASIO_MOVE_ARG(Args)... args)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<
typename conditional<
is_const<typename remove_reference<RawCompletionToken>::type>::value,
const CompletionToken, CompletionToken>::type,
typename detail::as_tuple_signature<Signatures>::type...>(
init_wrapper<typename decay<Initiation>::type>(
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.token_, BOOST_ASIO_MOVE_CAST(Args)(args)...)))
{
return async_initiate<
typename conditional<
is_const<typename remove_reference<RawCompletionToken>::type>::value,
const CompletionToken, CompletionToken>::type,
typename detail::as_tuple_signature<Signatures>::type...>(
init_wrapper<typename decay<Initiation>::type>(
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.token_, BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
};
#if defined(BOOST_ASIO_MSVC)
// Workaround for MSVC internal compiler error.
template <typename CompletionToken, typename Signature>
struct async_result<as_tuple_t<CompletionToken>, Signature>
: async_result<CompletionToken,
typename detail::as_tuple_signature<Signature>::type>
{
template <typename Initiation>
struct init_wrapper
{
init_wrapper(Initiation init)
: initiation_(BOOST_ASIO_MOVE_CAST(Initiation)(init))
{
}
template <typename Handler, typename... Args>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
detail::as_tuple_handler<
typename decay<Handler>::type>(
BOOST_ASIO_MOVE_CAST(Handler)(handler)),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
Initiation initiation_;
};
template <typename Initiation, typename RawCompletionToken, typename... Args>
static BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,
typename detail::as_tuple_signature<Signatures>::type...)
initiate(
BOOST_ASIO_MOVE_ARG(Initiation) initiation,
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
BOOST_ASIO_MOVE_ARG(Args)... args)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<
typename conditional<
is_const<typename remove_reference<RawCompletionToken>::type>::value,
const CompletionToken, CompletionToken>::type,
typename detail::as_tuple_signature<Signature>::type>(
init_wrapper<typename decay<Initiation>::type>(
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.token_, BOOST_ASIO_MOVE_CAST(Args)(args)...)))
{
return async_initiate<
typename conditional<
is_const<typename remove_reference<RawCompletionToken>::type>::value,
const CompletionToken, CompletionToken>::type,
typename detail::as_tuple_signature<Signature>::type>(
init_wrapper<typename decay<Initiation>::type>(
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.token_, BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
};
#endif // defined(BOOST_ASIO_MSVC)
template <template <typename, typename> class Associator,
typename Handler, typename DefaultCandidate>
struct associator<Associator,
detail::as_tuple_handler<Handler>, DefaultCandidate>
: Associator<Handler, DefaultCandidate>
{
static typename Associator<Handler, DefaultCandidate>::type
get(const detail::as_tuple_handler<Handler>& h) BOOST_ASIO_NOEXCEPT
{
return Associator<Handler, DefaultCandidate>::get(h.handler_);
}
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<Handler, DefaultCandidate>::type)
get(const detail::as_tuple_handler<Handler>& h,
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
{
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_IMPL_AS_TUPLE_HPP

View File

@@ -2,7 +2,7 @@
// impl/awaitable.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -19,20 +19,33 @@
#include <exception>
#include <new>
#include <tuple>
#include <utility>
#include <boost/asio/cancellation_signal.hpp>
#include <boost/asio/cancellation_state.hpp>
#include <boost/asio/detail/thread_context.hpp>
#include <boost/asio/detail/thread_info_base.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/post.hpp>
#include <boost/system/system_error.hpp>
#include <boost/asio/this_coro.hpp>
#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
# if defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
# include <boost/asio/detail/source_location.hpp>
# endif // defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
struct awaitable_thread_has_context_switched {};
template <typename, typename> class awaitable_async_op_handler;
template <typename, typename, typename> class awaitable_async_op;
// An awaitable_thread represents a thread-of-execution that is composed of one
// or more "stack frames", with each frame represented by an awaitable_frame.
// All execution occurs in the context of the awaitable_thread's executor. An
@@ -78,7 +91,7 @@ public:
{
return boost::asio::detail::thread_info_base::allocate(
boost::asio::detail::thread_info_base::awaitable_frame_tag(),
boost::asio::detail::thread_context::thread_call_stack::top(),
boost::asio::detail::thread_context::top_of_thread_call_stack(),
size);
}
@@ -86,7 +99,7 @@ public:
{
boost::asio::detail::thread_info_base::deallocate(
boost::asio::detail::thread_info_base::awaitable_frame_tag(),
boost::asio::detail::thread_context::thread_call_stack::top(),
boost::asio::detail::thread_context::top_of_thread_call_stack(),
pointer, size);
}
#endif // !defined(BOOST_ASIO_DISABLE_AWAITABLE_FRAME_RECYCLING)
@@ -112,7 +125,7 @@ public:
void await_suspend(coroutine_handle<void>) noexcept
{
this_->pop_frame();
this->this_->pop_frame();
}
void await_resume() const noexcept
@@ -147,12 +160,45 @@ public:
}
}
void clear_cancellation_slot()
{
this->attached_thread_->entry_point()->cancellation_state_.slot().clear();
}
template <typename T>
auto await_transform(awaitable<T, Executor> a) const
{
if (attached_thread_->entry_point()->throw_if_cancelled_)
if (!!attached_thread_->get_cancellation_state().cancelled())
throw_error(boost::asio::error::operation_aborted, "co_await");
return a;
}
template <typename Op>
auto await_transform(Op&& op,
typename constraint<is_async_operation<Op>::value>::type = 0
#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
# if defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
, detail::source_location location = detail::source_location::current()
# endif // defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
)
{
if (attached_thread_->entry_point()->throw_if_cancelled_)
if (!!attached_thread_->get_cancellation_state().cancelled())
throw_error(boost::asio::error::operation_aborted, "co_await");
return awaitable_async_op<typename completion_signature_of<Op>::type,
typename decay<Op>::type, Executor>{
std::forward<Op>(op), this
#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
# if defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
, location
# endif // defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
};
}
// This await transformation obtains the associated executor of the thread of
// execution.
auto await_transform(this_coro::executor_t) noexcept
@@ -179,6 +225,175 @@ public:
return result{this};
}
// This await transformation obtains the associated cancellation state of the
// thread of execution.
auto await_transform(this_coro::cancellation_state_t) noexcept
{
struct result
{
awaitable_frame_base* this_;
bool await_ready() const noexcept
{
return true;
}
void await_suspend(coroutine_handle<void>) noexcept
{
}
auto await_resume() const noexcept
{
return this_->attached_thread_->get_cancellation_state();
}
};
return result{this};
}
// This await transformation resets the associated cancellation state.
auto await_transform(this_coro::reset_cancellation_state_0_t) noexcept
{
struct result
{
awaitable_frame_base* this_;
bool await_ready() const noexcept
{
return true;
}
void await_suspend(coroutine_handle<void>) noexcept
{
}
auto await_resume() const
{
return this_->attached_thread_->reset_cancellation_state();
}
};
return result{this};
}
// This await transformation resets the associated cancellation state.
template <typename Filter>
auto await_transform(
this_coro::reset_cancellation_state_1_t<Filter> reset) noexcept
{
struct result
{
awaitable_frame_base* this_;
Filter filter_;
bool await_ready() const noexcept
{
return true;
}
void await_suspend(coroutine_handle<void>) noexcept
{
}
auto await_resume()
{
return this_->attached_thread_->reset_cancellation_state(
BOOST_ASIO_MOVE_CAST(Filter)(filter_));
}
};
return result{this, BOOST_ASIO_MOVE_CAST(Filter)(reset.filter)};
}
// This await transformation resets the associated cancellation state.
template <typename InFilter, typename OutFilter>
auto await_transform(
this_coro::reset_cancellation_state_2_t<InFilter, OutFilter> reset)
noexcept
{
struct result
{
awaitable_frame_base* this_;
InFilter in_filter_;
OutFilter out_filter_;
bool await_ready() const noexcept
{
return true;
}
void await_suspend(coroutine_handle<void>) noexcept
{
}
auto await_resume()
{
return this_->attached_thread_->reset_cancellation_state(
BOOST_ASIO_MOVE_CAST(InFilter)(in_filter_),
BOOST_ASIO_MOVE_CAST(OutFilter)(out_filter_));
}
};
return result{this,
BOOST_ASIO_MOVE_CAST(InFilter)(reset.in_filter),
BOOST_ASIO_MOVE_CAST(OutFilter)(reset.out_filter)};
}
// This await transformation determines whether cancellation is propagated as
// an exception.
auto await_transform(this_coro::throw_if_cancelled_0_t)
noexcept
{
struct result
{
awaitable_frame_base* this_;
bool await_ready() const noexcept
{
return true;
}
void await_suspend(coroutine_handle<void>) noexcept
{
}
auto await_resume()
{
return this_->attached_thread_->throw_if_cancelled();
}
};
return result{this};
}
// This await transformation sets whether cancellation is propagated as an
// exception.
auto await_transform(this_coro::throw_if_cancelled_1_t throw_if_cancelled)
noexcept
{
struct result
{
awaitable_frame_base* this_;
bool value_;
bool await_ready() const noexcept
{
return true;
}
void await_suspend(coroutine_handle<void>) noexcept
{
}
auto await_resume()
{
this_->attached_thread_->throw_if_cancelled(value_);
}
};
return result{this, throw_if_cancelled.value};
}
// This await transformation is used to run an async operation's initiation
// function object after the coroutine has been suspended. This ensures that
// immediate resumption of the coroutine in another thread does not cause a
@@ -190,7 +405,7 @@ public:
typename result_of<Function(awaitable_frame_base*)>::type,
awaitable_thread<Executor>*
>::value
>::type* = 0)
>::type* = nullptr)
{
struct result
{
@@ -204,7 +419,12 @@ public:
void await_suspend(coroutine_handle<void>) noexcept
{
function_(this_);
this_->after_suspend(
[](void* arg)
{
result* r = static_cast<result*>(arg);
r->function_(r->this_);
}, this);
}
void await_resume() const noexcept
@@ -215,6 +435,31 @@ public:
return result{std::move(f), this};
}
// Access the awaitable thread's has_context_switched_ flag.
auto await_transform(detail::awaitable_thread_has_context_switched) noexcept
{
struct result
{
awaitable_frame_base* this_;
bool await_ready() const noexcept
{
return true;
}
void await_suspend(coroutine_handle<void>) noexcept
{
}
bool& await_resume() const noexcept
{
return this_->attached_thread_->entry_point()->has_context_switched_;
}
};
return result{this};
}
void attach_thread(awaitable_thread<Executor>* handler) noexcept
{
attached_thread_ = handler;
@@ -222,6 +467,7 @@ public:
awaitable_thread<Executor>* detach_thread() noexcept
{
attached_thread_->entry_point()->has_context_switched_ = true;
return std::exchange(attached_thread_, nullptr);
}
@@ -229,7 +475,7 @@ public:
{
caller_ = caller;
attached_thread_ = caller_->attached_thread_;
attached_thread_->top_of_stack_ = this;
attached_thread_->entry_point()->top_of_stack_ = this;
caller_->attached_thread_ = nullptr;
}
@@ -237,14 +483,30 @@ public:
{
if (caller_)
caller_->attached_thread_ = attached_thread_;
attached_thread_->top_of_stack_ = caller_;
attached_thread_->entry_point()->top_of_stack_ = caller_;
attached_thread_ = nullptr;
caller_ = nullptr;
}
struct resume_context
{
void (*after_suspend_fn_)(void*) = nullptr;
void *after_suspend_arg_ = nullptr;
};
void resume()
{
resume_context context;
resume_context_ = &context;
coro_.resume();
if (context.after_suspend_fn_)
context.after_suspend_fn_(context.after_suspend_arg_);
}
void after_suspend(void (*fn)(void*), void* arg)
{
resume_context_->after_suspend_fn_ = fn;
resume_context_->after_suspend_arg_ = arg;
}
void destroy()
@@ -257,6 +519,7 @@ protected:
awaitable_thread<Executor>* attached_thread_ = nullptr;
awaitable_frame_base<Executor>* caller_ = nullptr;
std::exception_ptr pending_exception_ = nullptr;
resume_context* resume_context_ = nullptr;
};
template <typename T, typename Executor>
@@ -332,25 +595,88 @@ public:
}
};
struct awaitable_thread_entry_point {};
template <typename Executor>
class awaitable_frame<awaitable_thread_entry_point, Executor>
: public awaitable_frame_base<Executor>
{
public:
awaitable_frame()
: top_of_stack_(0),
has_executor_(false),
has_context_switched_(false),
throw_if_cancelled_(true)
{
}
~awaitable_frame()
{
if (has_executor_)
u_.executor_.~Executor();
}
awaitable<awaitable_thread_entry_point, Executor> get_return_object()
{
this->coro_ = coroutine_handle<awaitable_frame>::from_promise(*this);
return awaitable<awaitable_thread_entry_point, Executor>(this);
};
void return_void()
{
}
void get()
{
this->caller_ = nullptr;
this->rethrow_exception();
}
private:
template <typename> friend class awaitable_frame_base;
template <typename, typename> friend class awaitable_async_op_handler;
template <typename, typename> friend class awaitable_handler_base;
template <typename> friend class awaitable_thread;
union u
{
u() {}
~u() {}
char c_;
Executor executor_;
} u_;
awaitable_frame_base<Executor>* top_of_stack_;
boost::asio::cancellation_slot parent_cancellation_slot_;
boost::asio::cancellation_state cancellation_state_;
bool has_executor_;
bool has_context_switched_;
bool throw_if_cancelled_;
};
template <typename Executor>
class awaitable_thread
{
public:
typedef Executor executor_type;
typedef cancellation_slot cancellation_slot_type;
// Construct from the entry point of a new thread of execution.
awaitable_thread(awaitable<void, Executor> p, const Executor& ex)
: bottom_of_stack_(std::move(p)),
top_of_stack_(bottom_of_stack_.frame_),
executor_(ex)
awaitable_thread(awaitable<awaitable_thread_entry_point, Executor> p,
const Executor& ex, cancellation_slot parent_cancel_slot,
cancellation_state cancel_state)
: bottom_of_stack_(std::move(p))
{
bottom_of_stack_.frame_->top_of_stack_ = bottom_of_stack_.frame_;
new (&bottom_of_stack_.frame_->u_.executor_) Executor(ex);
bottom_of_stack_.frame_->has_executor_ = true;
bottom_of_stack_.frame_->parent_cancellation_slot_ = parent_cancel_slot;
bottom_of_stack_.frame_->cancellation_state_ = cancel_state;
}
// Transfer ownership from another awaitable_thread.
awaitable_thread(awaitable_thread&& other) noexcept
: bottom_of_stack_(std::move(other.bottom_of_stack_)),
top_of_stack_(std::exchange(other.top_of_stack_, nullptr)),
executor_(std::move(other.executor_))
: bottom_of_stack_(std::move(other.bottom_of_stack_))
{
}
@@ -361,23 +687,74 @@ public:
if (bottom_of_stack_.valid())
{
// Coroutine "stack unwinding" must be performed through the executor.
(post)(executor_,
auto* bottom_frame = bottom_of_stack_.frame_;
(post)(bottom_frame->u_.executor_,
[a = std::move(bottom_of_stack_)]() mutable
{
awaitable<void, Executor>(std::move(a));
(void)awaitable<awaitable_thread_entry_point, Executor>(
std::move(a));
});
}
}
awaitable_frame<awaitable_thread_entry_point, Executor>* entry_point()
{
return bottom_of_stack_.frame_;
}
executor_type get_executor() const noexcept
{
return executor_;
return bottom_of_stack_.frame_->u_.executor_;
}
cancellation_state get_cancellation_state() const noexcept
{
return bottom_of_stack_.frame_->cancellation_state_;
}
void reset_cancellation_state()
{
bottom_of_stack_.frame_->cancellation_state_ =
cancellation_state(bottom_of_stack_.frame_->parent_cancellation_slot_);
}
template <typename Filter>
void reset_cancellation_state(BOOST_ASIO_MOVE_ARG(Filter) filter)
{
bottom_of_stack_.frame_->cancellation_state_ =
cancellation_state(bottom_of_stack_.frame_->parent_cancellation_slot_,
BOOST_ASIO_MOVE_CAST(Filter)(filter));
}
template <typename InFilter, typename OutFilter>
void reset_cancellation_state(BOOST_ASIO_MOVE_ARG(InFilter) in_filter,
BOOST_ASIO_MOVE_ARG(OutFilter) out_filter)
{
bottom_of_stack_.frame_->cancellation_state_ =
cancellation_state(bottom_of_stack_.frame_->parent_cancellation_slot_,
BOOST_ASIO_MOVE_CAST(InFilter)(in_filter),
BOOST_ASIO_MOVE_CAST(OutFilter)(out_filter));
}
bool throw_if_cancelled() const
{
return bottom_of_stack_.frame_->throw_if_cancelled_;
}
void throw_if_cancelled(bool value)
{
bottom_of_stack_.frame_->throw_if_cancelled_ = value;
}
cancellation_slot_type get_cancellation_slot() const noexcept
{
return bottom_of_stack_.frame_->cancellation_state_.slot();
}
// Launch a new thread of execution.
void launch()
{
top_of_stack_->attach_thread(this);
bottom_of_stack_.frame_->top_of_stack_->attach_thread(this);
pump();
}
@@ -388,17 +765,399 @@ protected:
// has been transferred to another resumable_thread object.
void pump()
{
do top_of_stack_->resume(); while (top_of_stack_);
if (bottom_of_stack_.valid())
do
bottom_of_stack_.frame_->top_of_stack_->resume();
while (bottom_of_stack_.frame_ && bottom_of_stack_.frame_->top_of_stack_);
if (bottom_of_stack_.frame_)
{
awaitable<void, Executor> a(std::move(bottom_of_stack_));
awaitable<awaitable_thread_entry_point, Executor> a(
std::move(bottom_of_stack_));
a.frame_->rethrow_exception();
}
}
awaitable<void, Executor> bottom_of_stack_;
awaitable_frame_base<Executor>* top_of_stack_;
executor_type executor_;
awaitable<awaitable_thread_entry_point, Executor> bottom_of_stack_;
};
template <typename Signature, typename Executor>
class awaitable_async_op_handler;
template <typename R, typename Executor>
class awaitable_async_op_handler<R(), Executor>
: public awaitable_thread<Executor>
{
public:
struct result_type {};
awaitable_async_op_handler(
awaitable_thread<Executor>* h, result_type&)
: awaitable_thread<Executor>(std::move(*h))
{
}
void operator()()
{
this->entry_point()->top_of_stack_->attach_thread(this);
this->entry_point()->top_of_stack_->clear_cancellation_slot();
this->pump();
}
static void resume(result_type&)
{
}
};
template <typename R, typename Executor>
class awaitable_async_op_handler<R(boost::system::error_code), Executor>
: public awaitable_thread<Executor>
{
public:
typedef boost::system::error_code* result_type;
awaitable_async_op_handler(
awaitable_thread<Executor>* h, result_type& result)
: awaitable_thread<Executor>(std::move(*h)),
result_(result)
{
}
void operator()(boost::system::error_code ec)
{
result_ = &ec;
this->entry_point()->top_of_stack_->attach_thread(this);
this->entry_point()->top_of_stack_->clear_cancellation_slot();
this->pump();
}
static void resume(result_type& result)
{
throw_error(*result);
}
private:
result_type& result_;
};
template <typename R, typename Executor>
class awaitable_async_op_handler<R(std::exception_ptr), Executor>
: public awaitable_thread<Executor>
{
public:
typedef std::exception_ptr* result_type;
awaitable_async_op_handler(
awaitable_thread<Executor>* h, result_type& result)
: awaitable_thread<Executor>(std::move(*h)),
result_(result)
{
}
void operator()(std::exception_ptr ex)
{
result_ = &ex;
this->entry_point()->top_of_stack_->attach_thread(this);
this->entry_point()->top_of_stack_->clear_cancellation_slot();
this->pump();
}
static void resume(result_type& result)
{
if (*result)
{
std::exception_ptr ex = std::exchange(*result, nullptr);
std::rethrow_exception(ex);
}
}
private:
result_type& result_;
};
template <typename R, typename T, typename Executor>
class awaitable_async_op_handler<R(T), Executor>
: public awaitable_thread<Executor>
{
public:
typedef T* result_type;
awaitable_async_op_handler(
awaitable_thread<Executor>* h, result_type& result)
: awaitable_thread<Executor>(std::move(*h)),
result_(result)
{
}
void operator()(T result)
{
result_ = &result;
this->entry_point()->top_of_stack_->attach_thread(this);
this->entry_point()->top_of_stack_->clear_cancellation_slot();
this->pump();
}
static T resume(result_type& result)
{
return std::move(*result);
}
private:
result_type& result_;
};
template <typename R, typename T, typename Executor>
class awaitable_async_op_handler<R(boost::system::error_code, T), Executor>
: public awaitable_thread<Executor>
{
public:
struct result_type
{
boost::system::error_code* ec_;
T* value_;
};
awaitable_async_op_handler(
awaitable_thread<Executor>* h, result_type& result)
: awaitable_thread<Executor>(std::move(*h)),
result_(result)
{
}
void operator()(boost::system::error_code ec, T value)
{
result_.ec_ = &ec;
result_.value_ = &value;
this->entry_point()->top_of_stack_->attach_thread(this);
this->entry_point()->top_of_stack_->clear_cancellation_slot();
this->pump();
}
static T resume(result_type& result)
{
throw_error(*result.ec_);
return std::move(*result.value_);
}
private:
result_type& result_;
};
template <typename R, typename T, typename Executor>
class awaitable_async_op_handler<R(std::exception_ptr, T), Executor>
: public awaitable_thread<Executor>
{
public:
struct result_type
{
std::exception_ptr* ex_;
T* value_;
};
awaitable_async_op_handler(
awaitable_thread<Executor>* h, result_type& result)
: awaitable_thread<Executor>(std::move(*h)),
result_(result)
{
}
void operator()(std::exception_ptr ex, T value)
{
result_.ex_ = &ex;
result_.value_ = &value;
this->entry_point()->top_of_stack_->attach_thread(this);
this->entry_point()->top_of_stack_->clear_cancellation_slot();
this->pump();
}
static T resume(result_type& result)
{
if (*result.ex_)
{
std::exception_ptr ex = std::exchange(*result.ex_, nullptr);
std::rethrow_exception(ex);
}
return std::move(*result.value_);
}
private:
result_type& result_;
};
template <typename R, typename... Ts, typename Executor>
class awaitable_async_op_handler<R(Ts...), Executor>
: public awaitable_thread<Executor>
{
public:
typedef std::tuple<Ts...>* result_type;
awaitable_async_op_handler(
awaitable_thread<Executor>* h, result_type& result)
: awaitable_thread<Executor>(std::move(*h)),
result_(result)
{
}
template <typename... Args>
void operator()(Args&&... args)
{
std::tuple<Ts...> result(std::forward<Args>(args)...);
result_ = &result;
this->entry_point()->top_of_stack_->attach_thread(this);
this->entry_point()->top_of_stack_->clear_cancellation_slot();
this->pump();
}
static std::tuple<Ts...> resume(result_type& result)
{
return std::move(*result);
}
private:
result_type& result_;
};
template <typename R, typename... Ts, typename Executor>
class awaitable_async_op_handler<R(boost::system::error_code, Ts...), Executor>
: public awaitable_thread<Executor>
{
public:
struct result_type
{
boost::system::error_code* ec_;
std::tuple<Ts...>* value_;
};
awaitable_async_op_handler(
awaitable_thread<Executor>* h, result_type& result)
: awaitable_thread<Executor>(std::move(*h)),
result_(result)
{
}
template <typename... Args>
void operator()(boost::system::error_code ec, Args&&... args)
{
result_.ec_ = &ec;
std::tuple<Ts...> value(std::forward<Args>(args)...);
result_.value_ = &value;
this->entry_point()->top_of_stack_->attach_thread(this);
this->entry_point()->top_of_stack_->clear_cancellation_slot();
this->pump();
}
static std::tuple<Ts...> resume(result_type& result)
{
throw_error(*result.ec_);
return std::move(*result.value_);
}
private:
result_type& result_;
};
template <typename R, typename... Ts, typename Executor>
class awaitable_async_op_handler<R(std::exception_ptr, Ts...), Executor>
: public awaitable_thread<Executor>
{
public:
struct result_type
{
std::exception_ptr* ex_;
std::tuple<Ts...>* value_;
};
awaitable_async_op_handler(
awaitable_thread<Executor>* h, result_type& result)
: awaitable_thread<Executor>(std::move(*h)),
result_(result)
{
}
template <typename... Args>
void operator()(std::exception_ptr ex, Args&&... args)
{
result_.ex_ = &ex;
std::tuple<Ts...> value(std::forward<Args>(args)...);
result_.value_ = &value;
this->entry_point()->top_of_stack_->attach_thread(this);
this->entry_point()->top_of_stack_->clear_cancellation_slot();
this->pump();
}
static std::tuple<Ts...> resume(result_type& result)
{
if (*result.ex_)
{
std::exception_ptr ex = std::exchange(*result.ex_, nullptr);
std::rethrow_exception(ex);
}
return std::move(*result.value_);
}
private:
result_type& result_;
};
template <typename Signature, typename Op, typename Executor>
class awaitable_async_op
{
public:
typedef awaitable_async_op_handler<Signature, Executor> handler_type;
awaitable_async_op(Op&& o, awaitable_frame_base<Executor>* frame
#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
# if defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
, const detail::source_location& location
# endif // defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
)
: op_(std::forward<Op>(o)),
frame_(frame),
result_()
#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
# if defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
, location_(location)
# endif // defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
{
}
bool await_ready() const noexcept
{
return false;
}
void await_suspend(coroutine_handle<void>)
{
frame_->after_suspend(
[](void* arg)
{
awaitable_async_op* self = static_cast<awaitable_async_op*>(arg);
#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
# if defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
BOOST_ASIO_HANDLER_LOCATION((self->location_.file_name(),
self->location_.line(), self->location_.function_name()));
# endif // defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
std::forward<Op&&>(self->op_)(
handler_type(self->frame_->detach_thread(), self->result_));
}, this);
}
auto await_resume()
{
return handler_type::resume(result_);
}
private:
Op&& op_;
awaitable_frame_base<Executor>* frame_;
typename handler_type::result_type result_;
#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
# if defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
detail::source_location location_;
# endif // defined(BOOST_ASIO_HAS_SOURCE_LOCATION)
#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
};
} // namespace detail
@@ -406,6 +1165,19 @@ protected:
} // namespace boost
#if !defined(GENERATING_DOCUMENTATION)
# if defined(BOOST_ASIO_HAS_STD_COROUTINE)
namespace std {
template <typename T, typename Executor, typename... Args>
struct coroutine_traits<boost::asio::awaitable<T, Executor>, Args...>
{
typedef boost::asio::detail::awaitable_frame<T, Executor> promise_type;
};
} // namespace std
# else // defined(BOOST_ASIO_HAS_STD_COROUTINE)
namespace std { namespace experimental {
@@ -417,6 +1189,7 @@ struct coroutine_traits<boost::asio::awaitable<T, Executor>, Args...>
}} // namespace std::experimental
# endif // defined(BOOST_ASIO_HAS_STD_COROUTINE)
#endif // !defined(GENERATING_DOCUMENTATION)
#include <boost/asio/detail/pop_options.hpp>

View File

@@ -2,7 +2,7 @@
// impl/buffered_read_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -15,13 +15,13 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/associator.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -91,7 +91,7 @@ namespace detail
const std::size_t bytes_transferred)
{
storage_.resize(previous_size_ + bytes_transferred);
handler_(ec, bytes_transferred);
BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(ec, bytes_transferred);
}
//private:
@@ -101,19 +101,29 @@ namespace detail
};
template <typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
buffered_fill_handler<ReadHandler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
buffered_fill_handler<ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename ReadHandler>
@@ -125,26 +135,50 @@ namespace detail
}
template <typename Function, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
buffered_fill_handler<ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
buffered_fill_handler<ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
struct initiate_async_buffered_fill
template <typename Stream>
class initiate_async_buffered_fill
{
template <typename ReadHandler, typename Stream>
public:
typedef typename remove_reference<
Stream>::type::lowest_layer_type::executor_type executor_type;
explicit initiate_async_buffered_fill(
typename remove_reference<Stream>::type& next_layer)
: next_layer_(next_layer)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return next_layer_.lowest_layer().get_executor();
}
template <typename ReadHandler>
void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
buffered_stream_storage* storage, Stream* next_layer) const
buffered_stream_storage* storage) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a ReadHandler.
@@ -153,56 +187,65 @@ namespace detail
non_const_lvalue<ReadHandler> handler2(handler);
std::size_t previous_size = storage->size();
storage->resize(storage->capacity());
next_layer->async_read_some(
next_layer_.async_read_some(
buffer(
storage->data() + previous_size,
storage->size() - previous_size),
buffered_fill_handler<typename decay<ReadHandler>::type>(
*storage, previous_size, handler2.value));
}
private:
typename remove_reference<Stream>::type& next_layer_;
};
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename ReadHandler, typename Allocator>
struct associated_allocator<
detail::buffered_fill_handler<ReadHandler>, Allocator>
template <template <typename, typename> class Associator,
typename ReadHandler, typename DefaultCandidate>
struct associator<Associator,
detail::buffered_fill_handler<ReadHandler>,
DefaultCandidate>
: Associator<ReadHandler, DefaultCandidate>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(const detail::buffered_fill_handler<ReadHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
static typename Associator<ReadHandler, DefaultCandidate>::type
get(const detail::buffered_fill_handler<ReadHandler>& h) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
}
};
template <typename ReadHandler, typename Executor>
struct associated_executor<
detail::buffered_fill_handler<ReadHandler>, Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(const detail::buffered_fill_handler<ReadHandler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<ReadHandler, DefaultCandidate>::type)
get(const detail::buffered_fill_handler<ReadHandler>& h,
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename Stream>
template <typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler,
void (boost::system::error_code, std::size_t))
buffered_read_stream<Stream>::async_fill(
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<ReadHandler,
void (boost::system::error_code, std::size_t)>(
declval<detail::initiate_async_buffered_fill<Stream> >(),
handler, declval<detail::buffered_stream_storage*>())))
{
return async_initiate<ReadHandler,
void (boost::system::error_code, std::size_t)>(
detail::initiate_async_buffered_fill(), handler, &storage_, &next_layer_);
detail::initiate_async_buffered_fill<Stream>(next_layer_),
handler, &storage_);
}
template <typename Stream>
@@ -272,14 +315,14 @@ namespace detail
if (ec || storage_.empty())
{
const std::size_t length = 0;
handler_(ec, length);
BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(ec, length);
}
else
{
const std::size_t bytes_copied = boost::asio::buffer_copy(
buffers_, storage_.data(), storage_.size());
storage_.consume(bytes_copied);
handler_(ec, bytes_copied);
BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(ec, bytes_copied);
}
}
@@ -290,21 +333,31 @@ namespace detail
};
template <typename MutableBufferSequence, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
buffered_read_some_handler<
MutableBufferSequence, ReadHandler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename MutableBufferSequence, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
buffered_read_some_handler<
MutableBufferSequence, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename MutableBufferSequence, typename ReadHandler>
@@ -318,30 +371,53 @@ namespace detail
template <typename Function, typename MutableBufferSequence,
typename ReadHandler>
inline void asio_handler_invoke(Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
buffered_read_some_handler<
MutableBufferSequence, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename MutableBufferSequence,
typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
buffered_read_some_handler<
MutableBufferSequence, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
struct initiate_async_buffered_read_some
template <typename Stream>
class initiate_async_buffered_read_some
{
template <typename ReadHandler, typename Stream,
typename MutableBufferSequence>
public:
typedef typename remove_reference<
Stream>::type::lowest_layer_type::executor_type executor_type;
explicit initiate_async_buffered_read_some(
typename remove_reference<Stream>::type& next_layer)
: next_layer_(next_layer)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return next_layer_.lowest_layer().get_executor();
}
template <typename ReadHandler, typename MutableBufferSequence>
void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
buffered_stream_storage* storage, Stream* next_layer,
buffered_stream_storage* storage,
const MutableBufferSequence& buffers) const
{
// If you get an error on the following line it means that your handler
@@ -352,73 +428,76 @@ namespace detail
non_const_lvalue<ReadHandler> handler2(handler);
if (buffer_size(buffers) == 0 || !storage->empty())
{
next_layer->async_read_some(BOOST_ASIO_MUTABLE_BUFFER(0, 0),
next_layer_.async_read_some(BOOST_ASIO_MUTABLE_BUFFER(0, 0),
buffered_read_some_handler<MutableBufferSequence,
typename decay<ReadHandler>::type>(
*storage, buffers, handler2.value));
}
else
{
initiate_async_buffered_fill()(
initiate_async_buffered_fill<Stream>(this->next_layer_)(
buffered_read_some_handler<MutableBufferSequence,
typename decay<ReadHandler>::type>(
*storage, buffers, handler2.value),
storage, next_layer);
storage);
}
}
private:
typename remove_reference<Stream>::type& next_layer_;
};
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename MutableBufferSequence,
typename ReadHandler, typename Allocator>
struct associated_allocator<
template <template <typename, typename> class Associator,
typename MutableBufferSequence, typename ReadHandler,
typename DefaultCandidate>
struct associator<Associator,
detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,
Allocator>
DefaultCandidate>
: Associator<ReadHandler, DefaultCandidate>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(
const detail::buffered_read_some_handler<
MutableBufferSequence, ReadHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
static typename Associator<ReadHandler, DefaultCandidate>::type
get(const detail::buffered_read_some_handler<
MutableBufferSequence, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
}
};
template <typename MutableBufferSequence,
typename ReadHandler, typename Executor>
struct associated_executor<
detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,
Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(
const detail::buffered_read_some_handler<
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<ReadHandler, DefaultCandidate>::type)
get(const detail::buffered_read_some_handler<
MutableBufferSequence, ReadHandler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename Stream>
template <typename MutableBufferSequence, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler,
void (boost::system::error_code, std::size_t))
buffered_read_stream<Stream>::async_read_some(
const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<ReadHandler,
void (boost::system::error_code, std::size_t)>(
declval<detail::initiate_async_buffered_read_some<Stream> >(),
handler, declval<detail::buffered_stream_storage*>(), buffers)))
{
return async_initiate<ReadHandler,
void (boost::system::error_code, std::size_t)>(
detail::initiate_async_buffered_read_some(),
handler, &storage_, &next_layer_, buffers);
detail::initiate_async_buffered_read_some<Stream>(next_layer_),
handler, &storage_, buffers);
}
template <typename Stream>

View File

@@ -2,7 +2,7 @@
// impl/buffered_write_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -15,8 +15,7 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/associator.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
@@ -78,7 +77,7 @@ namespace detail
const std::size_t bytes_written)
{
storage_.consume(bytes_written);
handler_(ec, bytes_written);
BOOST_ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_written);
}
//private:
@@ -87,19 +86,29 @@ namespace detail
};
template <typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
buffered_flush_handler<WriteHandler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
buffered_flush_handler<WriteHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename WriteHandler>
@@ -111,80 +120,112 @@ namespace detail
}
template <typename Function, typename WriteHandler>
inline void asio_handler_invoke(Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
buffered_flush_handler<WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
buffered_flush_handler<WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
struct initiate_async_buffered_flush
template <typename Stream>
class initiate_async_buffered_flush
{
template <typename WriteHandler, typename Stream>
public:
typedef typename remove_reference<
Stream>::type::lowest_layer_type::executor_type executor_type;
explicit initiate_async_buffered_flush(
typename remove_reference<Stream>::type& next_layer)
: next_layer_(next_layer)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return next_layer_.lowest_layer().get_executor();
}
template <typename WriteHandler>
void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
buffered_stream_storage* storage, Stream* next_layer) const
buffered_stream_storage* storage) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
non_const_lvalue<WriteHandler> handler2(handler);
async_write(*next_layer, buffer(storage->data(), storage->size()),
async_write(next_layer_, buffer(storage->data(), storage->size()),
buffered_flush_handler<typename decay<WriteHandler>::type>(
*storage, handler2.value));
}
private:
typename remove_reference<Stream>::type& next_layer_;
};
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename WriteHandler, typename Allocator>
struct associated_allocator<
detail::buffered_flush_handler<WriteHandler>, Allocator>
template <template <typename, typename> class Associator,
typename WriteHandler, typename DefaultCandidate>
struct associator<Associator,
detail::buffered_flush_handler<WriteHandler>,
DefaultCandidate>
: Associator<WriteHandler, DefaultCandidate>
{
typedef typename associated_allocator<WriteHandler, Allocator>::type type;
static type get(const detail::buffered_flush_handler<WriteHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
static typename Associator<WriteHandler, DefaultCandidate>::type
get(const detail::buffered_flush_handler<WriteHandler>& h) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
}
};
template <typename WriteHandler, typename Executor>
struct associated_executor<
detail::buffered_flush_handler<WriteHandler>, Executor>
{
typedef typename associated_executor<WriteHandler, Executor>::type type;
static type get(const detail::buffered_flush_handler<WriteHandler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<WriteHandler, DefaultCandidate>::type)
get(const detail::buffered_flush_handler<WriteHandler>& h,
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)))
{
return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename Stream>
template <typename WriteHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) WriteHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler,
void (boost::system::error_code, std::size_t))
buffered_write_stream<Stream>::async_flush(
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<WriteHandler,
void (boost::system::error_code, std::size_t)>(
declval<detail::initiate_async_buffered_flush<Stream> >(),
handler, declval<detail::buffered_stream_storage*>())))
{
return async_initiate<WriteHandler,
void (boost::system::error_code, std::size_t)>(
detail::initiate_async_buffered_flush(),
handler, &storage_, &next_layer_);
detail::initiate_async_buffered_flush<Stream>(next_layer_),
handler, &storage_);
}
template <typename Stream>
@@ -254,7 +295,7 @@ namespace detail
if (ec)
{
const std::size_t length = 0;
handler_(ec, length);
BOOST_ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, length);
}
else
{
@@ -267,7 +308,7 @@ namespace detail
storage_.resize(orig_size + length);
const std::size_t bytes_copied = boost::asio::buffer_copy(
storage_.data() + orig_size, buffers_, length);
handler_(ec, bytes_copied);
BOOST_ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_copied);
}
}
@@ -278,21 +319,31 @@ namespace detail
};
template <typename ConstBufferSequence, typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
buffered_write_some_handler<
ConstBufferSequence, WriteHandler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename ConstBufferSequence, typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
buffered_write_some_handler<
ConstBufferSequence, WriteHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename ConstBufferSequence, typename WriteHandler>
@@ -306,30 +357,53 @@ namespace detail
template <typename Function, typename ConstBufferSequence,
typename WriteHandler>
inline void asio_handler_invoke(Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
buffered_write_some_handler<
ConstBufferSequence, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename ConstBufferSequence,
typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
buffered_write_some_handler<
ConstBufferSequence, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
struct initiate_async_buffered_write_some
template <typename Stream>
class initiate_async_buffered_write_some
{
template <typename WriteHandler, typename Stream,
typename ConstBufferSequence>
public:
typedef typename remove_reference<
Stream>::type::lowest_layer_type::executor_type executor_type;
explicit initiate_async_buffered_write_some(
typename remove_reference<Stream>::type& next_layer)
: next_layer_(next_layer)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return next_layer_.lowest_layer().get_executor();
}
template <typename WriteHandler, typename ConstBufferSequence>
void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
buffered_stream_storage* storage, Stream* next_layer,
buffered_stream_storage* storage,
const ConstBufferSequence& buffers) const
{
// If you get an error on the following line it means that your handler
@@ -340,73 +414,76 @@ namespace detail
non_const_lvalue<WriteHandler> handler2(handler);
if (buffer_size(buffers) == 0 || storage->size() < storage->capacity())
{
next_layer->async_write_some(BOOST_ASIO_CONST_BUFFER(0, 0),
next_layer_.async_write_some(BOOST_ASIO_CONST_BUFFER(0, 0),
buffered_write_some_handler<ConstBufferSequence,
typename decay<WriteHandler>::type>(
*storage, buffers, handler2.value));
}
else
{
initiate_async_buffered_flush()(
initiate_async_buffered_flush<Stream>(this->next_layer_)(
buffered_write_some_handler<ConstBufferSequence,
typename decay<WriteHandler>::type>(
*storage, buffers, handler2.value),
storage, next_layer);
storage);
}
}
private:
typename remove_reference<Stream>::type& next_layer_;
};
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename ConstBufferSequence,
typename WriteHandler, typename Allocator>
struct associated_allocator<
template <template <typename, typename> class Associator,
typename ConstBufferSequence, typename WriteHandler,
typename DefaultCandidate>
struct associator<Associator,
detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,
Allocator>
DefaultCandidate>
: Associator<WriteHandler, DefaultCandidate>
{
typedef typename associated_allocator<WriteHandler, Allocator>::type type;
static type get(
const detail::buffered_write_some_handler<
ConstBufferSequence, WriteHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
static typename Associator<WriteHandler, DefaultCandidate>::type
get(const detail::buffered_write_some_handler<
ConstBufferSequence, WriteHandler>& h) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
}
};
template <typename ConstBufferSequence,
typename WriteHandler, typename Executor>
struct associated_executor<
detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,
Executor>
{
typedef typename associated_executor<WriteHandler, Executor>::type type;
static type get(
const detail::buffered_write_some_handler<
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<WriteHandler, DefaultCandidate>::type)
get(const detail::buffered_write_some_handler<
ConstBufferSequence, WriteHandler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)))
{
return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename Stream>
template <typename ConstBufferSequence, typename WriteHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) WriteHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler,
void (boost::system::error_code, std::size_t))
buffered_write_stream<Stream>::async_write_some(
const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<WriteHandler,
void (boost::system::error_code, std::size_t)>(
declval<detail::initiate_async_buffered_write_some<Stream> >(),
handler, declval<detail::buffered_stream_storage*>(), buffers)))
{
return async_initiate<WriteHandler,
void (boost::system::error_code, std::size_t)>(
detail::initiate_async_buffered_write_some(),
handler, &storage_, &next_layer_, buffers);
detail::initiate_async_buffered_write_some<Stream>(next_layer_),
handler, &storage_, buffers);
}
template <typename Stream>

View File

@@ -0,0 +1,98 @@
//
// impl/cancellation_signal.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2023 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 BOOST_ASIO_IMPL_CANCELLATION_SIGNAL_IPP
#define BOOST_ASIO_IMPL_CANCELLATION_SIGNAL_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/cancellation_signal.hpp>
#include <boost/asio/detail/thread_context.hpp>
#include <boost/asio/detail/thread_info_base.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
cancellation_signal::~cancellation_signal()
{
if (handler_)
{
std::pair<void*, std::size_t> mem = handler_->destroy();
detail::thread_info_base::deallocate(
detail::thread_info_base::cancellation_signal_tag(),
detail::thread_context::top_of_thread_call_stack(),
mem.first, mem.second);
}
}
void cancellation_slot::clear()
{
if (handler_ != 0 && *handler_ != 0)
{
std::pair<void*, std::size_t> mem = (*handler_)->destroy();
detail::thread_info_base::deallocate(
detail::thread_info_base::cancellation_signal_tag(),
detail::thread_context::top_of_thread_call_stack(),
mem.first, mem.second);
*handler_ = 0;
}
}
std::pair<void*, std::size_t> cancellation_slot::prepare_memory(
std::size_t size, std::size_t align)
{
assert(handler_);
std::pair<void*, std::size_t> mem;
if (*handler_)
{
mem = (*handler_)->destroy();
*handler_ = 0;
}
if (size > mem.second
|| reinterpret_cast<std::size_t>(mem.first) % align != 0)
{
if (mem.first)
{
detail::thread_info_base::deallocate(
detail::thread_info_base::cancellation_signal_tag(),
detail::thread_context::top_of_thread_call_stack(),
mem.first, mem.second);
}
mem.first = detail::thread_info_base::allocate(
detail::thread_info_base::cancellation_signal_tag(),
detail::thread_context::top_of_thread_call_stack(),
size, align);
mem.second = size;
}
return mem;
}
cancellation_slot::auto_delete_helper::~auto_delete_helper()
{
if (mem.first)
{
detail::thread_info_base::deallocate(
detail::thread_info_base::cancellation_signal_tag(),
detail::thread_context::top_of_thread_call_stack(),
mem.first, mem.second);
}
}
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_IMPL_CANCELLATION_SIGNAL_IPP

View File

@@ -2,7 +2,7 @@
// impl/co_spawn.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -16,9 +16,14 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/associated_cancellation_slot.hpp>
#include <boost/asio/awaitable.hpp>
#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/recycling_allocator.hpp>
#include <boost/asio/dispatch.hpp>
#include <boost/asio/execution/outstanding_work.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/prefer.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -27,106 +32,404 @@ namespace boost {
namespace asio {
namespace detail {
template <typename T, typename Executor, typename F, typename Handler>
awaitable<void, Executor> co_spawn_entry_point(
awaitable<T, Executor>*, Executor ex, F f, Handler handler)
template <typename Executor, typename = void>
class co_spawn_work_guard
{
auto spawn_work = make_work_guard(ex);
auto handler_work = make_work_guard(handler, ex);
public:
typedef typename decay<
typename prefer_result<Executor,
execution::outstanding_work_t::tracked_t
>::type
>::type executor_type;
(void) co_await (post)(spawn_work.get_executor(),
use_awaitable_t<Executor>{});
co_spawn_work_guard(const Executor& ex)
: executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return executor_;
}
private:
executor_type executor_;
};
#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
template <typename Executor>
struct co_spawn_work_guard<Executor,
typename enable_if<
!execution::is_executor<Executor>::value
>::type> : executor_work_guard<Executor>
{
co_spawn_work_guard(const Executor& ex)
: executor_work_guard<Executor>(ex)
{
}
};
#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
template <typename Handler, typename Executor,
typename Function, typename = void>
struct co_spawn_state
{
template <typename H, typename F>
co_spawn_state(H&& h, const Executor& ex, F&& f)
: handler(std::forward<H>(h)),
spawn_work(ex),
handler_work(boost::asio::get_associated_executor(handler, ex)),
function(std::forward<F>(f))
{
}
Handler handler;
co_spawn_work_guard<Executor> spawn_work;
co_spawn_work_guard<typename associated_executor<
Handler, Executor>::type> handler_work;
Function function;
};
template <typename Handler, typename Executor, typename Function>
struct co_spawn_state<Handler, Executor, Function,
typename enable_if<
is_same<
typename associated_executor<Handler,
Executor>::asio_associated_executor_is_unspecialised,
void
>::value
>::type>
{
template <typename H, typename F>
co_spawn_state(H&& h, const Executor& ex, F&& f)
: handler(std::forward<H>(h)),
handler_work(ex),
function(std::forward<F>(f))
{
}
Handler handler;
co_spawn_work_guard<Executor> handler_work;
Function function;
};
struct co_spawn_dispatch
{
template <typename CompletionToken>
auto operator()(CompletionToken&& token) const
-> decltype(boost::asio::dispatch(std::forward<CompletionToken>(token)))
{
return boost::asio::dispatch(std::forward<CompletionToken>(token));
}
};
struct co_spawn_post
{
template <typename CompletionToken>
auto operator()(CompletionToken&& token) const
-> decltype(boost::asio::post(std::forward<CompletionToken>(token)))
{
return boost::asio::post(std::forward<CompletionToken>(token));
}
};
template <typename T, typename Handler, typename Executor, typename Function>
awaitable<awaitable_thread_entry_point, Executor> co_spawn_entry_point(
awaitable<T, Executor>*, co_spawn_state<Handler, Executor, Function> s)
{
(void) co_await co_spawn_dispatch{};
(co_await awaitable_thread_has_context_switched{}) = false;
std::exception_ptr e = nullptr;
bool done = false;
try
{
T t = co_await f();
T t = co_await s.function();
done = true;
(dispatch)(handler_work.get_executor(),
[handler = std::move(handler), t = std::move(t)]() mutable
bool switched = (co_await awaitable_thread_has_context_switched{});
if (!switched)
(void) co_await co_spawn_post();
(dispatch)(s.handler_work.get_executor(),
[handler = std::move(s.handler), t = std::move(t)]() mutable
{
handler(std::exception_ptr(), std::move(t));
std::move(handler)(std::exception_ptr(), std::move(t));
});
co_return;
}
catch (...)
{
if (done)
throw;
(dispatch)(handler_work.get_executor(),
[handler = std::move(handler), e = std::current_exception()]() mutable
{
handler(e, T());
});
e = std::current_exception();
}
bool switched = (co_await awaitable_thread_has_context_switched{});
if (!switched)
(void) co_await co_spawn_post();
(dispatch)(s.handler_work.get_executor(),
[handler = std::move(s.handler), e]() mutable
{
std::move(handler)(e, T());
});
}
template <typename Executor, typename F, typename Handler>
awaitable<void, Executor> co_spawn_entry_point(
awaitable<void, Executor>*, Executor ex, F f, Handler handler)
template <typename Handler, typename Executor, typename Function>
awaitable<awaitable_thread_entry_point, Executor> co_spawn_entry_point(
awaitable<void, Executor>*, co_spawn_state<Handler, Executor, Function> s)
{
auto spawn_work = make_work_guard(ex);
auto handler_work = make_work_guard(handler, ex);
(void) co_await (post)(spawn_work.get_executor(),
use_awaitable_t<Executor>{});
(void) co_await co_spawn_dispatch{};
(co_await awaitable_thread_has_context_switched{}) = false;
std::exception_ptr e = nullptr;
try
{
co_await f();
co_await s.function();
}
catch (...)
{
e = std::current_exception();
}
(dispatch)(handler_work.get_executor(),
[handler = std::move(handler), e]() mutable
bool switched = (co_await awaitable_thread_has_context_switched{});
if (!switched)
(void) co_await co_spawn_post();
(dispatch)(s.handler_work.get_executor(),
[handler = std::move(s.handler), e]() mutable
{
handler(e);
std::move(handler)(e);
});
}
struct initiate_co_spawn
template <typename T, typename Executor>
class awaitable_as_function
{
template <typename Handler, typename Executor, typename F>
void operator()(Handler&& handler, const Executor& ex, F&& f) const
public:
explicit awaitable_as_function(awaitable<T, Executor>&& a)
: awaitable_(std::move(a))
{
}
awaitable<T, Executor> operator()()
{
return std::move(awaitable_);
}
private:
awaitable<T, Executor> awaitable_;
};
template <typename Handler, typename Executor, typename = void>
class co_spawn_cancellation_handler
{
public:
co_spawn_cancellation_handler(const Handler&, const Executor& ex)
: signal_(detail::allocate_shared<cancellation_signal>(
detail::recycling_allocator<cancellation_signal,
detail::thread_info_base::cancellation_signal_tag>())),
ex_(ex)
{
}
cancellation_slot slot()
{
return signal_->slot();
}
void operator()(cancellation_type_t type)
{
shared_ptr<cancellation_signal> sig = signal_;
boost::asio::dispatch(ex_, [sig, type]{ sig->emit(type); });
}
private:
shared_ptr<cancellation_signal> signal_;
Executor ex_;
};
template <typename Handler, typename Executor>
class co_spawn_cancellation_handler<Handler, Executor,
typename enable_if<
is_same<
typename associated_executor<Handler,
Executor>::asio_associated_executor_is_unspecialised,
void
>::value
>::type>
{
public:
co_spawn_cancellation_handler(const Handler&, const Executor&)
{
}
cancellation_slot slot()
{
return signal_.slot();
}
void operator()(cancellation_type_t type)
{
signal_.emit(type);
}
private:
cancellation_signal signal_;
};
template <typename Executor>
class initiate_co_spawn
{
public:
typedef Executor executor_type;
template <typename OtherExecutor>
explicit initiate_co_spawn(const OtherExecutor& ex)
: ex_(ex)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return ex_;
}
template <typename Handler, typename F>
void operator()(Handler&& handler, F&& f) const
{
typedef typename result_of<F()>::type awaitable_type;
typedef typename awaitable_type::executor_type executor_type;
typedef typename decay<Handler>::type handler_type;
typedef typename decay<F>::type function_type;
typedef co_spawn_cancellation_handler<
handler_type, Executor> cancel_handler_type;
auto slot = boost::asio::get_associated_cancellation_slot(handler);
cancel_handler_type* cancel_handler = slot.is_connected()
? &slot.template emplace<cancel_handler_type>(handler, ex_)
: nullptr;
cancellation_slot proxy_slot(
cancel_handler
? cancel_handler->slot()
: cancellation_slot());
cancellation_state cancel_state(proxy_slot);
executor_type ex2(ex);
auto a = (co_spawn_entry_point)(static_cast<awaitable_type*>(nullptr),
ex2, std::forward<F>(f), std::forward<Handler>(handler));
awaitable_handler<executor_type, void>(std::move(a), ex2).launch();
co_spawn_state<handler_type, Executor, function_type>(
std::forward<Handler>(handler), ex_, std::forward<F>(f)));
awaitable_handler<executor_type, void>(std::move(a),
ex_, proxy_slot, cancel_state).launch();
}
private:
Executor ex_;
};
} // namespace detail
template <typename Executor, typename F, typename CompletionToken>
inline BOOST_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*)
template <typename Executor, typename T, typename AwaitableExecutor,
BOOST_ASIO_COMPLETION_TOKEN_FOR(
void(std::exception_ptr, T)) CompletionToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken, void(std::exception_ptr, T))
co_spawn(const Executor& ex,
awaitable<T, AwaitableExecutor> a, CompletionToken&& token,
typename constraint<
(is_executor<Executor>::value || execution::is_executor<Executor>::value)
&& is_convertible<Executor, AwaitableExecutor>::value
>::type)
{
return async_initiate<CompletionToken,
typename detail::awaitable_signature<typename result_of<F()>::type>>(
detail::initiate_co_spawn(), token, ex, std::forward<F>(f));
return async_initiate<CompletionToken, void(std::exception_ptr, T)>(
detail::initiate_co_spawn<AwaitableExecutor>(AwaitableExecutor(ex)),
token, detail::awaitable_as_function<T, AwaitableExecutor>(std::move(a)));
}
template <typename ExecutionContext, typename F, typename CompletionToken>
inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
template <typename Executor, typename AwaitableExecutor,
BOOST_ASIO_COMPLETION_TOKEN_FOR(
void(std::exception_ptr)) CompletionToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken, void(std::exception_ptr))
co_spawn(const Executor& ex,
awaitable<void, AwaitableExecutor> a, CompletionToken&& token,
typename constraint<
(is_executor<Executor>::value || execution::is_executor<Executor>::value)
&& is_convertible<Executor, AwaitableExecutor>::value
>::type)
{
return async_initiate<CompletionToken, void(std::exception_ptr)>(
detail::initiate_co_spawn<AwaitableExecutor>(AwaitableExecutor(ex)),
token, detail::awaitable_as_function<
void, AwaitableExecutor>(std::move(a)));
}
template <typename ExecutionContext, typename T, typename AwaitableExecutor,
BOOST_ASIO_COMPLETION_TOKEN_FOR(
void(std::exception_ptr, T)) CompletionToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken, void(std::exception_ptr, T))
co_spawn(ExecutionContext& ctx,
awaitable<T, AwaitableExecutor> a, CompletionToken&& token,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value
&& is_convertible<typename ExecutionContext::executor_type,
AwaitableExecutor>::value
>::type)
{
return (co_spawn)(ctx.get_executor(), std::move(a),
std::forward<CompletionToken>(token));
}
template <typename ExecutionContext, typename AwaitableExecutor,
BOOST_ASIO_COMPLETION_TOKEN_FOR(
void(std::exception_ptr)) CompletionToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken, void(std::exception_ptr))
co_spawn(ExecutionContext& ctx,
awaitable<void, AwaitableExecutor> a, CompletionToken&& token,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value
&& is_convertible<typename ExecutionContext::executor_type,
AwaitableExecutor>::value
>::type)
{
return (co_spawn)(ctx.get_executor(), std::move(a),
std::forward<CompletionToken>(token));
}
template <typename Executor, typename F,
BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature<
typename result_of<F()>::type>::type) CompletionToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,
typename detail::awaitable_signature<typename result_of<F()>::type>::type)
co_spawn(const Executor& ex, F&& f, CompletionToken&& token,
typename constraint<
is_executor<Executor>::value || execution::is_executor<Executor>::value
>::type)
{
return async_initiate<CompletionToken,
typename detail::awaitable_signature<typename result_of<F()>::type>::type>(
detail::initiate_co_spawn<
typename result_of<F()>::type::executor_type>(ex),
token, std::forward<F>(f));
}
template <typename ExecutionContext, typename F,
BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature<
typename result_of<F()>::type>::type) CompletionToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,
typename detail::awaitable_signature<typename result_of<F()>::type>::type)
co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token,
typename enable_if<
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value
>::type*)
>::type)
{
return (co_spawn)(ctx.get_executor(), std::forward<F>(f),
std::forward<CompletionToken>(token));

View File

@@ -1,421 +0,0 @@
//
// impl/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 BOOST_ASIO_IMPL_COMPOSE_HPP
#define BOOST_ASIO_IMPL_COMPOSE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/variadic_templates.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/is_executor.hpp>
#include <boost/asio/system_executor.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail
{
template <typename>
struct composed_work;
template <>
struct composed_work<void()>
{
composed_work() BOOST_ASIO_NOEXCEPT
: head_(system_executor())
{
}
void reset()
{
head_.reset();
}
typedef system_executor head_type;
executor_work_guard<system_executor> head_;
};
inline composed_work<void()> make_composed_work()
{
return composed_work<void()>();
}
template <typename Head>
struct composed_work<void(Head)>
{
explicit composed_work(const Head& ex) BOOST_ASIO_NOEXCEPT
: head_(ex)
{
}
void reset()
{
head_.reset();
}
typedef Head head_type;
executor_work_guard<Head> head_;
};
template <typename Head>
inline composed_work<void(Head)> make_composed_work(const Head& head)
{
return composed_work<void(Head)>(head);
}
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Head, typename... Tail>
struct composed_work<void(Head, Tail...)>
{
explicit composed_work(const Head& head,
const Tail&... tail) BOOST_ASIO_NOEXCEPT
: head_(head),
tail_(tail...)
{
}
void reset()
{
head_.reset();
tail_.reset();
}
typedef Head head_type;
executor_work_guard<Head> head_;
composed_work<void(Tail...)> tail_;
};
template <typename Head, typename... Tail>
inline composed_work<void(Head, Tail...)>
make_composed_work(const Head& head, const Tail&... tail)
{
return composed_work<void(Head, Tail...)>(head, tail...);
}
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
#define BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \
template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
struct composed_work<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
{ \
explicit composed_work(const Head& head, \
BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) BOOST_ASIO_NOEXCEPT \
: head_(head), \
tail_(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) \
{ \
} \
\
void reset() \
{ \
head_.reset(); \
tail_.reset(); \
} \
\
typedef Head head_type; \
executor_work_guard<Head> head_; \
composed_work<void(BOOST_ASIO_VARIADIC_TARGS(n))> tail_; \
}; \
\
template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
inline composed_work<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
make_composed_work(const Head& head, BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) \
{ \
return composed_work< \
void(Head, BOOST_ASIO_VARIADIC_TARGS(n))>( \
head, BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)); \
} \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF)
#undef BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Impl, typename Work, typename Handler, typename Signature>
class composed_op;
template <typename Impl, typename Work, typename Handler,
typename R, typename... Args>
class composed_op<Impl, Work, Handler, R(Args...)>
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Impl, typename Work, typename Handler, typename Signature>
class composed_op
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
{
public:
composed_op(BOOST_ASIO_MOVE_ARG(Impl) impl,
BOOST_ASIO_MOVE_ARG(Work) work,
BOOST_ASIO_MOVE_ARG(Handler) handler)
: impl_(BOOST_ASIO_MOVE_CAST(Impl)(impl)),
work_(BOOST_ASIO_MOVE_CAST(Work)(work)),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
invocations_(0)
{
}
#if defined(BOOST_ASIO_HAS_MOVE)
composed_op(composed_op&& other)
: impl_(BOOST_ASIO_MOVE_CAST(Impl)(other.impl_)),
work_(BOOST_ASIO_MOVE_CAST(Work)(other.work_)),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
invocations_(other.invocations_)
{
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
typedef typename associated_executor<Handler,
typename Work::head_type>::type executor_type;
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return (get_associated_executor)(handler_, work_.head_.get_executor());
}
typedef typename associated_allocator<Handler,
std::allocator<void> >::type allocator_type;
allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
{
return (get_associated_allocator)(handler_, std::allocator<void>());
}
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template<typename... T>
void operator()(BOOST_ASIO_MOVE_ARG(T)... t)
{
if (invocations_ < ~unsigned(0))
++invocations_;
impl_(*this, BOOST_ASIO_MOVE_CAST(T)(t)...);
}
void complete(Args... args)
{
this->work_.reset();
this->handler_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
void operator()()
{
if (invocations_ < ~unsigned(0))
++invocations_;
impl_(*this);
}
void complete()
{
this->work_.reset();
this->handler_();
}
#define BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF(n) \
template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
if (invocations_ < ~unsigned(0)) \
++invocations_; \
impl_(*this, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
\
template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
void complete(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
this->work_.reset(); \
this->handler_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF)
#undef BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
//private:
Impl impl_;
Work work_;
Handler handler_;
unsigned invocations_;
};
template <typename Impl, typename Work, typename Handler, typename Signature>
inline void* asio_handler_allocate(std::size_t size,
composed_op<Impl, Work, Handler, Signature>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename Impl, typename Work, typename Handler, typename Signature>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
composed_op<Impl, Work, Handler, Signature>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename Impl, typename Work, typename Handler, typename Signature>
inline bool asio_handler_is_continuation(
composed_op<Impl, Work, Handler, Signature>* this_handler)
{
return this_handler->invocations_ > 1 ? true
: boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename Impl,
typename Work, typename Handler, typename Signature>
inline void asio_handler_invoke(Function& function,
composed_op<Impl, Work, Handler, Signature>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename Impl,
typename Work, typename Handler, typename Signature>
inline void asio_handler_invoke(const Function& function,
composed_op<Impl, Work, Handler, Signature>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Signature>
struct initiate_composed_op
{
template <typename Handler, typename Impl, typename Work>
void operator()(BOOST_ASIO_MOVE_ARG(Handler) handler,
BOOST_ASIO_MOVE_ARG(Impl) impl,
BOOST_ASIO_MOVE_ARG(Work) work) const
{
composed_op<typename decay<Impl>::type, typename decay<Work>::type,
typename decay<Handler>::type, Signature>(
BOOST_ASIO_MOVE_CAST(Impl)(impl), BOOST_ASIO_MOVE_CAST(Work)(work),
BOOST_ASIO_MOVE_CAST(Handler)(handler))();
}
};
template <typename IoObject>
inline typename IoObject::executor_type
get_composed_io_executor(IoObject& io_object)
{
return io_object.get_executor();
}
template <typename Executor>
inline const Executor& get_composed_io_executor(const Executor& ex,
typename enable_if<is_executor<Executor>::value>::type* = 0)
{
return ex;
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename CompletionToken, typename Signature,
typename Implementation, typename... IoObjectsOrExecutors>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
BOOST_ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors)
{
return async_initiate<CompletionToken, Signature>(
detail::initiate_composed_op<Signature>(), token,
BOOST_ASIO_MOVE_CAST(Implementation)(implementation),
detail::make_composed_work(
detail::get_composed_io_executor(
BOOST_ASIO_MOVE_CAST(IoObjectsOrExecutors)(
io_objects_or_executors))...));
}
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename CompletionToken, typename Signature, typename Implementation>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
{
return async_initiate<CompletionToken, Signature>(
detail::initiate_composed_op<Signature>(), token,
BOOST_ASIO_MOVE_CAST(Implementation)(implementation),
detail::make_composed_work());
}
# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \
BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n
# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1))
# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2))
# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3))
# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4))
# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5))
#define BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \
template <typename CompletionToken, typename Signature, \
typename Implementation, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) \
async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, \
BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
return async_initiate<CompletionToken, Signature>( \
detail::initiate_composed_op<Signature>(), token, \
BOOST_ASIO_MOVE_CAST(Implementation)(implementation), \
detail::make_composed_work( \
BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))); \
} \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF)
#undef BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF
#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR
#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1
#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2
#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3
#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4
#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_IMPL_COMPOSE_HPP

View File

@@ -2,7 +2,7 @@
// impl/connect.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -16,15 +16,17 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <algorithm>
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/associator.hpp>
#include <boost/asio/detail/base_from_cancellation_state.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_tracking.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/post.hpp>
@@ -73,9 +75,9 @@ namespace detail
static const bool value =
sizeof(asio_connect_condition_check(
(*static_cast<legacy_connect_condition_helper<T, Iterator>*>(0))(
*static_cast<const boost::system::error_code*>(0),
*static_cast<const Iterator*>(0)))) != 1;
(declval<legacy_connect_condition_helper<T, Iterator> >())(
declval<const boost::system::error_code>(),
declval<const Iterator>()))) != 1;
};
template <typename ConnectCondition, typename Iterator>
@@ -105,8 +107,8 @@ namespace detail
template <typename Protocol, typename Executor, typename EndpointSequence>
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
typename constraint<is_endpoint_sequence<
EndpointSequence>::value>::type)
{
boost::system::error_code ec;
typename Protocol::endpoint result = connect(s, endpoints, ec);
@@ -117,8 +119,8 @@ typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
template <typename Protocol, typename Executor, typename EndpointSequence>
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, boost::system::error_code& ec,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
typename constraint<is_endpoint_sequence<
EndpointSequence>::value>::type)
{
return detail::deref_connect_result<Protocol>(
connect(s, endpoints.begin(), endpoints.end(),
@@ -128,7 +130,7 @@ typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
#if !defined(BOOST_ASIO_NO_DEPRECATED)
template <typename Protocol, typename Executor, typename Iterator>
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
{
boost::system::error_code ec;
Iterator result = connect(s, begin, ec);
@@ -139,7 +141,7 @@ Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
template <typename Protocol, typename Executor, typename Iterator>
inline Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, boost::system::error_code& ec,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
{
return connect(s, begin, Iterator(), detail::default_connect_condition(), ec);
}
@@ -166,8 +168,8 @@ template <typename Protocol, typename Executor,
typename EndpointSequence, typename ConnectCondition>
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
typename constraint<is_endpoint_sequence<
EndpointSequence>::value>::type)
{
boost::system::error_code ec;
typename Protocol::endpoint result = connect(
@@ -181,8 +183,8 @@ template <typename Protocol, typename Executor,
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition,
boost::system::error_code& ec,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
typename constraint<is_endpoint_sequence<
EndpointSequence>::value>::type)
{
return detail::deref_connect_result<Protocol>(
connect(s, endpoints.begin(), endpoints.end(),
@@ -194,7 +196,7 @@ template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition>
Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, ConnectCondition connect_condition,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
{
boost::system::error_code ec;
Iterator result = connect(s, begin, connect_condition, ec);
@@ -207,7 +209,7 @@ template <typename Protocol, typename Executor,
inline Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, ConnectCondition connect_condition,
boost::system::error_code& ec,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
{
return connect(s, begin, Iterator(), connect_condition, ec);
}
@@ -294,14 +296,18 @@ namespace detail
template <typename Protocol, typename Executor, typename EndpointSequence,
typename ConnectCondition, typename RangeConnectHandler>
class range_connect_op : base_from_connect_condition<ConnectCondition>
class range_connect_op
: public base_from_cancellation_state<RangeConnectHandler>,
base_from_connect_condition<ConnectCondition>
{
public:
range_connect_op(basic_socket<Protocol, Executor>& sock,
const EndpointSequence& endpoints,
const ConnectCondition& connect_condition,
RangeConnectHandler& handler)
: base_from_connect_condition<ConnectCondition>(connect_condition),
: base_from_cancellation_state<RangeConnectHandler>(
handler, enable_partial_cancellation()),
base_from_connect_condition<ConnectCondition>(connect_condition),
socket_(sock),
endpoints_(endpoints),
index_(0),
@@ -312,7 +318,8 @@ namespace detail
#if defined(BOOST_ASIO_HAS_MOVE)
range_connect_op(const range_connect_op& other)
: base_from_connect_condition<ConnectCondition>(other),
: base_from_cancellation_state<RangeConnectHandler>(other),
base_from_connect_condition<ConnectCondition>(other),
socket_(other.socket_),
endpoints_(other.endpoints_),
index_(other.index_),
@@ -322,7 +329,10 @@ namespace detail
}
range_connect_op(range_connect_op&& other)
: base_from_connect_condition<ConnectCondition>(other),
: base_from_cancellation_state<RangeConnectHandler>(
BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
RangeConnectHandler>)(other)),
base_from_connect_condition<ConnectCondition>(other),
socket_(other.socket_),
endpoints_(other.endpoints_),
index_(other.index_),
@@ -358,6 +368,7 @@ namespace detail
if (iter != end)
{
socket_.close(ec);
BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
socket_.async_connect(*iter,
BOOST_ASIO_MOVE_CAST(range_connect_op)(*this));
return;
@@ -366,13 +377,14 @@ namespace detail
if (start)
{
ec = boost::asio::error::not_found;
BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
boost::asio::post(socket_.get_executor(),
detail::bind_handler(
BOOST_ASIO_MOVE_CAST(range_connect_op)(*this), ec));
return;
}
default:
/* fall-through */ default:
if (iter == end)
break;
@@ -386,11 +398,18 @@ namespace detail
if (!ec)
break;
if (this->cancelled() != cancellation_type::none)
{
ec = boost::asio::error::operation_aborted;
break;
}
++iter;
++index_;
}
handler_(static_cast<const boost::system::error_code&>(ec),
BOOST_ASIO_MOVE_OR_LVALUE(RangeConnectHandler)(handler_)(
static_cast<const boost::system::error_code&>(ec),
static_cast<const typename Protocol::endpoint&>(
ec || iter == end ? typename Protocol::endpoint() : *iter));
}
@@ -405,22 +424,32 @@ namespace detail
template <typename Protocol, typename Executor, typename EndpointSequence,
typename ConnectCondition, typename RangeConnectHandler>
inline void* asio_handler_allocate(std::size_t size,
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Protocol, typename Executor, typename EndpointSequence,
typename ConnectCondition, typename RangeConnectHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Protocol, typename Executor, typename EndpointSequence,
@@ -436,31 +465,53 @@ namespace detail
template <typename Function, typename Executor, typename Protocol,
typename EndpointSequence, typename ConnectCondition,
typename RangeConnectHandler>
inline void asio_handler_invoke(Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename Executor, typename Protocol,
typename EndpointSequence, typename ConnectCondition,
typename RangeConnectHandler>
inline void asio_handler_invoke(const Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
struct initiate_async_range_connect
template <typename Protocol, typename Executor>
class initiate_async_range_connect
{
template <typename RangeConnectHandler, typename Protocol,
typename Executor, typename EndpointSequence, typename ConnectCondition>
public:
typedef Executor executor_type;
explicit initiate_async_range_connect(basic_socket<Protocol, Executor>& s)
: socket_(s)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return socket_.get_executor();
}
template <typename RangeConnectHandler,
typename EndpointSequence, typename ConnectCondition>
void operator()(BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
basic_socket<Protocol, Executor>* s, const EndpointSequence& endpoints,
const EndpointSequence& endpoints,
const ConnectCondition& connect_condition) const
{
// If you get an error on the following line it means that your
@@ -471,21 +522,28 @@ namespace detail
non_const_lvalue<RangeConnectHandler> handler2(handler);
range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition,
typename decay<RangeConnectHandler>::type>(*s, endpoints,
typename decay<RangeConnectHandler>::type>(socket_, endpoints,
connect_condition, handler2.value)(boost::system::error_code(), 1);
}
private:
basic_socket<Protocol, Executor>& socket_;
};
template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
class iterator_connect_op : base_from_connect_condition<ConnectCondition>
class iterator_connect_op
: public base_from_cancellation_state<IteratorConnectHandler>,
base_from_connect_condition<ConnectCondition>
{
public:
iterator_connect_op(basic_socket<Protocol, Executor>& sock,
const Iterator& begin, const Iterator& end,
const ConnectCondition& connect_condition,
IteratorConnectHandler& handler)
: base_from_connect_condition<ConnectCondition>(connect_condition),
: base_from_cancellation_state<IteratorConnectHandler>(
handler, enable_partial_cancellation()),
base_from_connect_condition<ConnectCondition>(connect_condition),
socket_(sock),
iter_(begin),
end_(end),
@@ -496,7 +554,8 @@ namespace detail
#if defined(BOOST_ASIO_HAS_MOVE)
iterator_connect_op(const iterator_connect_op& other)
: base_from_connect_condition<ConnectCondition>(other),
: base_from_cancellation_state<IteratorConnectHandler>(other),
base_from_connect_condition<ConnectCondition>(other),
socket_(other.socket_),
iter_(other.iter_),
end_(other.end_),
@@ -506,7 +565,10 @@ namespace detail
}
iterator_connect_op(iterator_connect_op&& other)
: base_from_connect_condition<ConnectCondition>(other),
: base_from_cancellation_state<IteratorConnectHandler>(
BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
IteratorConnectHandler>)(other)),
base_from_connect_condition<ConnectCondition>(other),
socket_(other.socket_),
iter_(other.iter_),
end_(other.end_),
@@ -528,6 +590,7 @@ namespace detail
if (iter_ != end_)
{
socket_.close(ec);
BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
socket_.async_connect(*iter_,
BOOST_ASIO_MOVE_CAST(iterator_connect_op)(*this));
return;
@@ -536,13 +599,14 @@ namespace detail
if (start)
{
ec = boost::asio::error::not_found;
BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
boost::asio::post(socket_.get_executor(),
detail::bind_handler(
BOOST_ASIO_MOVE_CAST(iterator_connect_op)(*this), ec));
return;
}
default:
/* fall-through */ default:
if (iter_ == end_)
break;
@@ -556,10 +620,17 @@ namespace detail
if (!ec)
break;
if (this->cancelled() != cancellation_type::none)
{
ec = boost::asio::error::operation_aborted;
break;
}
++iter_;
}
handler_(static_cast<const boost::system::error_code&>(ec),
BOOST_ASIO_MOVE_OR_LVALUE(IteratorConnectHandler)(handler_)(
static_cast<const boost::system::error_code&>(ec),
static_cast<const Iterator&>(iter_));
}
}
@@ -574,22 +645,32 @@ namespace detail
template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline void* asio_handler_allocate(std::size_t size,
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
iterator_connect_op<Protocol, Executor, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
iterator_connect_op<Protocol, Executor, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Protocol, typename Executor, typename Iterator,
@@ -605,32 +686,55 @@ namespace detail
template <typename Function, typename Executor, typename Protocol,
typename Iterator, typename ConnectCondition,
typename IteratorConnectHandler>
inline void asio_handler_invoke(Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
iterator_connect_op<Protocol, Executor, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename Executor, typename Protocol,
typename Iterator, typename ConnectCondition,
typename IteratorConnectHandler>
inline void asio_handler_invoke(const Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
iterator_connect_op<Protocol, Executor, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
struct initiate_async_iterator_connect
template <typename Protocol, typename Executor>
class initiate_async_iterator_connect
{
template <typename IteratorConnectHandler, typename Protocol,
typename Executor, typename Iterator, typename ConnectCondition>
public:
typedef Executor executor_type;
explicit initiate_async_iterator_connect(
basic_socket<Protocol, Executor>& s)
: socket_(s)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return socket_.get_executor();
}
template <typename IteratorConnectHandler,
typename Iterator, typename ConnectCondition>
void operator()(BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
basic_socket<Protocol, Executor>* s, Iterator begin,
Iterator end, const ConnectCondition& connect_condition) const
Iterator begin, Iterator end,
const ConnectCondition& connect_condition) const
{
// If you get an error on the following line it means that your
// handler does not meet the documented type requirements for an
@@ -640,186 +744,213 @@ namespace detail
non_const_lvalue<IteratorConnectHandler> handler2(handler);
iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition,
typename decay<IteratorConnectHandler>::type>(*s, begin, end,
typename decay<IteratorConnectHandler>::type>(socket_, begin, end,
connect_condition, handler2.value)(boost::system::error_code(), 1);
}
private:
basic_socket<Protocol, Executor>& socket_;
};
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename Protocol, typename Executor, typename EndpointSequence,
typename ConnectCondition, typename RangeConnectHandler, typename Allocator>
struct associated_allocator<
detail::range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>, Allocator>
template <template <typename, typename> class Associator,
typename Protocol, typename Executor, typename EndpointSequence,
typename ConnectCondition, typename RangeConnectHandler,
typename DefaultCandidate>
struct associator<Associator,
detail::range_connect_op<Protocol, Executor,
EndpointSequence, ConnectCondition, RangeConnectHandler>,
DefaultCandidate>
: Associator<RangeConnectHandler, DefaultCandidate>
{
typedef typename associated_allocator<
RangeConnectHandler, Allocator>::type type;
static type get(
const detail::range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
static typename Associator<RangeConnectHandler, DefaultCandidate>::type
get(const detail::range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>& h) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<RangeConnectHandler,
Allocator>::get(h.handler_, a);
return Associator<RangeConnectHandler, DefaultCandidate>::get(h.handler_);
}
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<RangeConnectHandler, DefaultCandidate>::type)
get(const detail::range_connect_op<Protocol, Executor,
EndpointSequence, ConnectCondition, RangeConnectHandler>& h,
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<RangeConnectHandler, DefaultCandidate>::get(
h.handler_, c)))
{
return Associator<RangeConnectHandler, DefaultCandidate>::get(
h.handler_, c);
}
};
template <typename Protocol, typename Executor, typename EndpointSequence,
typename ConnectCondition, typename RangeConnectHandler, typename Executor1>
struct associated_executor<
detail::range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>, Executor1>
{
typedef typename associated_executor<
RangeConnectHandler, Executor1>::type type;
static type get(
const detail::range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>& h,
const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
{
return associated_executor<RangeConnectHandler,
Executor1>::get(h.handler_, ex);
}
};
template <typename Protocol, typename Executor, typename Iterator,
template <template <typename, typename> class Associator,
typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler,
typename Allocator>
struct associated_allocator<
typename DefaultCandidate>
struct associator<Associator,
detail::iterator_connect_op<Protocol, Executor,
Iterator, ConnectCondition, IteratorConnectHandler>,
Allocator>
DefaultCandidate>
: Associator<IteratorConnectHandler, DefaultCandidate>
{
typedef typename associated_allocator<
IteratorConnectHandler, Allocator>::type type;
static type get(
const detail::iterator_connect_op<Protocol, Executor,
Iterator, ConnectCondition, IteratorConnectHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
static typename Associator<IteratorConnectHandler, DefaultCandidate>::type
get(const detail::iterator_connect_op<Protocol, Executor, Iterator,
ConnectCondition, IteratorConnectHandler>& h) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<IteratorConnectHandler,
Allocator>::get(h.handler_, a);
return Associator<IteratorConnectHandler, DefaultCandidate>::get(
h.handler_);
}
};
template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler,
typename Executor1>
struct associated_executor<
detail::iterator_connect_op<Protocol, Executor,
Iterator, ConnectCondition, IteratorConnectHandler>,
Executor1>
{
typedef typename associated_executor<
IteratorConnectHandler, Executor1>::type type;
static type get(
const detail::iterator_connect_op<Protocol, Executor,
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<IteratorConnectHandler, DefaultCandidate>::type)
get(const detail::iterator_connect_op<Protocol, Executor,
Iterator, ConnectCondition, IteratorConnectHandler>& h,
const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<IteratorConnectHandler, DefaultCandidate>::get(
h.handler_, c)))
{
return associated_executor<IteratorConnectHandler,
Executor1>::get(h.handler_, ex);
return Associator<IteratorConnectHandler, DefaultCandidate>::get(
h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename Protocol, typename Executor,
typename EndpointSequence, typename RangeConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
template <typename Protocol, typename Executor, typename EndpointSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
typename Protocol::endpoint)) RangeConnectToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(RangeConnectToken,
void (boost::system::error_code, typename Protocol::endpoint))
async_connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints,
BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
BOOST_ASIO_MOVE_ARG(RangeConnectToken) token,
typename constraint<is_endpoint_sequence<
EndpointSequence>::value>::type)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<RangeConnectToken,
void (boost::system::error_code, typename Protocol::endpoint)>(
declval<detail::initiate_async_range_connect<Protocol, Executor> >(),
token, endpoints, declval<detail::default_connect_condition>())))
{
return async_initiate<RangeConnectHandler,
return async_initiate<RangeConnectToken,
void (boost::system::error_code, typename Protocol::endpoint)>(
detail::initiate_async_range_connect(), handler,
&s, endpoints, detail::default_connect_condition());
detail::initiate_async_range_connect<Protocol, Executor>(s),
token, endpoints, detail::default_connect_condition());
}
#if !defined(BOOST_ASIO_NO_DEPRECATED)
template <typename Protocol, typename Executor,
typename Iterator, typename IteratorConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
template <typename Protocol, typename Executor, typename Iterator,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
Iterator)) IteratorConnectToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,
void (boost::system::error_code, Iterator))
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
BOOST_ASIO_MOVE_ARG(IteratorConnectToken) token,
typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<IteratorConnectToken,
void (boost::system::error_code, Iterator)>(
declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),
token, begin, Iterator(),
declval<detail::default_connect_condition>())))
{
return async_initiate<IteratorConnectHandler,
return async_initiate<IteratorConnectToken,
void (boost::system::error_code, Iterator)>(
detail::initiate_async_iterator_connect(), handler,
&s, begin, Iterator(), detail::default_connect_condition());
detail::initiate_async_iterator_connect<Protocol, Executor>(s),
token, begin, Iterator(),
detail::default_connect_condition());
}
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
template <typename Protocol, typename Executor,
typename Iterator, typename IteratorConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
template <typename Protocol, typename Executor, typename Iterator,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
Iterator)) IteratorConnectToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,
void (boost::system::error_code, Iterator))
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,
BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)
BOOST_ASIO_MOVE_ARG(IteratorConnectToken) token)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<IteratorConnectToken,
void (boost::system::error_code, Iterator)>(
declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),
token, begin, end, declval<detail::default_connect_condition>())))
{
return async_initiate<IteratorConnectHandler,
return async_initiate<IteratorConnectToken,
void (boost::system::error_code, Iterator)>(
detail::initiate_async_iterator_connect(), handler,
&s, begin, end, detail::default_connect_condition());
detail::initiate_async_iterator_connect<Protocol, Executor>(s),
token, begin, end, detail::default_connect_condition());
}
template <typename Protocol, typename Executor, typename EndpointSequence,
typename ConnectCondition, typename RangeConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
template <typename Protocol, typename Executor,
typename EndpointSequence, typename ConnectCondition,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
typename Protocol::endpoint)) RangeConnectToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(RangeConnectToken,
void (boost::system::error_code, typename Protocol::endpoint))
async_connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition,
BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
BOOST_ASIO_MOVE_ARG(RangeConnectToken) token,
typename constraint<is_endpoint_sequence<
EndpointSequence>::value>::type)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<RangeConnectToken,
void (boost::system::error_code, typename Protocol::endpoint)>(
declval<detail::initiate_async_range_connect<Protocol, Executor> >(),
token, endpoints, connect_condition)))
{
return async_initiate<RangeConnectHandler,
return async_initiate<RangeConnectToken,
void (boost::system::error_code, typename Protocol::endpoint)>(
detail::initiate_async_range_connect(),
handler, &s, endpoints, connect_condition);
detail::initiate_async_range_connect<Protocol, Executor>(s),
token, endpoints, connect_condition);
}
#if !defined(BOOST_ASIO_NO_DEPRECATED)
template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
Iterator)) IteratorConnectToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,
void (boost::system::error_code, Iterator))
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
ConnectCondition connect_condition,
BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
BOOST_ASIO_MOVE_ARG(IteratorConnectToken) token,
typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<IteratorConnectToken,
void (boost::system::error_code, Iterator)>(
declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),
token, begin, Iterator(), connect_condition)))
{
return async_initiate<IteratorConnectHandler,
return async_initiate<IteratorConnectToken,
void (boost::system::error_code, Iterator)>(
detail::initiate_async_iterator_connect(),
handler, &s, begin, Iterator(), connect_condition);
detail::initiate_async_iterator_connect<Protocol, Executor>(s),
token, begin, Iterator(), connect_condition);
}
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
Iterator)) IteratorConnectToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,
void (boost::system::error_code, Iterator))
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
Iterator end, ConnectCondition connect_condition,
BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)
BOOST_ASIO_MOVE_ARG(IteratorConnectToken) token)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<IteratorConnectToken,
void (boost::system::error_code, Iterator)>(
declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),
token, begin, end, connect_condition)))
{
return async_initiate<IteratorConnectHandler,
return async_initiate<IteratorConnectToken,
void (boost::system::error_code, Iterator)>(
detail::initiate_async_iterator_connect(),
handler, &s, begin, end, connect_condition);
detail::initiate_async_iterator_connect<Protocol, Executor>(s),
token, begin, end, connect_condition);
}
} // namespace asio

View File

@@ -0,0 +1,75 @@
//
// impl/connect_pipe.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2023 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 BOOST_ASIO_IMPL_CONNECT_PIPE_HPP
#define BOOST_ASIO_IMPL_CONNECT_PIPE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#if defined(BOOST_ASIO_HAS_PIPE)
#include <boost/asio/connect_pipe.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
template <typename Executor1, typename Executor2>
void connect_pipe(basic_readable_pipe<Executor1>& read_end,
basic_writable_pipe<Executor2>& write_end)
{
boost::system::error_code ec;
boost::asio::connect_pipe(read_end, write_end, ec);
boost::asio::detail::throw_error(ec, "connect_pipe");
}
template <typename Executor1, typename Executor2>
BOOST_ASIO_SYNC_OP_VOID connect_pipe(basic_readable_pipe<Executor1>& read_end,
basic_writable_pipe<Executor2>& write_end, boost::system::error_code& ec)
{
detail::native_pipe_handle p[2];
detail::create_pipe(p, ec);
if (ec)
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
read_end.assign(p[0], ec);
if (ec)
{
detail::close_pipe(p[0]);
detail::close_pipe(p[1]);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
write_end.assign(p[1], ec);
if (ec)
{
boost::system::error_code temp_ec;
read_end.close(temp_ec);
detail::close_pipe(p[1]);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // defined(BOOST_ASIO_HAS_PIPE)
#endif // BOOST_ASIO_IMPL_CONNECT_PIPE_HPP

View File

@@ -0,0 +1,151 @@
//
// impl/connect_pipe.ipp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2021 Klemens D. Morgenstern
// (klemens dot morgenstern at gmx dot net)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_ASIO_IMPL_CONNECT_PIPE_IPP
#define BOOST_ASIO_IMPL_CONNECT_PIPE_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#if defined(BOOST_ASIO_HAS_PIPE)
#include <boost/asio/connect_pipe.hpp>
#if defined(BOOST_ASIO_HAS_IOCP)
# include <cstdio>
# if _WIN32_WINNT >= 0x601
# include <bcrypt.h>
# if !defined(BOOST_ASIO_NO_DEFAULT_LINKED_LIBS)
# if defined(_MSC_VER)
# pragma comment(lib, "bcrypt.lib")
# endif // defined(_MSC_VER)
# endif // !defined(BOOST_ASIO_NO_DEFAULT_LINKED_LIBS)
# endif // _WIN32_WINNT >= 0x601
#else // defined(BOOST_ASIO_HAS_IOCP)
# include <boost/asio/detail/descriptor_ops.hpp>
#endif // defined(BOOST_ASIO_HAS_IOCP)
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
void create_pipe(native_pipe_handle p[2], boost::system::error_code& ec)
{
#if defined(BOOST_ASIO_HAS_IOCP)
using namespace std; // For sprintf and memcmp.
static long counter1 = 0;
static long counter2 = 0;
long n1 = ::InterlockedIncrement(&counter1);
long n2 = (static_cast<unsigned long>(n1) % 0x10000000) == 0
? ::InterlockedIncrement(&counter2)
: ::InterlockedExchangeAdd(&counter2, 0);
wchar_t pipe_name[128];
#if defined(BOOST_ASIO_HAS_SECURE_RTL)
swprintf_s(
#else // defined(BOOST_ASIO_HAS_SECURE_RTL)
_snwprintf(
#endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
pipe_name, 128,
L"\\\\.\\pipe\\asio-A0812896-741A-484D-AF23-BE51BF620E22-%u-%ld-%ld",
static_cast<unsigned int>(::GetCurrentProcessId()), n1, n2);
p[0] = ::CreateNamedPipeW(pipe_name,
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
0, 1, 8192, 8192, 0, 0);
if (p[0] == INVALID_HANDLE_VALUE)
{
DWORD last_error = ::GetLastError();
ec.assign(last_error, boost::asio::error::get_system_category());
return;
}
p[1] = ::CreateFileW(pipe_name, GENERIC_WRITE, 0,
0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (p[1] == INVALID_HANDLE_VALUE)
{
DWORD last_error = ::GetLastError();
::CloseHandle(p[0]);
ec.assign(last_error, boost::asio::error::get_system_category());
return;
}
# if _WIN32_WINNT >= 0x601
unsigned char nonce[16];
if (::BCryptGenRandom(0, nonce, sizeof(nonce),
BCRYPT_USE_SYSTEM_PREFERRED_RNG) != 0)
{
ec = boost::asio::error::connection_aborted;
::CloseHandle(p[0]);
::CloseHandle(p[1]);
return;
}
DWORD bytes_written = 0;
BOOL ok = ::WriteFile(p[1], nonce, sizeof(nonce), &bytes_written, 0);
if (!ok || bytes_written != sizeof(nonce))
{
ec = boost::asio::error::connection_aborted;
::CloseHandle(p[0]);
::CloseHandle(p[1]);
return;
}
unsigned char nonce_check[sizeof(nonce)];
DWORD bytes_read = 0;
ok = ::ReadFile(p[0], nonce_check, sizeof(nonce), &bytes_read, 0);
if (!ok || bytes_read != sizeof(nonce)
|| memcmp(nonce, nonce_check, sizeof(nonce)) != 0)
{
ec = boost::asio::error::connection_aborted;
::CloseHandle(p[0]);
::CloseHandle(p[1]);
return;
}
#endif // _WIN32_WINNT >= 0x601
boost::asio::error::clear(ec);
#else // defined(BOOST_ASIO_HAS_IOCP)
int result = ::pipe(p);
detail::descriptor_ops::get_last_error(ec, result != 0);
#endif // defined(BOOST_ASIO_HAS_IOCP)
}
void close_pipe(native_pipe_handle p)
{
#if defined(BOOST_ASIO_HAS_IOCP)
::CloseHandle(p);
#else // defined(BOOST_ASIO_HAS_IOCP)
boost::system::error_code ignored_ec;
detail::descriptor_ops::state_type state = 0;
detail::descriptor_ops::close(p, state, ignored_ec);
#endif // defined(BOOST_ASIO_HAS_IOCP)
}
} // namespace detail
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // defined(BOOST_ASIO_HAS_PIPE)
#endif // BOOST_ASIO_IMPL_CONNECT_PIPE_IPP

View File

@@ -0,0 +1,204 @@
//
// impl/consign.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2023 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 BOOST_ASIO_IMPL_CONSIGN_HPP
#define BOOST_ASIO_IMPL_CONSIGN_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/associator.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/utility.hpp>
#include <boost/asio/detail/variadic_templates.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
// Class to adapt a consign_t as a completion handler.
template <typename Handler, typename... Values>
class consign_handler
{
public:
typedef void result_type;
template <typename H>
consign_handler(BOOST_ASIO_MOVE_ARG(H) handler, std::tuple<Values...> values)
: handler_(BOOST_ASIO_MOVE_CAST(H)(handler)),
values_(BOOST_ASIO_MOVE_CAST(std::tuple<Values...>)(values))
{
}
template <typename... Args>
void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
{
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
//private:
Handler handler_;
std::tuple<Values...> values_;
};
template <typename Handler>
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
consign_handler<Handler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Handler>
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
consign_handler<Handler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Handler>
inline bool asio_handler_is_continuation(
consign_handler<Handler>* this_handler)
{
return boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename Handler>
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
consign_handler<Handler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename Handler>
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
consign_handler<Handler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename CompletionToken, typename... Values, typename... Signatures>
struct async_result<
consign_t<CompletionToken, Values...>, Signatures...>
: async_result<CompletionToken, Signatures...>
{
template <typename Initiation>
struct init_wrapper
{
init_wrapper(Initiation init)
: initiation_(BOOST_ASIO_MOVE_CAST(Initiation)(init))
{
}
template <typename Handler, typename... Args>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler,
std::tuple<Values...> values,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
detail::consign_handler<
typename decay<Handler>::type, Values...>(
BOOST_ASIO_MOVE_CAST(Handler)(handler),
BOOST_ASIO_MOVE_CAST(std::tuple<Values...>)(values)),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
Initiation initiation_;
};
template <typename Initiation, typename RawCompletionToken, typename... Args>
static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Signatures...,
(async_initiate<CompletionToken, Signatures...>(
declval<init_wrapper<typename decay<Initiation>::type> >(),
declval<CompletionToken&>(),
declval<std::tuple<Values...> >(),
declval<BOOST_ASIO_MOVE_ARG(Args)>()...)))
initiate(
BOOST_ASIO_MOVE_ARG(Initiation) initiation,
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
return async_initiate<CompletionToken, Signatures...>(
init_wrapper<typename decay<Initiation>::type>(
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.token_,
BOOST_ASIO_MOVE_CAST(std::tuple<Values...>)(token.values_),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
};
template <template <typename, typename> class Associator,
typename Handler, typename... Values, typename DefaultCandidate>
struct associator<Associator,
detail::consign_handler<Handler, Values...>, DefaultCandidate>
: Associator<Handler, DefaultCandidate>
{
static typename Associator<Handler, DefaultCandidate>::type
get(const detail::consign_handler<Handler, Values...>& h) BOOST_ASIO_NOEXCEPT
{
return Associator<Handler, DefaultCandidate>::get(h.handler_);
}
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<Handler, DefaultCandidate>::type)
get(const detail::consign_handler<Handler, Values...>& h,
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
{
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_IMPL_CONSIGN_HPP

View File

@@ -1,93 +0,0 @@
//
// impl/defer.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 BOOST_ASIO_IMPL_DEFER_HPP
#define BOOST_ASIO_IMPL_DEFER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/detail/work_dispatcher.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
struct initiate_defer
{
template <typename CompletionHandler>
void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler) const
{
typedef typename decay<CompletionHandler>::type DecayedHandler;
typename associated_executor<DecayedHandler>::type ex(
(get_associated_executor)(handler));
typename associated_allocator<DecayedHandler>::type alloc(
(get_associated_allocator)(handler));
ex.defer(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
}
template <typename CompletionHandler, typename Executor>
void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
BOOST_ASIO_MOVE_ARG(Executor) ex) const
{
typedef typename decay<CompletionHandler>::type DecayedHandler;
typename associated_allocator<DecayedHandler>::type alloc(
(get_associated_allocator)(handler));
ex.defer(detail::work_dispatcher<DecayedHandler>(
BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);
}
};
} // namespace detail
template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
BOOST_ASIO_MOVE_ARG(CompletionToken) token)
{
return async_initiate<CompletionToken, void()>(
detail::initiate_defer(), token);
}
template <typename Executor, typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_executor<Executor>::value>::type*)
{
return async_initiate<CompletionToken, void()>(
detail::initiate_defer(), token, ex);
}
template <typename ExecutionContext, typename CompletionToken>
inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_convertible<
ExecutionContext&, execution_context&>::value>::type*)
{
return (defer)(ctx.get_executor(),
BOOST_ASIO_MOVE_CAST(CompletionToken)(token));
}
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_IMPL_DEFER_HPP

View File

@@ -0,0 +1,158 @@
//
// impl/deferred.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2023 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 BOOST_ASIO_IMPL_DEFERRED_HPP
#define BOOST_ASIO_IMPL_DEFERRED_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
#if !defined(GENERATING_DOCUMENTATION)
template <typename Signature>
class async_result<deferred_t, Signature>
{
public:
template <typename Initiation, typename... InitArgs>
static deferred_async_operation<Signature, Initiation, InitArgs...>
initiate(BOOST_ASIO_MOVE_ARG(Initiation) initiation,
deferred_t, BOOST_ASIO_MOVE_ARG(InitArgs)... args)
{
return deferred_async_operation<
Signature, Initiation, InitArgs...>(
deferred_init_tag{},
BOOST_ASIO_MOVE_CAST(Initiation)(initiation),
BOOST_ASIO_MOVE_CAST(InitArgs)(args)...);
}
};
template <typename... Signatures>
class async_result<deferred_t, Signatures...>
{
public:
template <typename Initiation, typename... InitArgs>
static deferred_async_operation<
deferred_signatures<Signatures...>, Initiation, InitArgs...>
initiate(BOOST_ASIO_MOVE_ARG(Initiation) initiation,
deferred_t, BOOST_ASIO_MOVE_ARG(InitArgs)... args)
{
return deferred_async_operation<
deferred_signatures<Signatures...>, Initiation, InitArgs...>(
deferred_init_tag{},
BOOST_ASIO_MOVE_CAST(Initiation)(initiation),
BOOST_ASIO_MOVE_CAST(InitArgs)(args)...);
}
};
template <typename Function, typename Signature>
class async_result<deferred_function<Function>, Signature>
{
public:
template <typename Initiation, typename... InitArgs>
static auto initiate(BOOST_ASIO_MOVE_ARG(Initiation) initiation,
deferred_function<Function> token,
BOOST_ASIO_MOVE_ARG(InitArgs)... init_args)
-> decltype(
deferred_sequence<
deferred_async_operation<
Signature, Initiation, InitArgs...>,
Function>(deferred_init_tag{},
deferred_async_operation<
Signature, Initiation, InitArgs...>(
deferred_init_tag{},
BOOST_ASIO_MOVE_CAST(Initiation)(initiation),
BOOST_ASIO_MOVE_CAST(InitArgs)(init_args)...),
BOOST_ASIO_MOVE_CAST(Function)(token.function_)))
{
return deferred_sequence<
deferred_async_operation<
Signature, Initiation, InitArgs...>,
Function>(deferred_init_tag{},
deferred_async_operation<
Signature, Initiation, InitArgs...>(
deferred_init_tag{},
BOOST_ASIO_MOVE_CAST(Initiation)(initiation),
BOOST_ASIO_MOVE_CAST(InitArgs)(init_args)...),
BOOST_ASIO_MOVE_CAST(Function)(token.function_));
}
};
template <typename Function, typename... Signatures>
class async_result<deferred_function<Function>, Signatures...>
{
public:
template <typename Initiation, typename... InitArgs>
static auto initiate(BOOST_ASIO_MOVE_ARG(Initiation) initiation,
deferred_function<Function> token,
BOOST_ASIO_MOVE_ARG(InitArgs)... init_args)
-> decltype(
deferred_sequence<
deferred_async_operation<
deferred_signatures<Signatures...>, Initiation, InitArgs...>,
Function>(deferred_init_tag{},
deferred_async_operation<
deferred_signatures<Signatures...>, Initiation, InitArgs...>(
deferred_init_tag{},
BOOST_ASIO_MOVE_CAST(Initiation)(initiation),
BOOST_ASIO_MOVE_CAST(InitArgs)(init_args)...),
BOOST_ASIO_MOVE_CAST(Function)(token.function_)))
{
return deferred_sequence<
deferred_async_operation<
deferred_signatures<Signatures...>, Initiation, InitArgs...>,
Function>(deferred_init_tag{},
deferred_async_operation<
deferred_signatures<Signatures...>, Initiation, InitArgs...>(
deferred_init_tag{},
BOOST_ASIO_MOVE_CAST(Initiation)(initiation),
BOOST_ASIO_MOVE_CAST(InitArgs)(init_args)...),
BOOST_ASIO_MOVE_CAST(Function)(token.function_));
}
};
template <template <typename, typename> class Associator,
typename Handler, typename Tail, typename DefaultCandidate>
struct associator<Associator,
detail::deferred_sequence_handler<Handler, Tail>,
DefaultCandidate>
: Associator<Handler, DefaultCandidate>
{
static typename Associator<Handler, DefaultCandidate>::type
get(const detail::deferred_sequence_handler<Handler, Tail>& h)
BOOST_ASIO_NOEXCEPT
{
return Associator<Handler, DefaultCandidate>::get(h.handler_);
}
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<Handler, DefaultCandidate>::type)
get(const detail::deferred_sequence_handler<Handler, Tail>& h,
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
{
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_IMPL_DEFERRED_HPP

View File

@@ -2,7 +2,7 @@
// impl/detached.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)

View File

@@ -1,93 +0,0 @@
//
// impl/dispatch.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 BOOST_ASIO_IMPL_DISPATCH_HPP
#define BOOST_ASIO_IMPL_DISPATCH_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/detail/work_dispatcher.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
struct initiate_dispatch
{
template <typename CompletionHandler>
void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler) const
{
typedef typename decay<CompletionHandler>::type DecayedHandler;
typename associated_executor<DecayedHandler>::type ex(
(get_associated_executor)(handler));
typename associated_allocator<DecayedHandler>::type alloc(
(get_associated_allocator)(handler));
ex.dispatch(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
}
template <typename CompletionHandler, typename Executor>
void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
BOOST_ASIO_MOVE_ARG(Executor) ex) const
{
typedef typename decay<CompletionHandler>::type DecayedHandler;
typename associated_allocator<DecayedHandler>::type alloc(
(get_associated_allocator)(handler));
ex.dispatch(detail::work_dispatcher<DecayedHandler>(
BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);
}
};
} // namespace detail
template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
BOOST_ASIO_MOVE_ARG(CompletionToken) token)
{
return async_initiate<CompletionToken, void()>(
detail::initiate_dispatch(), token);
}
template <typename Executor, typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_executor<Executor>::value>::type*)
{
return async_initiate<CompletionToken, void()>(
detail::initiate_dispatch(), token, ex);
}
template <typename ExecutionContext, typename CompletionToken>
inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_convertible<
ExecutionContext&, execution_context&>::value>::type*)
{
return (dispatch)(ctx.get_executor(),
BOOST_ASIO_MOVE_CAST(CompletionToken)(token));
}
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_IMPL_DISPATCH_HPP

View File

@@ -2,7 +2,7 @@
// impl/error.ipp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)

View File

@@ -2,7 +2,7 @@
// impl/execution_context.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)

View File

@@ -2,7 +2,7 @@
// impl/execution_context.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)

View File

@@ -2,7 +2,7 @@
// impl/executor.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -16,11 +16,12 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
#include <boost/asio/detail/atomic_count.hpp>
#include <boost/asio/detail/executor_function.hpp>
#include <boost/asio/detail/global.hpp>
#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/recycling_allocator.hpp>
#include <boost/asio/executor.hpp>
#include <boost/asio/system_executor.hpp>
@@ -31,99 +32,7 @@ namespace asio {
#if !defined(GENERATING_DOCUMENTATION)
#if defined(BOOST_ASIO_HAS_MOVE)
// Lightweight, move-only function object wrapper.
class executor::function
{
public:
template <typename F, typename Alloc>
explicit function(F f, const Alloc& a)
{
// Allocate and construct an operation to wrap the function.
typedef detail::executor_function<F, Alloc> func_type;
typename func_type::ptr p = {
detail::addressof(a), func_type::ptr::allocate(a), 0 };
func_ = new (p.v) func_type(BOOST_ASIO_MOVE_CAST(F)(f), a);
p.v = 0;
}
function(function&& other) BOOST_ASIO_NOEXCEPT
: func_(other.func_)
{
other.func_ = 0;
}
~function()
{
if (func_)
func_->destroy();
}
void operator()()
{
if (func_)
{
detail::executor_function_base* func = func_;
func_ = 0;
func->complete();
}
}
private:
detail::executor_function_base* func_;
};
#else // defined(BOOST_ASIO_HAS_MOVE)
// Not so lightweight, copyable function object wrapper.
class executor::function
{
public:
template <typename F, typename Alloc>
explicit function(const F& f, const Alloc&)
: impl_(new impl<F>(f))
{
}
void operator()()
{
impl_->invoke_(impl_.get());
}
private:
// Base class for polymorphic function implementations.
struct impl_base
{
void (*invoke_)(impl_base*);
};
// Polymorphic function implementation.
template <typename F>
struct impl : impl_base
{
impl(const F& f)
: function_(f)
{
invoke_ = &function::invoke<F>;
}
F function_;
};
// Helper to invoke a function.
template <typename F>
static void invoke(impl_base* i)
{
static_cast<impl<F>*>(i)->function_();
}
detail::shared_ptr<impl_base> impl_;
};
#endif // defined(BOOST_ASIO_HAS_MOVE)
// Default polymorphic allocator implementation.
// Default polymorphic executor implementation.
template <typename Executor, typename Allocator>
class executor::impl
: public executor::impl_base
@@ -149,13 +58,13 @@ public:
impl_base* clone() const BOOST_ASIO_NOEXCEPT
{
++ref_count_;
detail::ref_count_up(ref_count_);
return const_cast<impl_base*>(static_cast<const impl_base*>(this));
}
void destroy() BOOST_ASIO_NOEXCEPT
{
if (--ref_count_ == 0)
if (detail::ref_count_down(ref_count_))
{
allocator_type alloc(allocator_);
impl* p = this;
@@ -247,7 +156,7 @@ private:
};
};
// Polymorphic allocator specialisation for system_executor.
// Polymorphic executor specialisation for system_executor.
template <typename Allocator>
class executor::impl<system_executor, Allocator>
: public executor::impl_base
@@ -290,17 +199,20 @@ public:
void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
{
executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f),
std::allocator<void>());
}
void post(BOOST_ASIO_MOVE_ARG(function) f)
{
executor_.post(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
executor_.post(BOOST_ASIO_MOVE_CAST(function)(f),
std::allocator<void>());
}
void defer(BOOST_ASIO_MOVE_ARG(function) f)
{
executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f),
std::allocator<void>());
}
type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
@@ -325,7 +237,6 @@ public:
private:
system_executor executor_;
Allocator allocator_;
};
template <typename Executor>
@@ -386,4 +297,6 @@ const Executor* executor::target() const BOOST_ASIO_NOEXCEPT
#include <boost/asio/detail/pop_options.hpp>
#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
#endif // BOOST_ASIO_IMPL_EXECUTOR_HPP

View File

@@ -2,7 +2,7 @@
// impl/executor.ipp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -16,6 +16,9 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
#include <boost/asio/executor.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -37,4 +40,6 @@ const char* bad_executor::what() const BOOST_ASIO_NOEXCEPT_OR_NOTHROW
#include <boost/asio/detail/pop_options.hpp>
#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
#endif // BOOST_ASIO_IMPL_EXECUTOR_IPP

View File

@@ -2,7 +2,7 @@
// impl/handler_alloc_hook.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -16,6 +16,7 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/thread_context.hpp>
#include <boost/asio/detail/thread_info_base.hpp>
#include <boost/asio/handler_alloc_hook.hpp>
@@ -25,24 +26,33 @@
namespace boost {
namespace asio {
void* asio_handler_allocate(std::size_t size, ...)
asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size, ...)
{
#if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
#if defined(BOOST_ASIO_NO_DEPRECATED)
(void)size;
return asio_handler_allocate_is_no_longer_used();
#elif !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
return detail::thread_info_base::allocate(
detail::thread_context::thread_call_stack::top(), size);
detail::thread_context::top_of_thread_call_stack(), size);
#else // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
return ::operator new(size);
return aligned_new(BOOST_ASIO_DEFAULT_ALIGN, size);
#endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
}
void asio_handler_deallocate(void* pointer, std::size_t size, ...)
asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size, ...)
{
#if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
#if defined(BOOST_ASIO_NO_DEPRECATED)
(void)pointer;
(void)size;
return asio_handler_deallocate_is_no_longer_used();
#elif !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
detail::thread_info_base::deallocate(
detail::thread_context::thread_call_stack::top(), pointer, size);
detail::thread_context::top_of_thread_call_stack(), pointer, size);
#else // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
(void)size;
::operator delete(pointer);
aligned_delete(pointer);
#endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
}

View File

@@ -2,7 +2,7 @@
// impl/io_context.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -20,18 +20,17 @@
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/recycling_allocator.hpp>
#include <boost/asio/detail/service_registry.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/push_options.hpp>
#if !defined(GENERATING_DOCUMENTATION)
namespace boost {
namespace asio {
#if !defined(GENERATING_DOCUMENTATION)
template <typename Service>
inline Service& use_service(io_context& ioc)
{
@@ -49,24 +48,8 @@ inline detail::io_context_impl& use_service<detail::io_context_impl>(
return ioc.impl_;
}
} // namespace asio
} // namespace boost
#endif // !defined(GENERATING_DOCUMENTATION)
#include <boost/asio/detail/pop_options.hpp>
#if defined(BOOST_ASIO_HAS_IOCP)
# include <boost/asio/detail/win_iocp_io_context.hpp>
#else
# include <boost/asio/detail/scheduler.hpp>
#endif
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
inline io_context::executor_type
io_context::get_executor() BOOST_ASIO_NOEXCEPT
{
@@ -157,10 +140,10 @@ struct io_context::initiate_dispatch
{
// Allocate and construct an operation to wrap the handler.
typedef detail::completion_handler<
typename decay<LegacyCompletionHandler>::type> op;
typename decay<LegacyCompletionHandler>::type, executor_type> op;
typename op::ptr p = { detail::addressof(handler2.value),
op::ptr::allocate(handler2.value), 0 };
p.p = new (p.v) op(handler2.value);
p.p = new (p.v) op(handler2.value, self->get_executor());
BOOST_ASIO_HANDLER_CREATION((*self, *p.p,
"io_context", self, 0, "dispatch"));
@@ -172,8 +155,11 @@ struct io_context::initiate_dispatch
};
template <typename LegacyCompletionHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ())
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ())
io_context::dispatch(BOOST_ASIO_MOVE_ARG(LegacyCompletionHandler) handler)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<LegacyCompletionHandler, void ()>(
declval<initiate_dispatch>(), handler, this)))
{
return async_initiate<LegacyCompletionHandler, void ()>(
initiate_dispatch(), handler, this);
@@ -197,10 +183,10 @@ struct io_context::initiate_post
// Allocate and construct an operation to wrap the handler.
typedef detail::completion_handler<
typename decay<LegacyCompletionHandler>::type> op;
typename decay<LegacyCompletionHandler>::type, executor_type> op;
typename op::ptr p = { detail::addressof(handler2.value),
op::ptr::allocate(handler2.value), 0 };
p.p = new (p.v) op(handler2.value);
p.p = new (p.v) op(handler2.value, self->get_executor());
BOOST_ASIO_HANDLER_CREATION((*self, *p.p,
"io_context", self, 0, "post"));
@@ -211,8 +197,11 @@ struct io_context::initiate_post
};
template <typename LegacyCompletionHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ())
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ())
io_context::post(BOOST_ASIO_MOVE_ARG(LegacyCompletionHandler) handler)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<LegacyCompletionHandler, void ()>(
declval<initiate_post>(), handler, this)))
{
return async_initiate<LegacyCompletionHandler, void ()>(
initiate_post(), handler, this);
@@ -231,32 +220,138 @@ io_context::wrap(Handler handler)
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
inline io_context&
io_context::executor_type::context() const BOOST_ASIO_NOEXCEPT
template <typename Allocator, uintptr_t Bits>
io_context::basic_executor_type<Allocator, Bits>&
io_context::basic_executor_type<Allocator, Bits>::operator=(
const basic_executor_type& other) BOOST_ASIO_NOEXCEPT
{
return io_context_;
if (this != &other)
{
static_cast<Allocator&>(*this) = static_cast<const Allocator&>(other);
io_context* old_io_context = context_ptr();
target_ = other.target_;
if (Bits & outstanding_work_tracked)
{
if (context_ptr())
context_ptr()->impl_.work_started();
if (old_io_context)
old_io_context->impl_.work_finished();
}
}
return *this;
}
inline void
io_context::executor_type::on_work_started() const BOOST_ASIO_NOEXCEPT
#if defined(BOOST_ASIO_HAS_MOVE)
template <typename Allocator, uintptr_t Bits>
io_context::basic_executor_type<Allocator, Bits>&
io_context::basic_executor_type<Allocator, Bits>::operator=(
basic_executor_type&& other) BOOST_ASIO_NOEXCEPT
{
io_context_.impl_.work_started();
if (this != &other)
{
static_cast<Allocator&>(*this) = static_cast<Allocator&&>(other);
io_context* old_io_context = context_ptr();
target_ = other.target_;
if (Bits & outstanding_work_tracked)
{
other.target_ = 0;
if (old_io_context)
old_io_context->impl_.work_finished();
}
}
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
template <typename Allocator, uintptr_t Bits>
inline bool io_context::basic_executor_type<Allocator,
Bits>::running_in_this_thread() const BOOST_ASIO_NOEXCEPT
{
return context_ptr()->impl_.can_dispatch();
}
inline void
io_context::executor_type::on_work_finished() const BOOST_ASIO_NOEXCEPT
template <typename Allocator, uintptr_t Bits>
template <typename Function>
void io_context::basic_executor_type<Allocator, Bits>::execute(
BOOST_ASIO_MOVE_ARG(Function) f) const
{
io_context_.impl_.work_finished();
typedef typename decay<Function>::type function_type;
// Invoke immediately if the blocking.possibly property is enabled and we are
// already inside the thread pool.
if ((bits() & blocking_never) == 0 && context_ptr()->impl_.can_dispatch())
{
// Make a local, non-const copy of the function.
function_type tmp(BOOST_ASIO_MOVE_CAST(Function)(f));
#if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) \
&& !defined(BOOST_ASIO_NO_EXCEPTIONS)
try
{
#endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
// && !defined(BOOST_ASIO_NO_EXCEPTIONS)
detail::fenced_block b(detail::fenced_block::full);
boost_asio_handler_invoke_helpers::invoke(tmp, tmp);
return;
#if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) \
&& !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
catch (...)
{
context_ptr()->impl_.capture_current_exception();
return;
}
#endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
// && !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator, detail::operation> op;
typename op::ptr p = {
detail::addressof(static_cast<const Allocator&>(*this)),
op::ptr::allocate(static_cast<const Allocator&>(*this)), 0 };
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f),
static_cast<const Allocator&>(*this));
BOOST_ASIO_HANDLER_CREATION((*context_ptr(), *p.p,
"io_context", context_ptr(), 0, "execute"));
context_ptr()->impl_.post_immediate_completion(p.p,
(bits() & relationship_continuation) != 0);
p.v = p.p = 0;
}
template <typename Function, typename Allocator>
void io_context::executor_type::dispatch(
BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
template <typename Allocator, uintptr_t Bits>
inline io_context& io_context::basic_executor_type<
Allocator, Bits>::context() const BOOST_ASIO_NOEXCEPT
{
return *context_ptr();
}
template <typename Allocator, uintptr_t Bits>
inline void io_context::basic_executor_type<Allocator,
Bits>::on_work_started() const BOOST_ASIO_NOEXCEPT
{
context_ptr()->impl_.work_started();
}
template <typename Allocator, uintptr_t Bits>
inline void io_context::basic_executor_type<Allocator,
Bits>::on_work_finished() const BOOST_ASIO_NOEXCEPT
{
context_ptr()->impl_.work_finished();
}
template <typename Allocator, uintptr_t Bits>
template <typename Function, typename OtherAllocator>
void io_context::basic_executor_type<Allocator, Bits>::dispatch(
BOOST_ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const
{
typedef typename decay<Function>::type function_type;
// Invoke immediately if we are already inside the thread pool.
if (io_context_.impl_.can_dispatch())
if (context_ptr()->impl_.can_dispatch())
{
// Make a local, non-const copy of the function.
function_type tmp(BOOST_ASIO_MOVE_CAST(Function)(f));
@@ -267,58 +362,58 @@ void io_context::executor_type::dispatch(
}
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator, detail::operation> op;
typedef detail::executor_op<function_type,
OtherAllocator, detail::operation> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
BOOST_ASIO_HANDLER_CREATION((this->context(), *p.p,
"io_context", &this->context(), 0, "dispatch"));
BOOST_ASIO_HANDLER_CREATION((*context_ptr(), *p.p,
"io_context", context_ptr(), 0, "dispatch"));
io_context_.impl_.post_immediate_completion(p.p, false);
context_ptr()->impl_.post_immediate_completion(p.p, false);
p.v = p.p = 0;
}
template <typename Function, typename Allocator>
void io_context::executor_type::post(
BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
template <typename Allocator, uintptr_t Bits>
template <typename Function, typename OtherAllocator>
void io_context::basic_executor_type<Allocator, Bits>::post(
BOOST_ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const
{
typedef typename decay<Function>::type function_type;
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator, detail::operation> op;
typedef detail::executor_op<function_type,
OtherAllocator, detail::operation> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
BOOST_ASIO_HANDLER_CREATION((this->context(), *p.p,
"io_context", &this->context(), 0, "post"));
BOOST_ASIO_HANDLER_CREATION((*context_ptr(), *p.p,
"io_context", context_ptr(), 0, "post"));
io_context_.impl_.post_immediate_completion(p.p, false);
context_ptr()->impl_.post_immediate_completion(p.p, false);
p.v = p.p = 0;
}
template <typename Function, typename Allocator>
void io_context::executor_type::defer(
BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
template <typename Allocator, uintptr_t Bits>
template <typename Function, typename OtherAllocator>
void io_context::basic_executor_type<Allocator, Bits>::defer(
BOOST_ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const
{
typedef typename decay<Function>::type function_type;
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator, detail::operation> op;
typedef detail::executor_op<function_type,
OtherAllocator, detail::operation> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
BOOST_ASIO_HANDLER_CREATION((this->context(), *p.p,
"io_context", &this->context(), 0, "defer"));
BOOST_ASIO_HANDLER_CREATION((*context_ptr(), *p.p,
"io_context", context_ptr(), 0, "defer"));
io_context_.impl_.post_immediate_completion(p.p, true);
context_ptr()->impl_.post_immediate_completion(p.p, true);
p.v = p.p = 0;
}
inline bool
io_context::executor_type::running_in_this_thread() const BOOST_ASIO_NOEXCEPT
{
return io_context_.impl_.can_dispatch();
}
#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
#if !defined(BOOST_ASIO_NO_DEPRECATED)
inline io_context::work::work(boost::asio::io_context& io_context)

View File

@@ -2,7 +2,7 @@
// impl/io_context.ipp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -55,6 +55,7 @@ io_context::impl_type& io_context::add_impl(io_context::impl_type* impl)
io_context::~io_context()
{
shutdown();
}
io_context::count_type io_context::run()

View File

@@ -0,0 +1,51 @@
//
// impl/multiple_exceptions.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2023 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 BOOST_ASIO_IMPL_MULTIPLE_EXCEPTIONS_IPP
#define BOOST_ASIO_IMPL_MULTIPLE_EXCEPTIONS_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/multiple_exceptions.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
#if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
multiple_exceptions::multiple_exceptions(
std::exception_ptr first) BOOST_ASIO_NOEXCEPT
: first_(BOOST_ASIO_MOVE_CAST(std::exception_ptr)(first))
{
}
const char* multiple_exceptions::what() const BOOST_ASIO_NOEXCEPT_OR_NOTHROW
{
return "multiple exceptions";
}
std::exception_ptr multiple_exceptions::first_exception() const
{
return first_;
}
#endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_IMPL_MULTIPLE_EXCEPTIONS_IPP

View File

@@ -1,93 +0,0 @@
//
// impl/post.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 BOOST_ASIO_IMPL_POST_HPP
#define BOOST_ASIO_IMPL_POST_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/detail/work_dispatcher.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
struct initiate_post
{
template <typename CompletionHandler>
void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler) const
{
typedef typename decay<CompletionHandler>::type DecayedHandler;
typename associated_executor<DecayedHandler>::type ex(
(get_associated_executor)(handler));
typename associated_allocator<DecayedHandler>::type alloc(
(get_associated_allocator)(handler));
ex.post(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
}
template <typename CompletionHandler, typename Executor>
void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
BOOST_ASIO_MOVE_ARG(Executor) ex) const
{
typedef typename decay<CompletionHandler>::type DecayedHandler;
typename associated_allocator<DecayedHandler>::type alloc(
(get_associated_allocator)(handler));
ex.post(detail::work_dispatcher<DecayedHandler>(
BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);
}
};
} // namespace detail
template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
BOOST_ASIO_MOVE_ARG(CompletionToken) token)
{
return async_initiate<CompletionToken, void()>(
detail::initiate_post(), token);
}
template <typename Executor, typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_executor<Executor>::value>::type*)
{
return async_initiate<CompletionToken, void()>(
detail::initiate_post(), token, ex);
}
template <typename ExecutionContext, typename CompletionToken>
inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_convertible<
ExecutionContext&, execution_context&>::value>::type*)
{
return (post)(ctx.get_executor(),
BOOST_ASIO_MOVE_CAST(CompletionToken)(token));
}
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_IMPL_POST_HPP

View File

@@ -0,0 +1,227 @@
//
// impl/prepend.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2023 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 BOOST_ASIO_IMPL_PREPEND_HPP
#define BOOST_ASIO_IMPL_PREPEND_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/associator.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/utility.hpp>
#include <boost/asio/detail/variadic_templates.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
// Class to adapt a prepend_t as a completion handler.
template <typename Handler, typename... Values>
class prepend_handler
{
public:
typedef void result_type;
template <typename H>
prepend_handler(BOOST_ASIO_MOVE_ARG(H) handler, std::tuple<Values...> values)
: handler_(BOOST_ASIO_MOVE_CAST(H)(handler)),
values_(BOOST_ASIO_MOVE_CAST(std::tuple<Values...>)(values))
{
}
template <typename... Args>
void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
{
this->invoke(
index_sequence_for<Values...>{},
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
template <std::size_t... I, typename... Args>
void invoke(index_sequence<I...>, BOOST_ASIO_MOVE_ARG(Args)... args)
{
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
BOOST_ASIO_MOVE_CAST(Values)(std::get<I>(values_))...,
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
//private:
Handler handler_;
std::tuple<Values...> values_;
};
template <typename Handler>
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
prepend_handler<Handler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Handler>
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
prepend_handler<Handler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Handler>
inline bool asio_handler_is_continuation(
prepend_handler<Handler>* this_handler)
{
return boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename Handler>
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
prepend_handler<Handler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename Handler>
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
prepend_handler<Handler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Signature, typename... Values>
struct prepend_signature;
template <typename R, typename... Args, typename... Values>
struct prepend_signature<R(Args...), Values...>
{
typedef R type(Values..., typename decay<Args>::type...);
};
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename CompletionToken, typename... Values, typename Signature>
struct async_result<
prepend_t<CompletionToken, Values...>, Signature>
: async_result<CompletionToken,
typename detail::prepend_signature<
Signature, Values...>::type>
{
typedef typename detail::prepend_signature<
Signature, Values...>::type signature;
template <typename Initiation>
struct init_wrapper
{
init_wrapper(Initiation init)
: initiation_(BOOST_ASIO_MOVE_CAST(Initiation)(init))
{
}
template <typename Handler, typename... Args>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler,
std::tuple<Values...> values,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
detail::prepend_handler<
typename decay<Handler>::type, Values...>(
BOOST_ASIO_MOVE_CAST(Handler)(handler),
BOOST_ASIO_MOVE_CAST(std::tuple<Values...>)(values)),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
Initiation initiation_;
};
template <typename Initiation, typename RawCompletionToken, typename... Args>
static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, signature,
(async_initiate<CompletionToken, signature>(
declval<init_wrapper<typename decay<Initiation>::type> >(),
declval<CompletionToken&>(),
declval<std::tuple<Values...> >(),
declval<BOOST_ASIO_MOVE_ARG(Args)>()...)))
initiate(
BOOST_ASIO_MOVE_ARG(Initiation) initiation,
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
return async_initiate<CompletionToken, signature>(
init_wrapper<typename decay<Initiation>::type>(
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.token_,
BOOST_ASIO_MOVE_CAST(std::tuple<Values...>)(token.values_),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
};
template <template <typename, typename> class Associator,
typename Handler, typename... Values, typename DefaultCandidate>
struct associator<Associator,
detail::prepend_handler<Handler, Values...>, DefaultCandidate>
: Associator<Handler, DefaultCandidate>
{
static typename Associator<Handler, DefaultCandidate>::type
get(const detail::prepend_handler<Handler, Values...>& h) BOOST_ASIO_NOEXCEPT
{
return Associator<Handler, DefaultCandidate>::get(h.handler_);
}
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<Handler, DefaultCandidate>::type)
get(const detail::prepend_handler<Handler, Values...>& h,
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
{
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_IMPL_PREPEND_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
// impl/read_at.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -16,11 +16,10 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <algorithm>
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/associator.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/completion_condition.hpp>
#include <boost/asio/detail/array_fwd.hpp>
#include <boost/asio/detail/base_from_cancellation_state.hpp>
#include <boost/asio/detail/base_from_completion_cond.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/consuming_buffers.hpp>
@@ -28,6 +27,7 @@
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_tracking.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
@@ -61,7 +61,7 @@ namespace detail
else
break;
}
return tmp.total_consumed();;
return tmp.total_consumed();
}
} // namespace detail
@@ -176,14 +176,16 @@ namespace detail
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
class read_at_op
: detail::base_from_completion_cond<CompletionCondition>
: public base_from_cancellation_state<ReadHandler>,
base_from_completion_cond<CompletionCondition>
{
public:
read_at_op(AsyncRandomAccessReadDevice& device,
uint64_t offset, const MutableBufferSequence& buffers,
CompletionCondition& completion_condition, ReadHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
: base_from_cancellation_state<ReadHandler>(
handler, enable_partial_cancellation()),
base_from_completion_cond<CompletionCondition>(completion_condition),
device_(device),
offset_(offset),
buffers_(buffers),
@@ -194,7 +196,8 @@ namespace detail
#if defined(BOOST_ASIO_HAS_MOVE)
read_at_op(const read_at_op& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
: base_from_cancellation_state<ReadHandler>(other),
base_from_completion_cond<CompletionCondition>(other),
device_(other.device_),
offset_(other.offset_),
buffers_(other.buffers_),
@@ -204,8 +207,11 @@ namespace detail
}
read_at_op(read_at_op&& other)
: detail::base_from_completion_cond<CompletionCondition>(
BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
: base_from_cancellation_state<ReadHandler>(
BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
ReadHandler>)(other)),
base_from_completion_cond<CompletionCondition>(
BOOST_ASIO_MOVE_CAST(base_from_completion_cond<
CompletionCondition>)(other)),
device_(other.device_),
offset_(other.offset_),
@@ -216,7 +222,7 @@ namespace detail
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
void operator()(const boost::system::error_code& ec,
void operator()(boost::system::error_code ec,
std::size_t bytes_transferred, int start = 0)
{
std::size_t max_size;
@@ -224,19 +230,31 @@ namespace detail
{
case 1:
max_size = this->check_for_completion(ec, buffers_.total_consumed());
do
for (;;)
{
device_.async_read_some_at(
offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
{
BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));
device_.async_read_some_at(
offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
}
return; default:
buffers_.consume(bytes_transferred);
if ((!ec && bytes_transferred == 0) || buffers_.empty())
break;
max_size = this->check_for_completion(ec, buffers_.total_consumed());
} while (max_size > 0);
if (max_size == 0)
break;
if (this->cancelled() != cancellation_type::none)
{
ec = boost::asio::error::operation_aborted;
break;
}
}
handler_(ec, buffers_.total_consumed());
BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(
static_cast<const boost::system::error_code&>(ec),
static_cast<const std::size_t&>(buffers_.total_consumed()));
}
}
@@ -254,23 +272,33 @@ namespace detail
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename AsyncRandomAccessReadDevice,
@@ -288,29 +316,37 @@ namespace detail
template <typename Function, typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline void start_read_at_buffer_sequence_op(AsyncRandomAccessReadDevice& d,
inline void start_read_at_op(AsyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
const MutableBufferIterator&, CompletionCondition& completion_condition,
ReadHandler& handler)
@@ -321,13 +357,26 @@ namespace detail
boost::system::error_code(), 0, 1);
}
struct initiate_async_read_at_buffer_sequence
template <typename AsyncRandomAccessReadDevice>
class initiate_async_read_at
{
template <typename ReadHandler, typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename CompletionCondition>
public:
typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;
explicit initiate_async_read_at(AsyncRandomAccessReadDevice& device)
: device_(device)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return device_.get_executor();
}
template <typename ReadHandler, typename MutableBufferSequence,
typename CompletionCondition>
void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
AsyncRandomAccessReadDevice* d, uint64_t offset,
const MutableBufferSequence& buffers,
uint64_t offset, const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
{
// If you get an error on the following line it means that your handler
@@ -336,84 +385,93 @@ namespace detail
non_const_lvalue<ReadHandler> handler2(handler);
non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
start_read_at_buffer_sequence_op(*d, offset, buffers,
start_read_at_op(device_, offset, buffers,
boost::asio::buffer_sequence_begin(buffers),
completion_cond2.value, handler2.value);
}
private:
AsyncRandomAccessReadDevice& device_;
};
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler, typename Allocator>
struct associated_allocator<
template <template <typename, typename> class Associator,
typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
typename MutableBufferIterator, typename CompletionCondition,
typename ReadHandler, typename DefaultCandidate>
struct associator<Associator,
detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>,
Allocator>
MutableBufferIterator, CompletionCondition, ReadHandler>,
DefaultCandidate>
: Associator<ReadHandler, DefaultCandidate>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(
const detail::read_at_op<AsyncRandomAccessReadDevice,
MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
static typename Associator<ReadHandler, DefaultCandidate>::type
get(const detail::read_at_op<AsyncRandomAccessReadDevice,
MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
}
};
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler, typename Executor>
struct associated_executor<
detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>,
Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(
const detail::read_at_op<AsyncRandomAccessReadDevice,
MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<ReadHandler, DefaultCandidate>::type)
get(const detail::read_at_op<AsyncRandomAccessReadDevice,
MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>& h,
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
typename CompletionCondition, typename ReadHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename CompletionCondition,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) ReadToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
void (boost::system::error_code, std::size_t))
async_read_at(AsyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
CompletionCondition completion_condition,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
BOOST_ASIO_MOVE_ARG(ReadToken) token)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<ReadToken,
void (boost::system::error_code, std::size_t)>(
declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice> >(),
token, offset, buffers,
BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition))))
{
return async_initiate<ReadHandler,
return async_initiate<ReadToken,
void (boost::system::error_code, std::size_t)>(
detail::initiate_async_read_at_buffer_sequence(), handler, &d, offset,
buffers, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d),
token, offset, buffers,
BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
typename ReadHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) ReadToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
void (boost::system::error_code, std::size_t))
async_read_at(AsyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
BOOST_ASIO_MOVE_ARG(ReadToken) token)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<ReadToken,
void (boost::system::error_code, std::size_t)>(
declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice> >(),
token, offset, buffers, transfer_all())))
{
return async_initiate<ReadHandler,
return async_initiate<ReadToken,
void (boost::system::error_code, std::size_t)>(
detail::initiate_async_read_at_buffer_sequence(),
handler, &d, offset, buffers, transfer_all());
detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d),
token, offset, buffers, transfer_all());
}
#if !defined(BOOST_ASIO_NO_EXTENSIONS)
@@ -424,14 +482,16 @@ namespace detail
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler>
class read_at_streambuf_op
: detail::base_from_completion_cond<CompletionCondition>
: public base_from_cancellation_state<ReadHandler>,
base_from_completion_cond<CompletionCondition>
{
public:
read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
uint64_t offset, basic_streambuf<Allocator>& streambuf,
CompletionCondition& completion_condition, ReadHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
: base_from_cancellation_state<ReadHandler>(
handler, enable_partial_cancellation()),
base_from_completion_cond<CompletionCondition>(completion_condition),
device_(device),
offset_(offset),
streambuf_(streambuf),
@@ -443,7 +503,8 @@ namespace detail
#if defined(BOOST_ASIO_HAS_MOVE)
read_at_streambuf_op(const read_at_streambuf_op& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
: base_from_cancellation_state<ReadHandler>(other),
base_from_completion_cond<CompletionCondition>(other),
device_(other.device_),
offset_(other.offset_),
streambuf_(other.streambuf_),
@@ -454,8 +515,11 @@ namespace detail
}
read_at_streambuf_op(read_at_streambuf_op&& other)
: detail::base_from_completion_cond<CompletionCondition>(
BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
: base_from_cancellation_state<ReadHandler>(
BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
ReadHandler>)(other)),
base_from_completion_cond<CompletionCondition>(
BOOST_ASIO_MOVE_CAST(base_from_completion_cond<
CompletionCondition>)(other)),
device_(other.device_),
offset_(other.offset_),
@@ -467,7 +531,7 @@ namespace detail
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
void operator()(const boost::system::error_code& ec,
void operator()(boost::system::error_code ec,
std::size_t bytes_transferred, int start = 0)
{
std::size_t max_size, bytes_available;
@@ -478,9 +542,12 @@ namespace detail
bytes_available = read_size_helper(streambuf_, max_size);
for (;;)
{
device_.async_read_some_at(offset_ + total_transferred_,
streambuf_.prepare(bytes_available),
BOOST_ASIO_MOVE_CAST(read_at_streambuf_op)(*this));
{
BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));
device_.async_read_some_at(offset_ + total_transferred_,
streambuf_.prepare(bytes_available),
BOOST_ASIO_MOVE_CAST(read_at_streambuf_op)(*this));
}
return; default:
total_transferred_ += bytes_transferred;
streambuf_.commit(bytes_transferred);
@@ -488,9 +555,16 @@ namespace detail
bytes_available = read_size_helper(streambuf_, max_size);
if ((!ec && bytes_transferred == 0) || bytes_available == 0)
break;
if (this->cancelled() != cancellation_type::none)
{
ec = boost::asio::error::operation_aborted;
break;
}
}
handler_(ec, static_cast<const std::size_t&>(total_transferred_));
BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(
static_cast<const boost::system::error_code&>(ec),
static_cast<const std::size_t&>(total_transferred_));
}
}
@@ -505,22 +579,32 @@ namespace detail
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
CompletionCondition, ReadHandler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename AsyncRandomAccessReadDevice, typename Allocator,
@@ -536,31 +620,53 @@ namespace detail
template <typename Function, typename AsyncRandomAccessReadDevice,
typename Allocator, typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename AsyncRandomAccessReadDevice,
typename Allocator, typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
struct initiate_async_read_at_streambuf
template <typename AsyncRandomAccessReadDevice>
class initiate_async_read_at_streambuf
{
template <typename ReadHandler, typename AsyncRandomAccessReadDevice,
public:
typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;
explicit initiate_async_read_at_streambuf(
AsyncRandomAccessReadDevice& device)
: device_(device)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return device_.get_executor();
}
template <typename ReadHandler,
typename Allocator, typename CompletionCondition>
void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
AsyncRandomAccessReadDevice* d, uint64_t offset,
basic_streambuf<Allocator>* b,
uint64_t offset, basic_streambuf<Allocator>* b,
BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
{
// If you get an error on the following line it means that your handler
@@ -571,79 +677,92 @@ namespace detail
non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
CompletionCondition, typename decay<ReadHandler>::type>(
*d, offset, *b, completion_cond2.value, handler2.value)(
device_, offset, *b, completion_cond2.value, handler2.value)(
boost::system::error_code(), 0, 1);
}
private:
AsyncRandomAccessReadDevice& device_;
};
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler, typename Allocator1>
struct associated_allocator<
detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
Allocator, CompletionCondition, ReadHandler>,
Allocator1>
{
typedef typename associated_allocator<ReadHandler, Allocator1>::type type;
static type get(
const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
Allocator, CompletionCondition, ReadHandler>& h,
const Allocator1& a = Allocator1()) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);
}
};
template <typename AsyncRandomAccessReadDevice, typename Executor,
typename CompletionCondition, typename ReadHandler, typename Executor1>
struct associated_executor<
template <template <typename, typename> class Associator,
typename AsyncRandomAccessReadDevice, typename Executor,
typename CompletionCondition, typename ReadHandler,
typename DefaultCandidate>
struct associator<Associator,
detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
Executor, CompletionCondition, ReadHandler>,
Executor1>
DefaultCandidate>
: Associator<ReadHandler, DefaultCandidate>
{
typedef typename associated_executor<ReadHandler, Executor1>::type type;
static type get(
const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
Executor, CompletionCondition, ReadHandler>& h,
const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
static typename Associator<ReadHandler, DefaultCandidate>::type
get(const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
Executor, CompletionCondition, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
{
return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);
return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
}
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<ReadHandler, DefaultCandidate>::type)
get(const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
Executor, CompletionCondition, ReadHandler>& h,
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
{
return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
template <typename AsyncRandomAccessReadDevice,
typename Allocator, typename CompletionCondition,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) ReadToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
void (boost::system::error_code, std::size_t))
async_read_at(AsyncRandomAccessReadDevice& d,
uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
BOOST_ASIO_MOVE_ARG(ReadToken) token)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<ReadToken,
void (boost::system::error_code, std::size_t)>(
declval<detail::initiate_async_read_at_streambuf<
AsyncRandomAccessReadDevice> >(),
token, offset, &b,
BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition))))
{
return async_initiate<ReadHandler,
return async_initiate<ReadToken,
void (boost::system::error_code, std::size_t)>(
detail::initiate_async_read_at_streambuf(), handler, &d, offset,
&b, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),
token, offset, &b,
BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename ReadHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) ReadToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
void (boost::system::error_code, std::size_t))
async_read_at(AsyncRandomAccessReadDevice& d,
uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
BOOST_ASIO_MOVE_ARG(ReadToken) token)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<ReadToken,
void (boost::system::error_code, std::size_t)>(
declval<detail::initiate_async_read_at_streambuf<
AsyncRandomAccessReadDevice> >(),
token, offset, &b, transfer_all())))
{
return async_initiate<ReadHandler,
return async_initiate<ReadToken,
void (boost::system::error_code, std::size_t)>(
detail::initiate_async_read_at_streambuf(),
handler, &d, offset, &b, transfer_all());
detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),
token, offset, &b, transfer_all());
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
// impl/redirect_error.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -16,8 +16,7 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associator.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
@@ -56,7 +55,7 @@ public:
void operator()()
{
handler_();
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)();
}
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
@@ -67,7 +66,8 @@ public:
>::type
operator()(BOOST_ASIO_MOVE_ARG(Arg) arg, BOOST_ASIO_MOVE_ARG(Args)... args)
{
handler_(BOOST_ASIO_MOVE_CAST(Arg)(arg),
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
BOOST_ASIO_MOVE_CAST(Arg)(arg),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
@@ -76,7 +76,8 @@ public:
BOOST_ASIO_MOVE_ARG(Args)... args)
{
ec_ = ec;
handler_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
@@ -87,13 +88,14 @@ public:
>::type
operator()(BOOST_ASIO_MOVE_ARG(Arg) arg)
{
handler_(BOOST_ASIO_MOVE_CAST(Arg)(arg));
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
BOOST_ASIO_MOVE_CAST(Arg)(arg));
}
void operator()(const boost::system::error_code& ec)
{
ec_ = ec;
handler_();
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)();
}
#define BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \
@@ -103,7 +105,8 @@ public:
>::type \
operator()(BOOST_ASIO_MOVE_ARG(Arg) arg, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
handler_(BOOST_ASIO_MOVE_CAST(Arg)(arg), \
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)( \
BOOST_ASIO_MOVE_CAST(Arg)(arg), \
BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
\
@@ -112,7 +115,8 @@ public:
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
ec_ = ec; \
handler_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)( \
BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF)
@@ -126,19 +130,29 @@ public:
};
template <typename Handler>
inline void* asio_handler_allocate(std::size_t size,
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
redirect_error_handler<Handler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Handler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
redirect_error_handler<Handler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Handler>
@@ -150,19 +164,27 @@ inline bool asio_handler_is_continuation(
}
template <typename Function, typename Handler>
inline void asio_handler_invoke(Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
redirect_error_handler<Handler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename Handler>
inline void asio_handler_invoke(const Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
redirect_error_handler<Handler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Signature>
@@ -185,6 +207,78 @@ struct redirect_error_signature<R(const boost::system::error_code&, Args...)>
typedef R type(Args...);
};
# if defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
template <typename R, typename... Args>
struct redirect_error_signature<R(boost::system::error_code, Args...) &>
{
typedef R type(Args...) &;
};
template <typename R, typename... Args>
struct redirect_error_signature<R(const boost::system::error_code&, Args...) &>
{
typedef R type(Args...) &;
};
template <typename R, typename... Args>
struct redirect_error_signature<R(boost::system::error_code, Args...) &&>
{
typedef R type(Args...) &&;
};
template <typename R, typename... Args>
struct redirect_error_signature<R(const boost::system::error_code&, Args...) &&>
{
typedef R type(Args...) &&;
};
# if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
template <typename R, typename... Args>
struct redirect_error_signature<
R(boost::system::error_code, Args...) noexcept>
{
typedef R type(Args...) & noexcept;
};
template <typename R, typename... Args>
struct redirect_error_signature<
R(const boost::system::error_code&, Args...) noexcept>
{
typedef R type(Args...) & noexcept;
};
template <typename R, typename... Args>
struct redirect_error_signature<
R(boost::system::error_code, Args...) & noexcept>
{
typedef R type(Args...) & noexcept;
};
template <typename R, typename... Args>
struct redirect_error_signature<
R(const boost::system::error_code&, Args...) & noexcept>
{
typedef R type(Args...) & noexcept;
};
template <typename R, typename... Args>
struct redirect_error_signature<
R(boost::system::error_code, Args...) && noexcept>
{
typedef R type(Args...) && noexcept;
};
template <typename R, typename... Args>
struct redirect_error_signature<
R(const boost::system::error_code&, Args...) && noexcept>
{
typedef R type(Args...) && noexcept;
};
# endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
# endif // defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename R>
@@ -217,6 +311,161 @@ struct redirect_error_signature<R(const boost::system::error_code&)>
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF)
#undef BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF
# if defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
template <typename R>
struct redirect_error_signature<R(boost::system::error_code) &>
{
typedef R type() &;
};
template <typename R>
struct redirect_error_signature<R(const boost::system::error_code&) &>
{
typedef R type() &;
};
template <typename R>
struct redirect_error_signature<R(boost::system::error_code) &&>
{
typedef R type() &&;
};
template <typename R>
struct redirect_error_signature<R(const boost::system::error_code&) &&>
{
typedef R type() &&;
};
#define BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \
template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
struct redirect_error_signature< \
R(boost::system::error_code, BOOST_ASIO_VARIADIC_TARGS(n)) &> \
{ \
typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)) &; \
}; \
\
template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
struct redirect_error_signature< \
R(const boost::system::error_code&, BOOST_ASIO_VARIADIC_TARGS(n)) &> \
{ \
typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)) &; \
}; \
\
template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
struct redirect_error_signature< \
R(boost::system::error_code, BOOST_ASIO_VARIADIC_TARGS(n)) &&> \
{ \
typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)) &&; \
}; \
\
template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
struct redirect_error_signature< \
R(const boost::system::error_code&, BOOST_ASIO_VARIADIC_TARGS(n)) &&> \
{ \
typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)) &&; \
}; \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF)
#undef BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF
# if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
template <typename R>
struct redirect_error_signature<
R(boost::system::error_code) noexcept>
{
typedef R type() noexcept;
};
template <typename R>
struct redirect_error_signature<
R(const boost::system::error_code&) noexcept>
{
typedef R type() noexcept;
};
template <typename R>
struct redirect_error_signature<
R(boost::system::error_code) & noexcept>
{
typedef R type() & noexcept;
};
template <typename R>
struct redirect_error_signature<
R(const boost::system::error_code&) & noexcept>
{
typedef R type() & noexcept;
};
template <typename R>
struct redirect_error_signature<
R(boost::system::error_code) && noexcept>
{
typedef R type() && noexcept;
};
template <typename R>
struct redirect_error_signature<
R(const boost::system::error_code&) && noexcept>
{
typedef R type() && noexcept;
};
#define BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \
template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
struct redirect_error_signature< \
R(boost::system::error_code, BOOST_ASIO_VARIADIC_TARGS(n)) noexcept> \
{ \
typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)) noexcept; \
}; \
\
template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
struct redirect_error_signature< \
R(const boost::system::error_code&, \
BOOST_ASIO_VARIADIC_TARGS(n)) noexcept> \
{ \
typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)) noexcept; \
}; \
\
template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
struct redirect_error_signature< \
R(boost::system::error_code, \
BOOST_ASIO_VARIADIC_TARGS(n)) & noexcept> \
{ \
typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)) & noexcept; \
}; \
\
template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
struct redirect_error_signature< \
R(const boost::system::error_code&, \
BOOST_ASIO_VARIADIC_TARGS(n)) & noexcept> \
{ \
typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)) & noexcept; \
}; \
\
template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
struct redirect_error_signature< \
R(boost::system::error_code, \
BOOST_ASIO_VARIADIC_TARGS(n)) && noexcept> \
{ \
typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)) && noexcept; \
}; \
\
template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
struct redirect_error_signature< \
R(const boost::system::error_code&, \
BOOST_ASIO_VARIADIC_TARGS(n)) && noexcept> \
{ \
typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)) && noexcept; \
}; \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF)
#undef BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF
# endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
# endif // defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
} // namespace detail
@@ -225,29 +474,26 @@ struct redirect_error_signature<R(const boost::system::error_code&)>
template <typename CompletionToken, typename Signature>
struct async_result<redirect_error_t<CompletionToken>, Signature>
: async_result<CompletionToken,
typename detail::redirect_error_signature<Signature>::type>
{
typedef typename async_result<CompletionToken,
typename detail::redirect_error_signature<Signature>::type>
::return_type return_type;
template <typename Initiation>
struct init_wrapper
{
template <typename Init>
init_wrapper(boost::system::error_code& ec, BOOST_ASIO_MOVE_ARG(Init) init)
: ec_(ec),
initiation_(BOOST_ASIO_MOVE_CAST(Init)(init))
explicit init_wrapper(boost::system::error_code& ec)
: ec_(ec)
{
}
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Handler, typename... Args>
template <typename Handler, typename Initiation, typename... Args>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler,
BOOST_ASIO_MOVE_ARG(Args)... args)
BOOST_ASIO_MOVE_ARG(Initiation) initiation,
BOOST_ASIO_MOVE_ARG(Args)... args) const
{
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)(
detail::redirect_error_handler<
typename decay<Handler>::type>(
ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
@@ -256,23 +502,26 @@ struct async_result<redirect_error_t<CompletionToken>, Signature>
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Handler>
template <typename Handler, typename Initiation>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler)
BOOST_ASIO_MOVE_ARG(Handler) handler,
BOOST_ASIO_MOVE_ARG(Initiation) initiation) const
{
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)(
detail::redirect_error_handler<
typename decay<Handler>::type>(
ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
}
#define BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \
template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
template <typename Handler, typename Initiation, \
BOOST_ASIO_VARIADIC_TPARAMS(n)> \
void operator()( \
BOOST_ASIO_MOVE_ARG(Handler) handler, \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
BOOST_ASIO_MOVE_ARG(Initiation) initiation, \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
{ \
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( \
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)( \
detail::redirect_error_handler< \
typename decay<Handler>::type>( \
ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
@@ -285,51 +534,67 @@ struct async_result<redirect_error_t<CompletionToken>, Signature>
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
boost::system::error_code& ec_;
Initiation initiation_;
};
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Initiation, typename RawCompletionToken, typename... Args>
static return_type initiate(
static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken,
typename detail::redirect_error_signature<Signature>::type,
(async_initiate<CompletionToken,
typename detail::redirect_error_signature<Signature>::type>(
declval<init_wrapper>(), declval<CompletionToken&>(),
declval<Initiation>(), declval<BOOST_ASIO_MOVE_ARG(Args)>()...)))
initiate(
BOOST_ASIO_MOVE_ARG(Initiation) initiation,
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
return async_initiate<CompletionToken,
typename detail::redirect_error_signature<Signature>::type>(
init_wrapper<typename decay<Initiation>::type>(
token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.token_, BOOST_ASIO_MOVE_CAST(Args)(args)...);
init_wrapper(token.ec_), token.token_,
BOOST_ASIO_MOVE_CAST(Initiation)(initiation),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Initiation, typename RawCompletionToken>
static return_type initiate(
static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken,
typename detail::redirect_error_signature<Signature>::type,
(async_initiate<CompletionToken,
typename detail::redirect_error_signature<Signature>::type>(
declval<init_wrapper>(), declval<CompletionToken&>(),
declval<Initiation>())))
initiate(
BOOST_ASIO_MOVE_ARG(Initiation) initiation,
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token)
{
return async_initiate<CompletionToken,
typename detail::redirect_error_signature<Signature>::type>(
init_wrapper<typename decay<Initiation>::type>(
token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.token_);
init_wrapper(token.ec_), token.token_,
BOOST_ASIO_MOVE_CAST(Initiation)(initiation));
}
#define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \
template <typename Initiation, typename RawCompletionToken, \
BOOST_ASIO_VARIADIC_TPARAMS(n)> \
static return_type initiate( \
static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, \
typename detail::redirect_error_signature<Signature>::type, \
(async_initiate<CompletionToken, \
typename detail::redirect_error_signature<Signature>::type>( \
declval<init_wrapper>(), declval<CompletionToken&>(), \
declval<Initiation>(), BOOST_ASIO_VARIADIC_DECLVAL(n)))) \
initiate( \
BOOST_ASIO_MOVE_ARG(Initiation) initiation, \
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
return async_initiate<CompletionToken, \
typename detail::redirect_error_signature<Signature>::type>( \
init_wrapper<typename decay<Initiation>::type>( \
token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), \
token.token_, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
init_wrapper(token.ec_), token.token_, \
BOOST_ASIO_MOVE_CAST(Initiation)(initiation), \
BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF)
@@ -338,29 +603,26 @@ struct async_result<redirect_error_t<CompletionToken>, Signature>
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
};
template <typename Handler, typename Executor>
struct associated_executor<detail::redirect_error_handler<Handler>, Executor>
template <template <typename, typename> class Associator,
typename Handler, typename DefaultCandidate>
struct associator<Associator,
detail::redirect_error_handler<Handler>, DefaultCandidate>
: Associator<Handler, DefaultCandidate>
{
typedef typename associated_executor<Handler, Executor>::type type;
static type get(
const detail::redirect_error_handler<Handler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
static typename Associator<Handler, DefaultCandidate>::type
get(const detail::redirect_error_handler<Handler>& h) BOOST_ASIO_NOEXCEPT
{
return associated_executor<Handler, Executor>::get(h.handler_, ex);
return Associator<Handler, DefaultCandidate>::get(h.handler_);
}
};
template <typename Handler, typename Allocator>
struct associated_allocator<detail::redirect_error_handler<Handler>, Allocator>
{
typedef typename associated_allocator<Handler, Allocator>::type type;
static type get(
const detail::redirect_error_handler<Handler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<Handler, DefaultCandidate>::type)
get(const detail::redirect_error_handler<Handler>& h,
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
{
return associated_allocator<Handler, Allocator>::get(h.handler_, a);
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
}
};

View File

@@ -2,7 +2,7 @@
// impl/serial_port_base.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying

View File

@@ -2,7 +2,7 @@
// impl/serial_port_base.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
// impl/src.hpp
// ~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -19,11 +19,16 @@
# error Do not compile Asio library source with BOOST_ASIO_HEADER_ONLY defined
#endif
#include <boost/asio/impl/any_completion_executor.ipp>
#include <boost/asio/impl/any_io_executor.ipp>
#include <boost/asio/impl/cancellation_signal.ipp>
#include <boost/asio/impl/connect_pipe.ipp>
#include <boost/asio/impl/error.ipp>
#include <boost/asio/impl/execution_context.ipp>
#include <boost/asio/impl/executor.ipp>
#include <boost/asio/impl/handler_alloc_hook.ipp>
#include <boost/asio/impl/io_context.ipp>
#include <boost/asio/impl/multiple_exceptions.ipp>
#include <boost/asio/impl/serial_port_base.ipp>
#include <boost/asio/impl/system_context.ipp>
#include <boost/asio/impl/thread_pool.ipp>
@@ -33,15 +38,19 @@
#include <boost/asio/detail/impl/epoll_reactor.ipp>
#include <boost/asio/detail/impl/eventfd_select_interrupter.ipp>
#include <boost/asio/detail/impl/handler_tracking.ipp>
#include <boost/asio/detail/impl/io_uring_descriptor_service.ipp>
#include <boost/asio/detail/impl/io_uring_file_service.ipp>
#include <boost/asio/detail/impl/io_uring_socket_service_base.ipp>
#include <boost/asio/detail/impl/io_uring_service.ipp>
#include <boost/asio/detail/impl/kqueue_reactor.ipp>
#include <boost/asio/detail/impl/null_event.ipp>
#include <boost/asio/detail/impl/pipe_select_interrupter.ipp>
#include <boost/asio/detail/impl/posix_event.ipp>
#include <boost/asio/detail/impl/posix_mutex.ipp>
#include <boost/asio/detail/impl/posix_serial_port_service.ipp>
#include <boost/asio/detail/impl/posix_thread.ipp>
#include <boost/asio/detail/impl/posix_tss_ptr.ipp>
#include <boost/asio/detail/impl/reactive_descriptor_service.ipp>
#include <boost/asio/detail/impl/reactive_serial_port_service.ipp>
#include <boost/asio/detail/impl/reactive_socket_service_base.ipp>
#include <boost/asio/detail/impl/resolver_service_base.ipp>
#include <boost/asio/detail/impl/scheduler.ipp>
@@ -52,9 +61,11 @@
#include <boost/asio/detail/impl/socket_select_interrupter.ipp>
#include <boost/asio/detail/impl/strand_executor_service.ipp>
#include <boost/asio/detail/impl/strand_service.ipp>
#include <boost/asio/detail/impl/thread_context.ipp>
#include <boost/asio/detail/impl/throw_error.ipp>
#include <boost/asio/detail/impl/timer_queue_ptime.ipp>
#include <boost/asio/detail/impl/timer_queue_set.ipp>
#include <boost/asio/detail/impl/win_iocp_file_service.ipp>
#include <boost/asio/detail/impl/win_iocp_handle_service.ipp>
#include <boost/asio/detail/impl/win_iocp_io_context.ipp>
#include <boost/asio/detail/impl/win_iocp_serial_port_service.ipp>
@@ -68,6 +79,9 @@
#include <boost/asio/detail/impl/winrt_ssocket_service_base.ipp>
#include <boost/asio/detail/impl/winrt_timer_scheduler.ipp>
#include <boost/asio/detail/impl/winsock_init.ipp>
#include <boost/asio/execution/impl/bad_executor.ipp>
#include <boost/asio/execution/impl/receiver_invocation_error.ipp>
#include <boost/asio/experimental/impl/channel_error.ipp>
#include <boost/asio/generic/detail/impl/endpoint.ipp>
#include <boost/asio/ip/impl/address.ipp>
#include <boost/asio/ip/impl/address_v4.ipp>

View File

@@ -2,7 +2,7 @@
// impl/system_context.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)

View File

@@ -2,7 +2,7 @@
// impl/system_context.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -29,8 +29,19 @@ struct system_context::thread_function
void operator()()
{
boost::system::error_code ec;
scheduler_->run(ec);
#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
try
{
#endif// !defined(BOOST_ASIO_NO_EXCEPTIONS)
boost::system::error_code ec;
scheduler_->run(ec);
#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
catch (...)
{
std::terminate();
}
#endif// !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
};
@@ -40,8 +51,9 @@ system_context::system_context()
scheduler_.work_started();
thread_function f = { &scheduler_ };
std::size_t num_threads = detail::thread::hardware_concurrency() * 2;
threads_.create_threads(f, num_threads ? num_threads : 2);
num_threads_ = detail::thread::hardware_concurrency() * 2;
num_threads_ = num_threads_ ? num_threads_ : 2;
threads_.create_threads(f, num_threads_);
}
system_context::~system_context()

View File

@@ -2,7 +2,7 @@
// impl/system_executor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -17,7 +17,6 @@
#include <boost/asio/detail/executor_op.hpp>
#include <boost/asio/detail/global.hpp>
#include <boost/asio/detail/recycling_allocator.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/system_context.hpp>
@@ -26,29 +25,128 @@
namespace boost {
namespace asio {
inline system_context& system_executor::context() const BOOST_ASIO_NOEXCEPT
template <typename Blocking, typename Relationship, typename Allocator>
inline system_context&
basic_system_executor<Blocking, Relationship, Allocator>::query(
execution::context_t) BOOST_ASIO_NOEXCEPT
{
return detail::global<system_context>();
}
template <typename Function, typename Allocator>
void system_executor::dispatch(
BOOST_ASIO_MOVE_ARG(Function) f, const Allocator&) const
template <typename Blocking, typename Relationship, typename Allocator>
inline std::size_t
basic_system_executor<Blocking, Relationship, Allocator>::query(
execution::occupancy_t) const BOOST_ASIO_NOEXCEPT
{
return detail::global<system_context>().num_threads_;
}
template <typename Blocking, typename Relationship, typename Allocator>
template <typename Function>
inline void
basic_system_executor<Blocking, Relationship, Allocator>::do_execute(
BOOST_ASIO_MOVE_ARG(Function) f, execution::blocking_t::possibly_t) const
{
// Obtain a non-const instance of the function.
detail::non_const_lvalue<Function> f2(f);
#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
try
{
#endif// !defined(BOOST_ASIO_NO_EXCEPTIONS)
detail::fenced_block b(detail::fenced_block::full);
boost_asio_handler_invoke_helpers::invoke(f2.value, f2.value);
#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
catch (...)
{
std::terminate();
}
#endif// !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
template <typename Blocking, typename Relationship, typename Allocator>
template <typename Function>
inline void
basic_system_executor<Blocking, Relationship, Allocator>::do_execute(
BOOST_ASIO_MOVE_ARG(Function) f, execution::blocking_t::always_t) const
{
// Obtain a non-const instance of the function.
detail::non_const_lvalue<Function> f2(f);
#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
try
{
#endif// !defined(BOOST_ASIO_NO_EXCEPTIONS)
detail::fenced_block b(detail::fenced_block::full);
boost_asio_handler_invoke_helpers::invoke(f2.value, f2.value);
#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
catch (...)
{
std::terminate();
}
#endif// !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
template <typename Blocking, typename Relationship, typename Allocator>
template <typename Function>
void basic_system_executor<Blocking, Relationship, Allocator>::do_execute(
BOOST_ASIO_MOVE_ARG(Function) f, execution::blocking_t::never_t) const
{
system_context& ctx = detail::global<system_context>();
// Allocate and construct an operation to wrap the function.
typedef typename decay<Function>::type function_type;
typedef detail::executor_op<function_type, Allocator> op;
typename op::ptr p = { detail::addressof(allocator_),
op::ptr::allocate(allocator_), 0 };
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), allocator_);
if (is_same<Relationship, execution::relationship_t::continuation_t>::value)
{
BOOST_ASIO_HANDLER_CREATION((ctx, *p.p,
"system_executor", &ctx, 0, "execute(blk=never,rel=cont)"));
}
else
{
BOOST_ASIO_HANDLER_CREATION((ctx, *p.p,
"system_executor", &ctx, 0, "execute(blk=never,rel=fork)"));
}
ctx.scheduler_.post_immediate_completion(p.p,
is_same<Relationship, execution::relationship_t::continuation_t>::value);
p.v = p.p = 0;
}
#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
template <typename Blocking, typename Relationship, typename Allocator>
inline system_context& basic_system_executor<
Blocking, Relationship, Allocator>::context() const BOOST_ASIO_NOEXCEPT
{
return detail::global<system_context>();
}
template <typename Blocking, typename Relationship, typename Allocator>
template <typename Function, typename OtherAllocator>
void basic_system_executor<Blocking, Relationship, Allocator>::dispatch(
BOOST_ASIO_MOVE_ARG(Function) f, const OtherAllocator&) const
{
typename decay<Function>::type tmp(BOOST_ASIO_MOVE_CAST(Function)(f));
boost_asio_handler_invoke_helpers::invoke(tmp, tmp);
}
template <typename Function, typename Allocator>
void system_executor::post(
BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
template <typename Blocking, typename Relationship, typename Allocator>
template <typename Function, typename OtherAllocator>
void basic_system_executor<Blocking, Relationship, Allocator>::post(
BOOST_ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const
{
typedef typename decay<Function>::type function_type;
system_context& ctx = detail::global<system_context>();
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator> op;
typedef detail::executor_op<function_type, OtherAllocator> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
@@ -59,16 +157,17 @@ void system_executor::post(
p.v = p.p = 0;
}
template <typename Function, typename Allocator>
void system_executor::defer(
BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
template <typename Blocking, typename Relationship, typename Allocator>
template <typename Function, typename OtherAllocator>
void basic_system_executor<Blocking, Relationship, Allocator>::defer(
BOOST_ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const
{
typedef typename decay<Function>::type function_type;
system_context& ctx = detail::global<system_context>();
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator> op;
typedef detail::executor_op<function_type, OtherAllocator> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
@@ -78,6 +177,7 @@ void system_executor::defer(
ctx.scheduler_.post_immediate_completion(p.p, true);
p.v = p.p = 0;
}
#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
} // namespace asio
} // namespace boost

View File

@@ -2,7 +2,7 @@
// impl/thread_pool.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -15,9 +15,11 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/blocking_executor_op.hpp>
#include <boost/asio/detail/bulk_executor_op.hpp>
#include <boost/asio/detail/executor_op.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/recycling_allocator.hpp>
#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/execution_context.hpp>
@@ -32,32 +34,260 @@ thread_pool::get_executor() BOOST_ASIO_NOEXCEPT
return executor_type(*this);
}
inline thread_pool&
thread_pool::executor_type::context() const BOOST_ASIO_NOEXCEPT
inline thread_pool::executor_type
thread_pool::executor() BOOST_ASIO_NOEXCEPT
{
return pool_;
return executor_type(*this);
}
inline void
thread_pool::executor_type::on_work_started() const BOOST_ASIO_NOEXCEPT
inline thread_pool::scheduler_type
thread_pool::scheduler() BOOST_ASIO_NOEXCEPT
{
pool_.scheduler_.work_started();
return scheduler_type(*this);
}
inline void thread_pool::executor_type::on_work_finished()
const BOOST_ASIO_NOEXCEPT
template <typename Allocator, unsigned int Bits>
thread_pool::basic_executor_type<Allocator, Bits>&
thread_pool::basic_executor_type<Allocator, Bits>::operator=(
const basic_executor_type& other) BOOST_ASIO_NOEXCEPT
{
pool_.scheduler_.work_finished();
if (this != &other)
{
thread_pool* old_thread_pool = pool_;
pool_ = other.pool_;
allocator_ = other.allocator_;
bits_ = other.bits_;
if (Bits & outstanding_work_tracked)
{
if (pool_)
pool_->scheduler_.work_started();
if (old_thread_pool)
old_thread_pool->scheduler_.work_finished();
}
}
return *this;
}
template <typename Function, typename Allocator>
void thread_pool::executor_type::dispatch(
BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
#if defined(BOOST_ASIO_HAS_MOVE)
template <typename Allocator, unsigned int Bits>
thread_pool::basic_executor_type<Allocator, Bits>&
thread_pool::basic_executor_type<Allocator, Bits>::operator=(
basic_executor_type&& other) BOOST_ASIO_NOEXCEPT
{
if (this != &other)
{
thread_pool* old_thread_pool = pool_;
pool_ = other.pool_;
allocator_ = std::move(other.allocator_);
bits_ = other.bits_;
if (Bits & outstanding_work_tracked)
{
other.pool_ = 0;
if (old_thread_pool)
old_thread_pool->scheduler_.work_finished();
}
}
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
template <typename Allocator, unsigned int Bits>
inline bool thread_pool::basic_executor_type<Allocator,
Bits>::running_in_this_thread() const BOOST_ASIO_NOEXCEPT
{
return pool_->scheduler_.can_dispatch();
}
template <typename Allocator, unsigned int Bits>
template <typename Function>
void thread_pool::basic_executor_type<Allocator,
Bits>::do_execute(BOOST_ASIO_MOVE_ARG(Function) f, false_type) const
{
typedef typename decay<Function>::type function_type;
// Invoke immediately if the blocking.possibly property is enabled and we are
// already inside the thread pool.
if ((bits_ & blocking_never) == 0 && pool_->scheduler_.can_dispatch())
{
// Make a local, non-const copy of the function.
function_type tmp(BOOST_ASIO_MOVE_CAST(Function)(f));
#if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) \
&& !defined(BOOST_ASIO_NO_EXCEPTIONS)
try
{
#endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
// && !defined(BOOST_ASIO_NO_EXCEPTIONS)
detail::fenced_block b(detail::fenced_block::full);
boost_asio_handler_invoke_helpers::invoke(tmp, tmp);
return;
#if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) \
&& !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
catch (...)
{
pool_->scheduler_.capture_current_exception();
return;
}
#endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
// && !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator> op;
typename op::ptr p = { detail::addressof(allocator_),
op::ptr::allocate(allocator_), 0 };
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), allocator_);
if ((bits_ & relationship_continuation) != 0)
{
BOOST_ASIO_HANDLER_CREATION((*pool_, *p.p,
"thread_pool", pool_, 0, "execute(blk=never,rel=cont)"));
}
else
{
BOOST_ASIO_HANDLER_CREATION((*pool_, *p.p,
"thread_pool", pool_, 0, "execute(blk=never,rel=fork)"));
}
pool_->scheduler_.post_immediate_completion(p.p,
(bits_ & relationship_continuation) != 0);
p.v = p.p = 0;
}
template <typename Allocator, unsigned int Bits>
template <typename Function>
void thread_pool::basic_executor_type<Allocator,
Bits>::do_execute(BOOST_ASIO_MOVE_ARG(Function) f, true_type) const
{
// Obtain a non-const instance of the function.
detail::non_const_lvalue<Function> f2(f);
// Invoke immediately if we are already inside the thread pool.
if (pool_->scheduler_.can_dispatch())
{
#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
try
{
#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
detail::fenced_block b(detail::fenced_block::full);
boost_asio_handler_invoke_helpers::invoke(f2.value, f2.value);
return;
#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
catch (...)
{
std::terminate();
}
#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
// Construct an operation to wrap the function.
typedef typename decay<Function>::type function_type;
detail::blocking_executor_op<function_type> op(f2.value);
BOOST_ASIO_HANDLER_CREATION((*pool_, op,
"thread_pool", pool_, 0, "execute(blk=always)"));
pool_->scheduler_.post_immediate_completion(&op, false);
op.wait();
}
template <typename Allocator, unsigned int Bits>
template <typename Function>
void thread_pool::basic_executor_type<Allocator, Bits>::do_bulk_execute(
BOOST_ASIO_MOVE_ARG(Function) f, std::size_t n, false_type) const
{
typedef typename decay<Function>::type function_type;
typedef detail::bulk_executor_op<function_type, Allocator> op;
// Allocate and construct operations to wrap the function.
detail::op_queue<detail::scheduler_operation> ops;
for (std::size_t i = 0; i < n; ++i)
{
typename op::ptr p = { detail::addressof(allocator_),
op::ptr::allocate(allocator_), 0 };
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), allocator_, i);
ops.push(p.p);
if ((bits_ & relationship_continuation) != 0)
{
BOOST_ASIO_HANDLER_CREATION((*pool_, *p.p,
"thread_pool", pool_, 0, "bulk_execute(blk=never,rel=cont)"));
}
else
{
BOOST_ASIO_HANDLER_CREATION((*pool_, *p.p,
"thread_pool", pool_, 0, "bulk)execute(blk=never,rel=fork)"));
}
p.v = p.p = 0;
}
pool_->scheduler_.post_immediate_completions(n,
ops, (bits_ & relationship_continuation) != 0);
}
template <typename Function>
struct thread_pool_always_blocking_function_adapter
{
typename decay<Function>::type* f;
std::size_t n;
void operator()()
{
for (std::size_t i = 0; i < n; ++i)
{
(*f)(i);
}
}
};
template <typename Allocator, unsigned int Bits>
template <typename Function>
void thread_pool::basic_executor_type<Allocator, Bits>::do_bulk_execute(
BOOST_ASIO_MOVE_ARG(Function) f, std::size_t n, true_type) const
{
// Obtain a non-const instance of the function.
detail::non_const_lvalue<Function> f2(f);
thread_pool_always_blocking_function_adapter<Function>
adapter = { detail::addressof(f2.value), n };
this->do_execute(adapter, true_type());
}
#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
template <typename Allocator, unsigned int Bits>
inline thread_pool& thread_pool::basic_executor_type<
Allocator, Bits>::context() const BOOST_ASIO_NOEXCEPT
{
return *pool_;
}
template <typename Allocator, unsigned int Bits>
inline void thread_pool::basic_executor_type<Allocator,
Bits>::on_work_started() const BOOST_ASIO_NOEXCEPT
{
pool_->scheduler_.work_started();
}
template <typename Allocator, unsigned int Bits>
inline void thread_pool::basic_executor_type<Allocator,
Bits>::on_work_finished() const BOOST_ASIO_NOEXCEPT
{
pool_->scheduler_.work_finished();
}
template <typename Allocator, unsigned int Bits>
template <typename Function, typename OtherAllocator>
void thread_pool::basic_executor_type<Allocator, Bits>::dispatch(
BOOST_ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const
{
typedef typename decay<Function>::type function_type;
// Invoke immediately if we are already inside the thread pool.
if (pool_.scheduler_.can_dispatch())
if (pool_->scheduler_.can_dispatch())
{
// Make a local, non-const copy of the function.
function_type tmp(BOOST_ASIO_MOVE_CAST(Function)(f));
@@ -68,58 +298,55 @@ void thread_pool::executor_type::dispatch(
}
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator> op;
typedef detail::executor_op<function_type, OtherAllocator> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
BOOST_ASIO_HANDLER_CREATION((pool_, *p.p,
"thread_pool", &this->context(), 0, "dispatch"));
BOOST_ASIO_HANDLER_CREATION((*pool_, *p.p,
"thread_pool", pool_, 0, "dispatch"));
pool_.scheduler_.post_immediate_completion(p.p, false);
pool_->scheduler_.post_immediate_completion(p.p, false);
p.v = p.p = 0;
}
template <typename Function, typename Allocator>
void thread_pool::executor_type::post(
BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
template <typename Allocator, unsigned int Bits>
template <typename Function, typename OtherAllocator>
void thread_pool::basic_executor_type<Allocator, Bits>::post(
BOOST_ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const
{
typedef typename decay<Function>::type function_type;
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator> op;
typedef detail::executor_op<function_type, OtherAllocator> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
BOOST_ASIO_HANDLER_CREATION((pool_, *p.p,
"thread_pool", &this->context(), 0, "post"));
BOOST_ASIO_HANDLER_CREATION((*pool_, *p.p,
"thread_pool", pool_, 0, "post"));
pool_.scheduler_.post_immediate_completion(p.p, false);
pool_->scheduler_.post_immediate_completion(p.p, false);
p.v = p.p = 0;
}
template <typename Function, typename Allocator>
void thread_pool::executor_type::defer(
BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
template <typename Allocator, unsigned int Bits>
template <typename Function, typename OtherAllocator>
void thread_pool::basic_executor_type<Allocator, Bits>::defer(
BOOST_ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const
{
typedef typename decay<Function>::type function_type;
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator> op;
typedef detail::executor_op<function_type, OtherAllocator> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
BOOST_ASIO_HANDLER_CREATION((pool_, *p.p,
"thread_pool", &this->context(), 0, "defer"));
BOOST_ASIO_HANDLER_CREATION((*pool_, *p.p,
"thread_pool", pool_, 0, "defer"));
pool_.scheduler_.post_immediate_completion(p.p, true);
pool_->scheduler_.post_immediate_completion(p.p, true);
p.v = p.p = 0;
}
inline bool
thread_pool::executor_type::running_in_this_thread() const BOOST_ASIO_NOEXCEPT
{
return pool_.scheduler_.can_dispatch();
}
#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
} // namespace asio
} // namespace boost

View File

@@ -2,7 +2,7 @@
// impl/thread_pool.ipp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -16,7 +16,9 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <stdexcept>
#include <boost/asio/thread_pool.hpp>
#include <boost/asio/detail/throw_exception.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -29,35 +31,75 @@ struct thread_pool::thread_function
void operator()()
{
boost::system::error_code ec;
scheduler_->run(ec);
#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
try
{
#endif// !defined(BOOST_ASIO_NO_EXCEPTIONS)
boost::system::error_code ec;
scheduler_->run(ec);
#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
catch (...)
{
std::terminate();
}
#endif// !defined(BOOST_ASIO_NO_EXCEPTIONS)
}
};
#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
namespace detail {
inline long default_thread_pool_size()
{
std::size_t num_threads = thread::hardware_concurrency() * 2;
num_threads = num_threads == 0 ? 2 : num_threads;
return static_cast<long>(num_threads);
}
} // namespace detail
thread_pool::thread_pool()
: scheduler_(add_scheduler(new detail::scheduler(*this, 0, false)))
: scheduler_(add_scheduler(new detail::scheduler(*this, 0, false))),
num_threads_(detail::default_thread_pool_size())
{
scheduler_.work_started();
thread_function f = { &scheduler_ };
std::size_t num_threads = detail::thread::hardware_concurrency() * 2;
threads_.create_threads(f, num_threads ? num_threads : 2);
threads_.create_threads(f, static_cast<std::size_t>(num_threads_));
}
#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
namespace detail {
inline long clamp_thread_pool_size(std::size_t n)
{
if (n > 0x7FFFFFFF)
{
std::out_of_range ex("thread pool size");
boost::asio::detail::throw_exception(ex);
}
return static_cast<long>(n & 0x7FFFFFFF);
}
} // namespace detail
thread_pool::thread_pool(std::size_t num_threads)
: scheduler_(add_scheduler(new detail::scheduler(
*this, num_threads == 1 ? 1 : 0, false)))
*this, num_threads == 1 ? 1 : 0, false))),
num_threads_(detail::clamp_thread_pool_size(num_threads))
{
scheduler_.work_started();
thread_function f = { &scheduler_ };
threads_.create_threads(f, num_threads);
threads_.create_threads(f, static_cast<std::size_t>(num_threads_));
}
thread_pool::~thread_pool()
{
stop();
join();
shutdown();
}
void thread_pool::stop()
@@ -65,13 +107,20 @@ void thread_pool::stop()
scheduler_.stop();
}
void thread_pool::attach()
{
++num_threads_;
thread_function f = { &scheduler_ };
f();
}
void thread_pool::join()
{
if (!threads_.empty())
{
if (num_threads_)
scheduler_.work_finished();
if (!threads_.empty())
threads_.join();
}
}
detail::scheduler& thread_pool::add_scheduler(detail::scheduler* s)
@@ -81,6 +130,12 @@ detail::scheduler& thread_pool::add_scheduler(detail::scheduler* s)
return *scoped_impl.release();
}
void thread_pool::wait()
{
scheduler_.work_finished();
threads_.join();
}
} // namespace asio
} // namespace boost

View File

@@ -2,7 +2,7 @@
// impl/use_awaitable.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -17,6 +17,7 @@
#include <boost/asio/detail/config.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/cancellation_signal.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -33,8 +34,9 @@ public:
typedef awaitable<T, Executor> awaitable_type;
// Construct from the entry point of a new thread of execution.
awaitable_handler_base(awaitable<void, Executor> a, const Executor& ex)
: awaitable_thread<Executor>(std::move(a), ex)
awaitable_handler_base(awaitable<awaitable_thread_entry_point, Executor> a,
const Executor& ex, cancellation_slot pcs, cancellation_state cs)
: awaitable_thread<Executor>(std::move(a), ex, pcs, cs)
{
}
@@ -47,7 +49,8 @@ public:
protected:
awaitable_frame<T, Executor>* frame() noexcept
{
return static_cast<awaitable_frame<T, Executor>*>(this->top_of_stack_);
return static_cast<awaitable_frame<T, Executor>*>(
this->entry_point()->top_of_stack_);
}
};
@@ -55,7 +58,7 @@ template <typename, typename...>
class awaitable_handler;
template <typename Executor>
class awaitable_handler<Executor, void>
class awaitable_handler<Executor>
: public awaitable_handler_base<Executor, void>
{
public:
@@ -65,6 +68,7 @@ public:
{
this->frame()->attach_thread(this);
this->frame()->return_void();
this->frame()->clear_cancellation_slot();
this->frame()->pop_frame();
this->pump();
}
@@ -84,6 +88,7 @@ public:
this->frame()->set_error(ec);
else
this->frame()->return_void();
this->frame()->clear_cancellation_slot();
this->frame()->pop_frame();
this->pump();
}
@@ -103,6 +108,7 @@ public:
this->frame()->set_except(ex);
else
this->frame()->return_void();
this->frame()->clear_cancellation_slot();
this->frame()->pop_frame();
this->pump();
}
@@ -120,6 +126,7 @@ public:
{
this->frame()->attach_thread(this);
this->frame()->return_value(std::forward<Arg>(arg));
this->frame()->clear_cancellation_slot();
this->frame()->pop_frame();
this->pump();
}
@@ -140,6 +147,7 @@ public:
this->frame()->set_error(ec);
else
this->frame()->return_value(std::forward<Arg>(arg));
this->frame()->clear_cancellation_slot();
this->frame()->pop_frame();
this->pump();
}
@@ -160,6 +168,7 @@ public:
this->frame()->set_except(ex);
else
this->frame()->return_value(std::forward<Arg>(arg));
this->frame()->clear_cancellation_slot();
this->frame()->pop_frame();
this->pump();
}
@@ -178,6 +187,7 @@ public:
{
this->frame()->attach_thread(this);
this->frame()->return_values(std::forward<Args>(args)...);
this->frame()->clear_cancellation_slot();
this->frame()->pop_frame();
this->pump();
}
@@ -199,6 +209,7 @@ public:
this->frame()->set_error(ec);
else
this->frame()->return_values(std::forward<Args>(args)...);
this->frame()->clear_cancellation_slot();
this->frame()->pop_frame();
this->pump();
}
@@ -220,6 +231,7 @@ public:
this->frame()->set_except(ex);
else
this->frame()->return_values(std::forward<Args>(args)...);
this->frame()->clear_cancellation_slot();
this->frame()->pop_frame();
this->pump();
}
@@ -229,6 +241,19 @@ public:
#if !defined(GENERATING_DOCUMENTATION)
#if defined(_MSC_VER)
template <typename T>
T dummy_return()
{
return std::move(*static_cast<T*>(nullptr));
}
template <>
inline void dummy_return()
{
}
#endif // defined(_MSC_VER)
template <typename Executor, typename R, typename... Args>
class async_result<use_awaitable_t<Executor>, R(Args...)>
{
@@ -237,28 +262,28 @@ public:
Executor, typename decay<Args>::type...> handler_type;
typedef typename handler_type::awaitable_type return_type;
#if defined(_MSC_VER)
template <typename T>
static T dummy_return()
template <typename Initiation, typename... InitArgs>
#if defined(__APPLE_CC__) && (__clang_major__ == 13)
__attribute__((noinline))
#endif // defined(__APPLE_CC__) && (__clang_major__ == 13)
static handler_type* do_init(
detail::awaitable_frame_base<Executor>* frame, Initiation& initiation,
use_awaitable_t<Executor> u, InitArgs&... args)
{
return std::move(*static_cast<T*>(nullptr));
(void)u;
BOOST_ASIO_HANDLER_LOCATION((u.file_name_, u.line_, u.function_name_));
handler_type handler(frame->detach_thread());
std::move(initiation)(std::move(handler), std::move(args)...);
return nullptr;
}
template <>
static void dummy_return()
{
}
#endif // defined(_MSC_VER)
template <typename Initiation, typename... InitArgs>
static return_type initiate(Initiation initiation,
use_awaitable_t<Executor>, InitArgs... args)
use_awaitable_t<Executor> u, InitArgs... args)
{
co_await [&](auto* frame)
co_await [&] (auto* frame)
{
handler_type handler(frame->detach_thread());
std::move(initiation)(std::move(handler), std::move(args)...);
return static_cast<handler_type*>(nullptr);
return do_init(frame, initiation, u, args...);
};
for (;;) {} // Never reached.

View File

@@ -2,7 +2,7 @@
// impl/use_future.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -19,7 +19,9 @@
#include <tuple>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/memory.hpp>
#include <boost/asio/dispatch.hpp>
#include <boost/system/error_code.hpp>
#include <boost/asio/execution.hpp>
#include <boost/asio/packaged_task.hpp>
#include <boost/system/system_error.hpp>
#include <boost/asio/system_executor.hpp>
@@ -201,7 +203,7 @@ private:
// An executor that adapts the system_executor to capture any exeption thrown
// by a submitted function object and save it into a promise.
template <typename T>
template <typename T, typename Blocking = execution::blocking_t::possibly_t>
class promise_executor
{
public:
@@ -210,6 +212,42 @@ public:
{
}
execution_context& query(execution::context_t) const BOOST_ASIO_NOEXCEPT
{
return boost::asio::query(system_executor(), execution::context);
}
static BOOST_ASIO_CONSTEXPR Blocking query(execution::blocking_t)
{
return Blocking();
}
promise_executor<T, execution::blocking_t::possibly_t>
require(execution::blocking_t::possibly_t) const
{
return promise_executor<T, execution::blocking_t::possibly_t>(p_);
}
promise_executor<T, execution::blocking_t::never_t>
require(execution::blocking_t::never_t) const
{
return promise_executor<T, execution::blocking_t::never_t>(p_);
}
template <typename F>
void execute(BOOST_ASIO_MOVE_ARG(F) f) const
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost::asio::require(system_executor(), Blocking()).execute(
promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)));
#else // defined(BOOST_ASIO_NO_DEPRECATED)
execution::execute(
boost::asio::require(system_executor(), Blocking()),
promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)));
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
execution_context& context() const BOOST_ASIO_NOEXCEPT
{
return system_executor().context();
@@ -237,6 +275,7 @@ public:
system_executor().defer(
promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)), a);
}
#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
friend bool operator==(const promise_executor& a,
const promise_executor& b) BOOST_ASIO_NOEXCEPT
@@ -578,7 +617,7 @@ class promise_handler_selector<void(std::exception_ptr, Arg...)>
: public promise_handler_ex_n< \
std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF)
BOOST_ASIO_VARIADIC_GENERATE_5(BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF)
#undef BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
@@ -608,13 +647,36 @@ private:
Allocator allocator_;
};
template <typename Function>
struct promise_function_wrapper
{
explicit promise_function_wrapper(Function& f)
: function_(BOOST_ASIO_MOVE_CAST(Function)(f))
{
}
explicit promise_function_wrapper(const Function& f)
: function_(f)
{
}
void operator()()
{
function_();
}
Function function_;
};
#if !defined(BOOST_ASIO_NO_DEPRECATED)
template <typename Function, typename Signature, typename Allocator>
inline void asio_handler_invoke(Function& f,
promise_handler<Signature, Allocator>* h)
{
typename promise_handler<Signature, Allocator>::executor_type
ex(h->get_executor());
ex.dispatch(BOOST_ASIO_MOVE_CAST(Function)(f), std::allocator<void>());
boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
}
template <typename Function, typename Signature, typename Allocator>
@@ -623,9 +685,11 @@ inline void asio_handler_invoke(const Function& f,
{
typename promise_handler<Signature, Allocator>::executor_type
ex(h->get_executor());
ex.dispatch(f, std::allocator<void>());
boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
}
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
// Helper base class for async_result specialisation.
template <typename Signature, typename Allocator>
class promise_async_result
@@ -720,6 +784,8 @@ private:
Allocator allocator_;
};
#if !defined(BOOST_ASIO_NO_DEPRECATED)
template <typename Function,
typename Function1, typename Allocator, typename Result>
inline void asio_handler_invoke(Function& f,
@@ -727,7 +793,7 @@ inline void asio_handler_invoke(Function& f,
{
typename packaged_handler<Function1, Allocator, Result>::executor_type
ex(h->get_executor());
ex.dispatch(BOOST_ASIO_MOVE_CAST(Function)(f), std::allocator<void>());
boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
}
template <typename Function,
@@ -737,9 +803,11 @@ inline void asio_handler_invoke(const Function& f,
{
typename packaged_handler<Function1, Allocator, Result>::executor_type
ex(h->get_executor());
ex.dispatch(f, std::allocator<void>());
boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
}
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
// Helper base class for async_result specialisation.
template <typename Function, typename Allocator, typename Result>
class packaged_async_result
@@ -879,6 +947,104 @@ public:
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
namespace traits {
#if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
template <typename T, typename Blocking>
struct equality_comparable<
boost::asio::detail::promise_executor<T, Blocking> >
{
BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
};
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
#if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
template <typename T, typename Blocking, typename Function>
struct execute_member<
boost::asio::detail::promise_executor<T, Blocking>, Function>
{
BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
typedef void result_type;
};
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
#if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
template <typename T, typename Blocking, typename Property>
struct query_static_constexpr_member<
boost::asio::detail::promise_executor<T, Blocking>,
Property,
typename boost::asio::enable_if<
boost::asio::is_convertible<
Property,
boost::asio::execution::blocking_t
>::value
>::type
>
{
BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
typedef Blocking result_type;
static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT
{
return Blocking();
}
};
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
#if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
template <typename T, typename Blocking>
struct query_member<
boost::asio::detail::promise_executor<T, Blocking>,
execution::context_t
>
{
BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
typedef boost::asio::system_context& result_type;
};
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
#if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
template <typename T, typename Blocking>
struct require_member<
boost::asio::detail::promise_executor<T, Blocking>,
execution::blocking_t::possibly_t
>
{
BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
typedef boost::asio::detail::promise_executor<T,
execution::blocking_t::possibly_t> result_type;
};
template <typename T, typename Blocking>
struct require_member<
boost::asio::detail::promise_executor<T, Blocking>,
execution::blocking_t::never_t
>
{
BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
typedef boost::asio::detail::promise_executor<T,
execution::blocking_t::never_t> result_type;
};
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
} // namespace traits
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
// impl/write_at.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2023 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)
@@ -15,11 +15,10 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/associator.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/completion_condition.hpp>
#include <boost/asio/detail/array_fwd.hpp>
#include <boost/asio/detail/base_from_cancellation_state.hpp>
#include <boost/asio/detail/base_from_completion_cond.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/consuming_buffers.hpp>
@@ -27,6 +26,7 @@
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_tracking.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
@@ -59,7 +59,7 @@ namespace detail
else
break;
}
return tmp.total_consumed();;
return tmp.total_consumed();
}
} // namespace detail
@@ -161,14 +161,16 @@ namespace detail
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
class write_at_op
: detail::base_from_completion_cond<CompletionCondition>
: public base_from_cancellation_state<WriteHandler>,
base_from_completion_cond<CompletionCondition>
{
public:
write_at_op(AsyncRandomAccessWriteDevice& device,
uint64_t offset, const ConstBufferSequence& buffers,
CompletionCondition& completion_condition, WriteHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
: base_from_cancellation_state<WriteHandler>(
handler, enable_partial_cancellation()),
base_from_completion_cond<CompletionCondition>(completion_condition),
device_(device),
offset_(offset),
buffers_(buffers),
@@ -179,7 +181,8 @@ namespace detail
#if defined(BOOST_ASIO_HAS_MOVE)
write_at_op(const write_at_op& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
: base_from_cancellation_state<WriteHandler>(other),
base_from_completion_cond<CompletionCondition>(other),
device_(other.device_),
offset_(other.offset_),
buffers_(other.buffers_),
@@ -189,8 +192,11 @@ namespace detail
}
write_at_op(write_at_op&& other)
: detail::base_from_completion_cond<CompletionCondition>(
BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
: base_from_cancellation_state<WriteHandler>(
BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
WriteHandler>)(other)),
base_from_completion_cond<CompletionCondition>(
BOOST_ASIO_MOVE_CAST(base_from_completion_cond<
CompletionCondition>)(other)),
device_(other.device_),
offset_(other.offset_),
@@ -201,7 +207,7 @@ namespace detail
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
void operator()(const boost::system::error_code& ec,
void operator()(boost::system::error_code ec,
std::size_t bytes_transferred, int start = 0)
{
std::size_t max_size;
@@ -209,19 +215,31 @@ namespace detail
{
case 1:
max_size = this->check_for_completion(ec, buffers_.total_consumed());
do
for (;;)
{
device_.async_write_some_at(
offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
{
BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write_at"));
device_.async_write_some_at(
offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
}
return; default:
buffers_.consume(bytes_transferred);
if ((!ec && bytes_transferred == 0) || buffers_.empty())
break;
max_size = this->check_for_completion(ec, buffers_.total_consumed());
} while (max_size > 0);
if (max_size == 0)
break;
if (this->cancelled() != cancellation_type::none)
{
ec = boost::asio::error::operation_aborted;
break;
}
}
handler_(ec, buffers_.total_consumed());
BOOST_ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(
static_cast<const boost::system::error_code&>(ec),
static_cast<const std::size_t&>(buffers_.total_consumed()));
}
}
@@ -239,23 +257,33 @@ namespace detail
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename AsyncRandomAccessWriteDevice,
@@ -273,29 +301,37 @@ namespace detail
template <typename Function, typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void asio_handler_invoke(Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void start_write_at_buffer_sequence_op(AsyncRandomAccessWriteDevice& d,
inline void start_write_at_op(AsyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
const ConstBufferIterator&, CompletionCondition& completion_condition,
WriteHandler& handler)
@@ -306,13 +342,26 @@ namespace detail
boost::system::error_code(), 0, 1);
}
struct initiate_async_write_at_buffer_sequence
template <typename AsyncRandomAccessWriteDevice>
class initiate_async_write_at
{
template <typename WriteHandler, typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename CompletionCondition>
public:
typedef typename AsyncRandomAccessWriteDevice::executor_type executor_type;
explicit initiate_async_write_at(AsyncRandomAccessWriteDevice& device)
: device_(device)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return device_.get_executor();
}
template <typename WriteHandler, typename ConstBufferSequence,
typename CompletionCondition>
void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
AsyncRandomAccessWriteDevice* d, uint64_t offset,
const ConstBufferSequence& buffers,
uint64_t offset, const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
{
// If you get an error on the following line it means that your handler
@@ -321,84 +370,95 @@ namespace detail
non_const_lvalue<WriteHandler> handler2(handler);
non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
start_write_at_buffer_sequence_op(*d, offset, buffers,
start_write_at_op(device_, offset, buffers,
boost::asio::buffer_sequence_begin(buffers),
completion_cond2.value, handler2.value);
}
private:
AsyncRandomAccessWriteDevice& device_;
};
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler, typename Allocator>
struct associated_allocator<
template <template <typename, typename> class Associator,
typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
typename ConstBufferIterator, typename CompletionCondition,
typename WriteHandler, typename DefaultCandidate>
struct associator<Associator,
detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>,
Allocator>
DefaultCandidate>
: Associator<WriteHandler, DefaultCandidate>
{
typedef typename associated_allocator<WriteHandler, Allocator>::type type;
static type get(
const detail::write_at_op<AsyncRandomAccessWriteDevice,
static typename Associator<WriteHandler, DefaultCandidate>::type
get(const detail::write_at_op<AsyncRandomAccessWriteDevice,
ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
CompletionCondition, WriteHandler>& h) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
}
};
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler, typename Executor>
struct associated_executor<
detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>,
Executor>
{
typedef typename associated_executor<WriteHandler, Executor>::type type;
static type get(
const detail::write_at_op<AsyncRandomAccessWriteDevice,
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<WriteHandler, DefaultCandidate>::type)
get(const detail::write_at_op<AsyncRandomAccessWriteDevice,
ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)))
{
return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
typename CompletionCondition, typename WriteHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename CompletionCondition,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) WriteToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,
void (boost::system::error_code, std::size_t))
async_write_at(AsyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
CompletionCondition completion_condition,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
BOOST_ASIO_MOVE_ARG(WriteToken) token)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<WriteToken,
void (boost::system::error_code, std::size_t)>(
declval<detail::initiate_async_write_at<
AsyncRandomAccessWriteDevice> >(),
token, offset, buffers,
BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition))))
{
return async_initiate<WriteHandler,
return async_initiate<WriteToken,
void (boost::system::error_code, std::size_t)>(
detail::initiate_async_write_at_buffer_sequence(), handler, &d, offset,
buffers, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
detail::initiate_async_write_at<AsyncRandomAccessWriteDevice>(d),
token, offset, buffers,
BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
typename WriteHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) WriteToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,
void (boost::system::error_code, std::size_t))
async_write_at(AsyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
BOOST_ASIO_MOVE_ARG(WriteToken) token)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<WriteToken,
void (boost::system::error_code, std::size_t)>(
declval<detail::initiate_async_write_at<
AsyncRandomAccessWriteDevice> >(),
token, offset, buffers, transfer_all())))
{
return async_initiate<WriteHandler,
return async_initiate<WriteToken,
void (boost::system::error_code, std::size_t)>(
detail::initiate_async_write_at_buffer_sequence(),
handler, &d, offset, buffers, transfer_all());
detail::initiate_async_write_at<AsyncRandomAccessWriteDevice>(d),
token, offset, buffers, transfer_all());
}
#if !defined(BOOST_ASIO_NO_EXTENSIONS)
@@ -436,7 +496,7 @@ namespace detail
const std::size_t bytes_transferred)
{
streambuf_.consume(bytes_transferred);
handler_(ec, bytes_transferred);
BOOST_ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_transferred);
}
//private:
@@ -445,19 +505,29 @@ namespace detail
};
template <typename Allocator, typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,
write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
{
#if defined(BOOST_ASIO_NO_DEPRECATED)
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
return asio_handler_allocate_is_no_longer_used();
#else // defined(BOOST_ASIO_NO_DEPRECATED)
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Allocator, typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void* pointer, std::size_t size,
write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_deallocate_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Allocator, typename WriteHandler>
@@ -469,28 +539,50 @@ namespace detail
}
template <typename Function, typename Allocator, typename WriteHandler>
inline void asio_handler_invoke(Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function& function,
write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
template <typename Function, typename Allocator, typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function& function,
write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
#if defined(BOOST_ASIO_NO_DEPRECATED)
return asio_handler_invoke_is_no_longer_used();
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
}
struct initiate_async_write_at_streambuf
template <typename AsyncRandomAccessWriteDevice>
class initiate_async_write_at_streambuf
{
template <typename WriteHandler, typename AsyncRandomAccessWriteDevice,
public:
typedef typename AsyncRandomAccessWriteDevice::executor_type executor_type;
explicit initiate_async_write_at_streambuf(
AsyncRandomAccessWriteDevice& device)
: device_(device)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return device_.get_executor();
}
template <typename WriteHandler,
typename Allocator, typename CompletionCondition>
void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
AsyncRandomAccessWriteDevice* d, uint64_t offset,
basic_streambuf<Allocator>* b,
uint64_t offset, basic_streambuf<Allocator>* b,
BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_condition) const
{
// If you get an error on the following line it means that your handler
@@ -498,75 +590,92 @@ namespace detail
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
non_const_lvalue<WriteHandler> handler2(handler);
async_write_at(*d, offset, b->data(),
async_write_at(device_, offset, b->data(),
BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition),
write_at_streambuf_op<Allocator, typename decay<WriteHandler>::type>(
*b, handler2.value));
}
private:
AsyncRandomAccessWriteDevice& device_;
};
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename Allocator, typename WriteHandler, typename Allocator1>
struct associated_allocator<
detail::write_at_streambuf_op<Allocator, WriteHandler>,
Allocator1>
{
typedef typename associated_allocator<WriteHandler, Allocator1>::type type;
static type get(
const detail::write_at_streambuf_op<Allocator, WriteHandler>& h,
const Allocator1& a = Allocator1()) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<WriteHandler, Allocator1>::get(h.handler_, a);
}
};
template <typename Executor, typename WriteHandler, typename Executor1>
struct associated_executor<
template <template <typename, typename> class Associator,
typename Executor, typename WriteHandler, typename DefaultCandidate>
struct associator<Associator,
detail::write_at_streambuf_op<Executor, WriteHandler>,
Executor1>
DefaultCandidate>
: Associator<WriteHandler, DefaultCandidate>
{
typedef typename associated_executor<WriteHandler, Executor1>::type type;
static type get(
const detail::write_at_streambuf_op<Executor, WriteHandler>& h,
const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
static typename Associator<WriteHandler, DefaultCandidate>::type
get(const detail::write_at_streambuf_op<Executor, WriteHandler>& h)
BOOST_ASIO_NOEXCEPT
{
return associated_executor<WriteHandler, Executor1>::get(h.handler_, ex);
return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
}
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
typename Associator<WriteHandler, DefaultCandidate>::type)
get(const detail::write_at_streambuf_op<Executor, WriteHandler>& h,
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)))
{
return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessWriteDevice, typename Allocator,
typename CompletionCondition, typename WriteHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
template <typename AsyncRandomAccessWriteDevice,
typename Allocator, typename CompletionCondition,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) WriteToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,
void (boost::system::error_code, std::size_t))
async_write_at(AsyncRandomAccessWriteDevice& d,
uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
BOOST_ASIO_MOVE_ARG(WriteToken) token)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<WriteToken,
void (boost::system::error_code, std::size_t)>(
declval<detail::initiate_async_write_at_streambuf<
AsyncRandomAccessWriteDevice> >(),
token, offset, &b,
BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition))))
{
return async_initiate<WriteHandler,
return async_initiate<WriteToken,
void (boost::system::error_code, std::size_t)>(
detail::initiate_async_write_at_streambuf(), handler, &d, offset,
&b, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
detail::initiate_async_write_at_streambuf<
AsyncRandomAccessWriteDevice>(d),
token, offset, &b,
BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
template <typename AsyncRandomAccessWriteDevice, typename Allocator,
typename WriteHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) WriteToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,
void (boost::system::error_code, std::size_t))
async_write_at(AsyncRandomAccessWriteDevice& d,
uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
BOOST_ASIO_MOVE_ARG(WriteToken) token)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
async_initiate<WriteToken,
void (boost::system::error_code, std::size_t)>(
declval<detail::initiate_async_write_at_streambuf<
AsyncRandomAccessWriteDevice> >(),
token, offset, &b, transfer_all())))
{
return async_initiate<WriteHandler,
return async_initiate<WriteToken,
void (boost::system::error_code, std::size_t)>(
detail::initiate_async_write_at_streambuf(),
handler, &d, offset, &b, transfer_all());
detail::initiate_async_write_at_streambuf<
AsyncRandomAccessWriteDevice>(d),
token, offset, &b, transfer_all());
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)