forked from chriskohlhoff/asio
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add experimental::prepend completion token adapter.
The prepend completion token adapter can be used to pass additional before the existing completion handler arguments. For example: timer.async_wait( asio::experimental::prepend( [](int i, std::error_code ec) { // ... }, 42) ); std::future<std::tuple<int, std::error_code>> f = timer.async_wait( asio::experimental::prepend( asio::use_future, 42 ) );
- Loading branch information
1 parent
90f3b6c
commit d6735d4
Showing
4 changed files
with
295 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
// | ||
// experimental/impl/prepend.hpp | ||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
// | ||
// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) | ||
// | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
// | ||
|
||
#ifndef ASIO_IMPL_EXPERIMENTAL_PREPEND_HPP | ||
#define ASIO_IMPL_EXPERIMENTAL_PREPEND_HPP | ||
|
||
#if defined(_MSC_VER) && (_MSC_VER >= 1200) | ||
# pragma once | ||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | ||
|
||
#include "asio/detail/config.hpp" | ||
|
||
#include "asio/associator.hpp" | ||
#include "asio/async_result.hpp" | ||
#include "asio/detail/handler_alloc_helpers.hpp" | ||
#include "asio/detail/handler_cont_helpers.hpp" | ||
#include "asio/detail/handler_invoke_helpers.hpp" | ||
#include "asio/detail/type_traits.hpp" | ||
#include "asio/detail/variadic_templates.hpp" | ||
|
||
#include "asio/detail/push_options.hpp" | ||
|
||
namespace asio { | ||
namespace experimental { | ||
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(ASIO_MOVE_ARG(H) handler, std::tuple<Values...> values) | ||
: handler_(ASIO_MOVE_CAST(H)(handler)), | ||
values_(ASIO_MOVE_CAST(std::tuple<Values...>)(values)) | ||
{ | ||
} | ||
|
||
template <typename... Args> | ||
void operator()(ASIO_MOVE_ARG(Args)... args) | ||
{ | ||
this->invoke( | ||
std::make_index_sequence<sizeof...(Values)>{}, | ||
ASIO_MOVE_CAST(Args)(args)...); | ||
} | ||
|
||
template <std::size_t... I, typename... Args> | ||
void invoke(std::index_sequence<I...>, ASIO_MOVE_ARG(Args)... args) | ||
{ | ||
ASIO_MOVE_OR_LVALUE(Handler)(handler_)( | ||
ASIO_MOVE_CAST(Values)(std::get<I>(values_))..., | ||
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(ASIO_NO_DEPRECATED) | ||
asio_handler_alloc_helpers::allocate(size, this_handler->handler_); | ||
return asio_handler_allocate_is_no_longer_used(); | ||
#else // defined(ASIO_NO_DEPRECATED) | ||
return asio_handler_alloc_helpers::allocate( | ||
size, this_handler->handler_); | ||
#endif // defined(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) | ||
{ | ||
asio_handler_alloc_helpers::deallocate( | ||
pointer, size, this_handler->handler_); | ||
#if defined(ASIO_NO_DEPRECATED) | ||
return asio_handler_deallocate_is_no_longer_used(); | ||
#endif // defined(ASIO_NO_DEPRECATED) | ||
} | ||
|
||
template <typename Handler> | ||
inline bool asio_handler_is_continuation( | ||
prepend_handler<Handler>* this_handler) | ||
{ | ||
return 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) | ||
{ | ||
asio_handler_invoke_helpers::invoke( | ||
function, this_handler->handler_); | ||
#if defined(ASIO_NO_DEPRECATED) | ||
return asio_handler_invoke_is_no_longer_used(); | ||
#endif // defined(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) | ||
{ | ||
asio_handler_invoke_helpers::invoke( | ||
function, this_handler->handler_); | ||
#if defined(ASIO_NO_DEPRECATED) | ||
return asio_handler_invoke_is_no_longer_used(); | ||
#endif // defined(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 | ||
} // namespace experimental | ||
|
||
#if !defined(GENERATING_DOCUMENTATION) | ||
|
||
template <typename CompletionToken, typename... Values, typename Signature> | ||
struct async_result< | ||
experimental::prepend_t<CompletionToken, Values...>, Signature> | ||
: async_result<CompletionToken, | ||
typename experimental::detail::prepend_signature< | ||
Signature, Values...>::type> | ||
{ | ||
typedef typename experimental::detail::prepend_signature< | ||
Signature, Values...>::type signature; | ||
|
||
template <typename Initiation> | ||
struct init_wrapper | ||
{ | ||
init_wrapper(Initiation init) | ||
: initiation_(ASIO_MOVE_CAST(Initiation)(init)) | ||
{ | ||
} | ||
|
||
template <typename Handler, typename... Args> | ||
void operator()( | ||
ASIO_MOVE_ARG(Handler) handler, | ||
std::tuple<Values...> values, | ||
ASIO_MOVE_ARG(Args)... args) | ||
{ | ||
ASIO_MOVE_CAST(Initiation)(initiation_)( | ||
experimental::detail::prepend_handler< | ||
typename decay<Handler>::type, Values...>( | ||
ASIO_MOVE_CAST(Handler)(handler), | ||
ASIO_MOVE_CAST(std::tuple<Values...>)(values)), | ||
ASIO_MOVE_CAST(Args)(args)...); | ||
} | ||
|
||
Initiation initiation_; | ||
}; | ||
|
||
template <typename Initiation, typename RawCompletionToken, typename... Args> | ||
static 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<ASIO_MOVE_ARG(Args)>()...))) | ||
initiate( | ||
ASIO_MOVE_ARG(Initiation) initiation, | ||
ASIO_MOVE_ARG(RawCompletionToken) token, | ||
ASIO_MOVE_ARG(Args)... args) | ||
{ | ||
return async_initiate<CompletionToken, signature>( | ||
init_wrapper<typename decay<Initiation>::type>( | ||
ASIO_MOVE_CAST(Initiation)(initiation)), | ||
token.token_, | ||
ASIO_MOVE_CAST(std::tuple<Values...>)(token.values_), | ||
ASIO_MOVE_CAST(Args)(args)...); | ||
} | ||
}; | ||
|
||
template <template <typename, typename> class Associator, | ||
typename Handler, typename DefaultCandidate> | ||
struct associator<Associator, | ||
experimental::detail::prepend_handler<Handler>, DefaultCandidate> | ||
: Associator<Handler, DefaultCandidate> | ||
{ | ||
static typename Associator<Handler, DefaultCandidate>::type get( | ||
const experimental::detail::prepend_handler<Handler>& h, | ||
const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT | ||
{ | ||
return Associator<Handler, DefaultCandidate>::get(h.handler_, c); | ||
} | ||
}; | ||
|
||
#endif // !defined(GENERATING_DOCUMENTATION) | ||
|
||
} // namespace asio | ||
|
||
#include "asio/detail/pop_options.hpp" | ||
|
||
#endif // ASIO_IMPL_EXPERIMENTAL_PREPEND_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// | ||
// experimental/prepend.hpp | ||
// ~~~~~~~~~~~~~~~~~~~~~~~~ | ||
// | ||
// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) | ||
// | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
// | ||
|
||
#ifndef ASIO_EXPERIMENTAL_PREPEND_HPP | ||
#define ASIO_EXPERIMENTAL_PREPEND_HPP | ||
|
||
#if defined(_MSC_VER) && (_MSC_VER >= 1200) | ||
# pragma once | ||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | ||
|
||
#include "asio/detail/config.hpp" | ||
#include <tuple> | ||
#include "asio/detail/type_traits.hpp" | ||
|
||
#include "asio/detail/push_options.hpp" | ||
|
||
namespace asio { | ||
namespace experimental { | ||
|
||
/// Completion token type used to specify that the completion handler | ||
/// arguments should be passed additional values before the results of the | ||
/// operation. | ||
template <typename CompletionToken, typename... Values> | ||
class prepend_t | ||
{ | ||
public: | ||
/// Constructor. | ||
template <typename T, typename... V> | ||
ASIO_CONSTEXPR explicit prepend_t( | ||
ASIO_MOVE_ARG(T) completion_token, | ||
ASIO_MOVE_ARG(V)... values) | ||
: token_(ASIO_MOVE_CAST(T)(completion_token)), | ||
values_(ASIO_MOVE_CAST(V)(values)...) | ||
{ | ||
} | ||
|
||
//private: | ||
CompletionToken token_; | ||
std::tuple<Values...> values_; | ||
}; | ||
|
||
/// Completion token type used to specify that the completion handler | ||
/// arguments should be passed additional values before the results of the | ||
/// operation. | ||
template <typename CompletionToken, typename... Values> | ||
inline ASIO_CONSTEXPR prepend_t< | ||
typename decay<CompletionToken>::type, typename decay<Values>::type...> | ||
prepend(ASIO_MOVE_ARG(CompletionToken) completion_token, | ||
ASIO_MOVE_ARG(Values)... values) | ||
{ | ||
return prepend_t< | ||
typename decay<CompletionToken>::type, typename decay<Values>::type...>( | ||
ASIO_MOVE_CAST(CompletionToken)(completion_token), | ||
ASIO_MOVE_CAST(Values)(values)...); | ||
} | ||
|
||
} // namespace experimental | ||
} // namespace asio | ||
|
||
#include "asio/detail/pop_options.hpp" | ||
|
||
#include "asio/experimental/impl/prepend.hpp" | ||
|
||
#endif // ASIO_EXPERIMENTAL_PREPEND_HPP |