Files
OpenVPNAdapter/asio/include/asio/bind_executor.hpp
Sergey Abramchuk 6f1fcb972a Squashed 'OpenVPN Adapter/Vendors/asio/' changes from 524288cb4..82be891ba
b3d2ab725 asio version 1.12.0 released
d9161a36e Update release script to match new boost doc build.
54c7b85de Update revision history.
9eaa2a2e5 Update tutorial text to use 'io_context'.
41eb9dc20 Ignore tsified directory.
9229964dc Don't use inline namespace 'v1' in example code snippets.
10098abd6 Include inline namespace 'v1' in tsified code.
9bdbef19f Regenerate documentation.
8fa11a15d Exclude use_future_t implementation detail from documentation.
577b69806 Workaround broken doxygen typedef linking when primary template is undefined.
ea1b39f04 Fix tsify.pl to work with latest code.
694ed5284 Document the new concurrency hints.
3834d7363 Some updates to 'Using' notes.
00873ce91 Document Networking TS changes.
8f25ea4b5 Remove spurious value_type from buffer sequence requirements.
b33eb0219 gcc 4.7 is the minimum version required for std::allocator_traits.
036faf66a Use new move-enabled form of async_accept.
f72304319 Ensure that use_future<std::allocator<void>> is always constexpr default-constructible.
4ad7a397c Add missing variadic template emulation in use_future.
5c591a466 Disable buffer debugging for older MSVC, as it triggers compiler misbehaviour.
f8bd903af Add assign() and clear() functions to error_code.
db4c0e83f Disable boost.chrono error handling.
cca13eefa Document the new handler tracking features.
ff9d69e2f Add check for _DEFAULT_SOURCE in addition to _BSD_SOURCE.
52498bbc6 Suppress recv truncation errors on Windows, to match POSIX behaviour.
e87c37ec9 Add documentation examples of using asio::post to submit work.
ad52c82d2 Create C++11 versions of the fork, local, multicast and nonblocking examples.
f16e39e78 Don't directly include <chrono>, to keep header C++03-compatible.
c016e1aec Boostify the TS headers.
559013298 Suppress MSVC dynamic initialisation warning.
efa18153d Add tests to ensure the ts/* headers compile and are self-contained.
41fccd565 asio/use_future.hpp is already in the convenience header.
2e743f737 Add waitable timer headers to convenience header.
fe5470f4f Use new post() in serialization example.
45dcb33c2 Use asio::coroutine in latency tests.
e556aed8d Update invocation examples to use executors.
5a9d0721d Fix up reference to post().
24050d5ea Show how to associate an executor using nested type and member function.
b02c6c758 Update allocation overview and examples to use new form.
3218be74e Fix typo in strands overview.
3152e77f8 Increase number of buffers per operation for consuming_buffers.
5acae1971 Increase threshold for small memory block recycling to 1KB.
986ef7361 Make sure asio/system_context.hpp is self-contained.
c80c1cbd5 Don't call memcpy with length 0, to avoid passing null pointers.
ede4e7597 Fix description of std::getline's behaviour.
60170d625 Fix copy/paste error in comment.
cff2b4998 Fix clang narrowing warning.
a40570919 Fix incorrect hyperlink target.
fcaf75700 Remove last remaining instance of auto_ptr.
fddf89126 Restore binder support for 3, 4 and 5 arguments.
096660c47 Fix double delete issue introduced by 47b9319acbc45d3c1bcb805a4a03cd47df177c11.
b44805ff0 Add backward compatibility for the old ConnectCondition form.
09c69982e Ensure make_network_vX error_code overload doesn't throw on invalid prefix length.
f4fecdfe4 Fix the rights for event objects on UWP.
2943ee65f Suppress implicit fallthrough warning on newer gcc.
b441bf70b Fix clang version detection for suppression of unused typedef warning.
565c6e8fa Fix compile errors in some asio::connect overloads.
d52b81646 Bump minimum MSVC version required for C++11 allocators.
5618fadb1 Fix compile warning under Emscripten
b2367dab2 Use proper SSL_version() function so that asio can build with BoringSSL.
cfe47e71d Regenerate documentation.
6377b0466 Patch up some template links.
2bda4b85c Add new macros to doxygen configuration.
4a4d28b0d Qualify use of error_code.
e39a95a73 Fix boostify.pl to work with latest code.
2ccb648f4 Only obtain associated allocator when handler is known to be valid.
230c0d2ae Asynchronous accept should not check user-set non-blocking flag.
862aed305 Require gcc >= 4.7 to use standard atomics.
a0d28e5a7 Don't use auto_ptr.
15e136fa8 Use deregister_internal_descriptor in signal_set_service.
59330e825 Put detail/config.hpp include first in detail/string_view.hpp.
d6144828b Only enable string_view with /std:c++17 on MSVC.
c2cb5395e Use hook allocation strategy whenever associated allocator is std::allocator.
5b4aa5ef9 Make epoll_reactor resistant to events with duplicate user data.
47b9319ac Don't free the reactor's per-descriptor state until after close.
cbf687653 Fix compile errors in dev_poll_reactor.
870124ab5 Add missing 'else' in epoll_reactor's handler tracking support.
b37b9449e Clean up socket release() implementation for reactor-based platforms.
f5c570826 Add out_of_band_inline socket option.
7f849376c Expose the system_executor's execution context as system_context.
9f62b6791 Update io_context run* documentation.
ac89cf0ba Enable newer language features for recent MSVC versions.
64ae9bcae Add alias templates for associators.
e502a6b36 Use shorter enum name resolver_errc::try_again.
b3ebdd8f6 Use ADL for calls to buffer_size.
c516cd591 Fix non-dereferencing pointer overflow in basic_streambuf::commit.
b8a34a1dc Fix work counting issue in asynchronous resolver implementation.
48e7ef864 is_continuation misplaced in reactive socket service
5adce6e26 Use poll.h rather than sys/poll.h if possible.
ddef4994f Avoid exception throwing from `make_network_v{4,6}(str, ec)`
0442bc922 Disable Boost.Chrono's dependency on Boost.System.
6c5b04eff Conditionally enable iostream move constructor and assignment.
a3bba3394 Fix version check for string_view.
246f387e7 Fix compile error on gcc 4.8.
fd024792c Add -lrt when linking on linux.
0921ab3db Simplify automatic detection of boost source distributions.
6b34f88a5 Make SSL/TLS version handling more consistent across OpenSSL versions.
1517bd1a1 Add travis and appveyor configuration.
70249b796 Use GetModuleHandleA rather than GetModuleHandle.
582ed12f7 Update copyright notices.
b6ac42dde Remove unused error code variable.
d52f28a09 Add missing rvalue cast in use_future implementation.
b33b3ae01 Unlocked reactor I/O implies a concurrency hint of 1.
cf351c44a Don't use non-portable sockaddr_storage member ss_len.
bbe092b3d Simplify and improve performance of executor operations.
e5acea17d Add shallow-constness to strands.
00a85845e Eliminate redundant copy as executors are now shallow-const.

git-subtree-dir: OpenVPN Adapter/Vendors/asio
git-subtree-split: 82be891ba69c65be4c684d709d78a225da69c3c5
2018-05-03 12:28:44 +03:00

612 lines
16 KiB
C++

//
// bind_executor.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 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_BIND_EXECUTOR_HPP
#define ASIO_BIND_EXECUTOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/detail/variadic_templates.hpp"
#include "asio/associated_executor.hpp"
#include "asio/associated_allocator.hpp"
#include "asio/async_result.hpp"
#include "asio/execution_context.hpp"
#include "asio/is_executor.hpp"
#include "asio/uses_executor.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
template <typename T>
struct executor_binder_check
{
typedef void type;
};
// Helper to automatically define nested typedef result_type.
template <typename T, typename = void>
struct executor_binder_result_type
{
protected:
typedef void result_type_or_void;
};
template <typename T>
struct executor_binder_result_type<T,
typename executor_binder_check<typename T::result_type>::type>
{
typedef typename T::result_type result_type;
protected:
typedef result_type result_type_or_void;
};
template <typename R>
struct executor_binder_result_type<R(*)()>
{
typedef R result_type;
protected:
typedef result_type result_type_or_void;
};
template <typename R>
struct executor_binder_result_type<R(&)()>
{
typedef R result_type;
protected:
typedef result_type result_type_or_void;
};
template <typename R, typename A1>
struct executor_binder_result_type<R(*)(A1)>
{
typedef R result_type;
protected:
typedef result_type result_type_or_void;
};
template <typename R, typename A1>
struct executor_binder_result_type<R(&)(A1)>
{
typedef R result_type;
protected:
typedef result_type result_type_or_void;
};
template <typename R, typename A1, typename A2>
struct executor_binder_result_type<R(*)(A1, A2)>
{
typedef R result_type;
protected:
typedef result_type result_type_or_void;
};
template <typename R, typename A1, typename A2>
struct executor_binder_result_type<R(&)(A1, A2)>
{
typedef R result_type;
protected:
typedef result_type result_type_or_void;
};
// Helper to automatically define nested typedef argument_type.
template <typename T, typename = void>
struct executor_binder_argument_type {};
template <typename T>
struct executor_binder_argument_type<T,
typename executor_binder_check<typename T::argument_type>::type>
{
typedef typename T::argument_type argument_type;
};
template <typename R, typename A1>
struct executor_binder_argument_type<R(*)(A1)>
{
typedef A1 argument_type;
};
template <typename R, typename A1>
struct executor_binder_argument_type<R(&)(A1)>
{
typedef A1 argument_type;
};
// Helper to automatically define nested typedefs first_argument_type and
// second_argument_type.
template <typename T, typename = void>
struct executor_binder_argument_types {};
template <typename T>
struct executor_binder_argument_types<T,
typename executor_binder_check<typename T::first_argument_type>::type>
{
typedef typename T::first_argument_type first_argument_type;
typedef typename T::second_argument_type second_argument_type;
};
template <typename R, typename A1, typename A2>
struct executor_binder_argument_type<R(*)(A1, A2)>
{
typedef A1 first_argument_type;
typedef A2 second_argument_type;
};
template <typename R, typename A1, typename A2>
struct executor_binder_argument_type<R(&)(A1, A2)>
{
typedef A1 first_argument_type;
typedef A2 second_argument_type;
};
// Helper to:
// - Apply the empty base optimisation to the executor.
// - Perform uses_executor construction of the target type, if required.
template <typename T, typename Executor, bool UsesExecutor>
class executor_binder_base;
template <typename T, typename Executor>
class executor_binder_base<T, Executor, true>
: protected Executor
{
protected:
template <typename E, typename U>
executor_binder_base(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(U) u)
: executor_(ASIO_MOVE_CAST(E)(e)),
target_(executor_arg_t(), executor_, ASIO_MOVE_CAST(U)(u))
{
}
Executor executor_;
T target_;
};
template <typename T, typename Executor>
class executor_binder_base<T, Executor, false>
{
protected:
template <typename E, typename U>
executor_binder_base(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(U) u)
: executor_(ASIO_MOVE_CAST(E)(e)),
target_(ASIO_MOVE_CAST(U)(u))
{
}
Executor executor_;
T target_;
};
// Helper to enable SFINAE on zero-argument operator() below.
template <typename T, typename = void>
struct executor_binder_result_of0
{
typedef void type;
};
template <typename T>
struct executor_binder_result_of0<T,
typename executor_binder_check<typename result_of<T()>::type>::type>
{
typedef typename result_of<T()>::type type;
};
} // namespace detail
/// A call wrapper type to bind an executor of type @c Executor to an object of
/// type @c T.
template <typename T, typename Executor>
class executor_binder
#if !defined(GENERATING_DOCUMENTATION)
: public detail::executor_binder_result_type<T>,
public detail::executor_binder_argument_type<T>,
public detail::executor_binder_argument_types<T>,
private detail::executor_binder_base<
T, Executor, uses_executor<T, Executor>::value>
#endif // !defined(GENERATING_DOCUMENTATION)
{
public:
/// The type of the target object.
typedef T target_type;
/// The type of the associated executor.
typedef Executor executor_type;
#if defined(GENERATING_DOCUMENTATION)
/// The return type if a function.
/**
* The type of @c result_type is based on the type @c T of the wrapper's
* target object:
*
* @li if @c T is a pointer to function type, @c result_type is a synonym for
* the return type of @c T;
*
* @li if @c T is a class type with a member type @c result_type, then @c
* result_type is a synonym for @c T::result_type;
*
* @li otherwise @c result_type is not defined.
*/
typedef see_below result_type;
/// The type of the function's argument.
/**
* The type of @c argument_type is based on the type @c T of the wrapper's
* target object:
*
* @li if @c T is a pointer to a function type accepting a single argument,
* @c argument_type is a synonym for the return type of @c T;
*
* @li if @c T is a class type with a member type @c argument_type, then @c
* argument_type is a synonym for @c T::argument_type;
*
* @li otherwise @c argument_type is not defined.
*/
typedef see_below argument_type;
/// The type of the function's first argument.
/**
* The type of @c first_argument_type is based on the type @c T of the
* wrapper's target object:
*
* @li if @c T is a pointer to a function type accepting two arguments, @c
* first_argument_type is a synonym for the return type of @c T;
*
* @li if @c T is a class type with a member type @c first_argument_type,
* then @c first_argument_type is a synonym for @c T::first_argument_type;
*
* @li otherwise @c first_argument_type is not defined.
*/
typedef see_below first_argument_type;
/// The type of the function's second argument.
/**
* The type of @c second_argument_type is based on the type @c T of the
* wrapper's target object:
*
* @li if @c T is a pointer to a function type accepting two arguments, @c
* second_argument_type is a synonym for the return type of @c T;
*
* @li if @c T is a class type with a member type @c first_argument_type,
* then @c second_argument_type is a synonym for @c T::second_argument_type;
*
* @li otherwise @c second_argument_type is not defined.
*/
typedef see_below second_argument_type;
#endif // defined(GENERATING_DOCUMENTATION)
/// Construct an executor wrapper for the specified object.
/**
* This constructor is only valid if the type @c T is constructible from type
* @c U.
*/
template <typename U>
executor_binder(executor_arg_t, const executor_type& e,
ASIO_MOVE_ARG(U) u)
: base_type(e, ASIO_MOVE_CAST(U)(u))
{
}
/// Copy constructor.
executor_binder(const executor_binder& other)
: base_type(other.get_executor(), other.get())
{
}
/// Construct a copy, but specify a different executor.
executor_binder(executor_arg_t, const executor_type& e,
const executor_binder& other)
: base_type(e, other.get())
{
}
/// Construct a copy of a different executor wrapper type.
/**
* This constructor is only valid if the @c Executor type is constructible
* from type @c OtherExecutor, and the type @c T is constructible from type
* @c U.
*/
template <typename U, typename OtherExecutor>
executor_binder(const executor_binder<U, OtherExecutor>& other)
: base_type(other.get_executor(), other.get())
{
}
/// Construct a copy of a different executor wrapper type, but specify a
/// different executor.
/**
* This constructor is only valid if the type @c T is constructible from type
* @c U.
*/
template <typename U, typename OtherExecutor>
executor_binder(executor_arg_t, const executor_type& e,
const executor_binder<U, OtherExecutor>& other)
: base_type(e, other.get())
{
}
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move constructor.
executor_binder(executor_binder&& other)
: base_type(ASIO_MOVE_CAST(executor_type)(other.get_executor()),
ASIO_MOVE_CAST(T)(other.get()))
{
}
/// Move construct the target object, but specify a different executor.
executor_binder(executor_arg_t, const executor_type& e,
executor_binder&& other)
: base_type(e, ASIO_MOVE_CAST(T)(other.get()))
{
}
/// Move construct from a different executor wrapper type.
template <typename U, typename OtherExecutor>
executor_binder(executor_binder<U, OtherExecutor>&& other)
: base_type(ASIO_MOVE_CAST(OtherExecutor)(other.get_executor()),
ASIO_MOVE_CAST(U)(other.get()))
{
}
/// Move construct from a different executor wrapper type, but specify a
/// different executor.
template <typename U, typename OtherExecutor>
executor_binder(executor_arg_t, const executor_type& e,
executor_binder<U, OtherExecutor>&& other)
: base_type(e, ASIO_MOVE_CAST(U)(other.get()))
{
}
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Destructor.
~executor_binder()
{
}
/// Obtain a reference to the target object.
target_type& get() ASIO_NOEXCEPT
{
return this->target_;
}
/// Obtain a reference to the target object.
const target_type& get() const ASIO_NOEXCEPT
{
return this->target_;
}
/// Obtain the associated executor.
executor_type get_executor() const ASIO_NOEXCEPT
{
return this->executor_;
}
#if defined(GENERATING_DOCUMENTATION)
template <typename... Args> auto operator()(Args&& ...);
template <typename... Args> auto operator()(Args&& ...) const;
#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)
/// Forwarding function call operator.
template <typename... Args>
typename result_of<T(Args...)>::type operator()(
ASIO_MOVE_ARG(Args)... args)
{
return this->target_(ASIO_MOVE_CAST(Args)(args)...);
}
/// Forwarding function call operator.
template <typename... Args>
typename result_of<T(Args...)>::type operator()(
ASIO_MOVE_ARG(Args)... args) const
{
return this->target_(ASIO_MOVE_CAST(Args)(args)...);
}
#elif defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
typename detail::executor_binder_result_of0<T>::type operator()()
{
return this->target_();
}
typename detail::executor_binder_result_of0<T>::type operator()() const
{
return this->target_();
}
#define ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF(n) \
template <ASIO_VARIADIC_TPARAMS(n)> \
typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \
ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
\
template <ASIO_VARIADIC_TPARAMS(n)> \
typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \
ASIO_VARIADIC_MOVE_PARAMS(n)) const \
{ \
return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF)
#undef ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF
#else // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
typedef typename detail::executor_binder_result_type<T>::result_type_or_void
result_type_or_void;
result_type_or_void operator()()
{
return this->target_();
}
result_type_or_void operator()() const
{
return this->target_();
}
#define ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF(n) \
template <ASIO_VARIADIC_TPARAMS(n)> \
result_type_or_void operator()( \
ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
\
template <ASIO_VARIADIC_TPARAMS(n)> \
result_type_or_void operator()( \
ASIO_VARIADIC_MOVE_PARAMS(n)) const \
{ \
return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF)
#undef ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF
#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
private:
typedef detail::executor_binder_base<T, Executor,
uses_executor<T, Executor>::value> base_type;
};
/// Associate an object of type @c T with an executor of type @c Executor.
template <typename Executor, typename T>
inline executor_binder<typename decay<T>::type, Executor>
bind_executor(const Executor& ex, ASIO_MOVE_ARG(T) t,
typename enable_if<is_executor<Executor>::value>::type* = 0)
{
return executor_binder<typename decay<T>::type, Executor>(
executor_arg_t(), ex, ASIO_MOVE_CAST(T)(t));
}
/// Associate an object of type @c T with an execution context's executor.
template <typename ExecutionContext, typename T>
inline executor_binder<typename decay<T>::type,
typename ExecutionContext::executor_type>
bind_executor(ExecutionContext& ctx, ASIO_MOVE_ARG(T) t,
typename enable_if<is_convertible<
ExecutionContext&, execution_context&>::value>::type* = 0)
{
return executor_binder<typename decay<T>::type,
typename ExecutionContext::executor_type>(
executor_arg_t(), ctx.get_executor(), ASIO_MOVE_CAST(T)(t));
}
#if !defined(GENERATING_DOCUMENTATION)
template <typename T, typename Executor>
struct uses_executor<executor_binder<T, Executor>, Executor>
: true_type {};
template <typename T, typename Executor, typename Signature>
class async_result<executor_binder<T, Executor>, Signature>
{
public:
typedef executor_binder<
typename async_result<T, Signature>::completion_handler_type, Executor>
completion_handler_type;
typedef typename async_result<T, Signature>::return_type return_type;
explicit async_result(executor_binder<T, Executor>& b)
: target_(b.get())
{
}
return_type get()
{
return target_.get();
}
private:
async_result(const async_result&) ASIO_DELETED;
async_result& operator=(const async_result&) ASIO_DELETED;
async_result<T, Signature> target_;
};
#if !defined(ASIO_NO_DEPRECATED)
template <typename T, typename Executor, typename Signature>
struct handler_type<executor_binder<T, Executor>, Signature>
{
typedef executor_binder<
typename handler_type<T, Signature>::type, Executor> type;
};
template <typename T, typename Executor>
class async_result<executor_binder<T, Executor> >
{
public:
typedef typename async_result<T>::type type;
explicit async_result(executor_binder<T, Executor>& b)
: target_(b.get())
{
}
type get()
{
return target_.get();
}
private:
async_result<T> target_;
};
#endif // !defined(ASIO_NO_DEPRECATED)
template <typename T, typename Executor, typename Allocator>
struct associated_allocator<executor_binder<T, Executor>, Allocator>
{
typedef typename associated_allocator<T, Allocator>::type type;
static type get(const executor_binder<T, Executor>& b,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<T, Allocator>::get(b.get(), a);
}
};
template <typename T, typename Executor, typename Executor1>
struct associated_executor<executor_binder<T, Executor>, Executor1>
{
typedef Executor type;
static type get(const executor_binder<T, Executor>& b,
const Executor1& = Executor1()) ASIO_NOEXCEPT
{
return b.get_executor();
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BIND_EXECUTOR_HPP