Make is_executor<> trait automatic.

This commit is contained in:
Christopher Kohlhoff 2016-08-10 19:36:11 +10:00
parent 3dd8a77afa
commit a1f71f95c4
16 changed files with 146 additions and 68 deletions

View File

@ -21,6 +21,7 @@
#include "asio/associated_allocator.hpp"
#include "asio/async_result.hpp"
#include "asio/handler_type.hpp"
#include "asio/is_executor.hpp"
#include "asio/uses_executor.hpp"
#include "asio/detail/push_options.hpp"
@ -166,27 +167,27 @@ class executor_binder_base<T, Executor, true>
protected:
template <typename E, typename U>
executor_binder_base(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(U) u)
: Executor(ASIO_MOVE_CAST(E)(e)),
target_(executor_arg_t(), static_cast<const Executor&>(*this),
ASIO_MOVE_CAST(U)(u))
: executor_(ASIO_MOVE_CAST(E)(e)),
target_(executor_arg_t(), executor_, ASIO_MOVE_CAST(U)(u))
{
}
Executor executor_;
T target_;
};
template <typename T, typename Executor>
class executor_binder_base<T, Executor, false>
: protected Executor
{
protected:
template <typename E, typename U>
executor_binder_base(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(U) u)
: Executor(ASIO_MOVE_CAST(E)(e)),
: executor_(ASIO_MOVE_CAST(E)(e)),
target_(ASIO_MOVE_CAST(U)(u))
{
}
Executor executor_;
T target_;
};
@ -393,7 +394,7 @@ public:
/// Obtain the associated executor.
executor_type get_executor() const ASIO_NOEXCEPT
{
return static_cast<const Executor&>(*this);
return this->executor_;
}
#if defined(GENERATING_DOCUMENTATION)

View File

@ -0,0 +1,126 @@
//
// detail/is_executor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_IS_EXECUTOR_HPP
#define ASIO_DETAIL_IS_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/push_options.hpp"
namespace asio {
namespace detail {
struct executor_memfns_base
{
void context();
void on_work_started();
void on_work_finished();
void dispatch();
void post();
void defer();
};
template <typename T>
struct executor_memfns_derived
: T, executor_memfns_base
{
};
template <typename T, T>
struct executor_memfns_check
{
};
template <typename>
char (&context_memfn_helper(...))[2];
template <typename T>
char context_memfn_helper(
executor_memfns_check<
void (executor_memfns_base::*)(),
&executor_memfns_derived<T>::context>*);
template <typename>
char (&on_work_started_memfn_helper(...))[2];
template <typename T>
char on_work_started_memfn_helper(
executor_memfns_check<
void (executor_memfns_base::*)(),
&executor_memfns_derived<T>::on_work_started>*);
template <typename>
char (&on_work_finished_memfn_helper(...))[2];
template <typename T>
char on_work_finished_memfn_helper(
executor_memfns_check<
void (executor_memfns_base::*)(),
&executor_memfns_derived<T>::on_work_finished>*);
template <typename>
char (&dispatch_memfn_helper(...))[2];
template <typename T>
char dispatch_memfn_helper(
executor_memfns_check<
void (executor_memfns_base::*)(),
&executor_memfns_derived<T>::dispatch>*);
template <typename>
char (&post_memfn_helper(...))[2];
template <typename T>
char post_memfn_helper(
executor_memfns_check<
void (executor_memfns_base::*)(),
&executor_memfns_derived<T>::post>*);
template <typename>
char (&defer_memfn_helper(...))[2];
template <typename T>
char defer_memfn_helper(
executor_memfns_check<
void (executor_memfns_base::*)(),
&executor_memfns_derived<T>::defer>*);
template <typename T>
struct is_executor_class
: integral_constant<bool,
sizeof(context_memfn_helper<T>(0)) != 1 &&
sizeof(on_work_started_memfn_helper<T>(0)) != 1 &&
sizeof(on_work_finished_memfn_helper<T>(0)) != 1 &&
sizeof(dispatch_memfn_helper<T>(0)) != 1 &&
sizeof(post_memfn_helper<T>(0)) != 1 &&
sizeof(defer_memfn_helper<T>(0)) != 1>
{
};
template <typename T>
struct is_executor
: conditional<is_class<T>::value,
is_executor_class<T>,
false_type>::type
{
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_IS_EXECUTOR_HPP

View File

@ -21,7 +21,6 @@
#include "asio/detail/memory.hpp"
#include "asio/detail/throw_exception.hpp"
#include "asio/execution_context.hpp"
#include "asio/is_executor.hpp"
#include "asio/detail/push_options.hpp"
@ -328,10 +327,6 @@ private:
#endif // !defined(GENERATING_DOCUMENTATION)
};
#if !defined(GENERATING_DOCUMENTATION)
template <> struct is_executor<executor> : true_type {};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
ASIO_USES_ALLOCATOR(asio::executor)

View File

@ -18,6 +18,7 @@
#include "asio/detail/config.hpp"
#include "asio/associated_executor.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/is_executor.hpp"
#include "asio/detail/push_options.hpp"

View File

@ -24,7 +24,6 @@
#include "asio/detail/wrapped_handler.hpp"
#include "asio/error_code.hpp"
#include "asio/execution_context.hpp"
#include "asio/is_executor.hpp"
#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
# include "asio/detail/winsock_init.hpp"
@ -611,11 +610,6 @@ private:
io_context& io_context_;
};
#if !defined(GENERATING_DOCUMENTATION)
template <> struct is_executor<io_context::executor_type> : true_type {};
#endif // !defined(GENERATING_DOCUMENTATION)
/// (Deprecated: Use executor_work_guard.) Class to inform the io_context when
/// it has work to do.
/**

View File

@ -370,11 +370,6 @@ private:
asio::detail::strand_service::implementation_type impl_;
};
#if !defined(GENERATING_DOCUMENTATION)
template <>
struct is_executor<io_context::strand> : true_type {};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
#include "asio/detail/pop_options.hpp"

View File

@ -16,7 +16,7 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/detail/is_executor.hpp"
#include "asio/detail/push_options.hpp"
@ -25,13 +25,19 @@ namespace asio {
/// The is_executor trait detects whether a type T meets the Executor type
/// requirements.
/**
* Meets the UnaryTypeTrait requirements. The asio library implementation
* provides a definition that is derived from false_type. A program may
* specialise this template to derive from true_type for a user-defined type T
* that meets the Executor requirements.
* Class template @c is_executor is a UnaryTypeTrait that is derived from @c
* true_type if the type @c T meets the syntactic requirements for Executor,
* otherwise @c false_type.
*/
template <typename T>
struct is_executor : false_type {};
struct is_executor
#if defined(GENERATING_DOCUMENTATION)
: integral_constant<bool, automatically_determined>
#else // defined(GENERATING_DOCUMENTATION)
: asio::detail::is_executor<T>
#endif // defined(GENERATING_DOCUMENTATION)
{
};
} // namespace asio

View File

@ -18,7 +18,6 @@
#include "asio/detail/config.hpp"
#include "asio/detail/strand_executor_service.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/is_executor.hpp"
#include "asio/detail/push_options.hpp"
@ -272,11 +271,6 @@ private:
implementation_type impl_;
};
#if !defined(GENERATING_DOCUMENTATION)
template <typename Executor>
struct is_executor<strand<Executor> > : true_type {};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
#include "asio/detail/pop_options.hpp"

View File

@ -19,7 +19,6 @@
#include "asio/detail/scheduler.hpp"
#include "asio/detail/thread_group.hpp"
#include "asio/execution_context.hpp"
#include "asio/is_executor.hpp"
#include "asio/detail/push_options.hpp"
@ -142,10 +141,6 @@ private:
};
};
#if !defined(GENERATING_DOCUMENTATION)
template <> struct is_executor<system_executor> : true_type {};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
#include "asio/detail/pop_options.hpp"

View File

@ -20,7 +20,6 @@
#include "asio/detail/scheduler.hpp"
#include "asio/detail/thread_group.hpp"
#include "asio/execution_context.hpp"
#include "asio/is_executor.hpp"
#include "asio/detail/push_options.hpp"
@ -191,10 +190,6 @@ private:
thread_pool& pool_;
};
#if !defined(GENERATING_DOCUMENTATION)
template <> struct is_executor<thread_pool::executor_type> : true_type {};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
#include "asio/detail/pop_options.hpp"

View File

@ -252,10 +252,6 @@ private:
std::shared_ptr<std::size_t> work_count_;
};
namespace asio {
template <> struct is_executor<fork_executor> : std::true_type {};
}
// Helper class to automatically join a fork_executor when exiting a scope.
class join_guard
{

View File

@ -101,10 +101,6 @@ public:
execution_context::id thread_executor::thread_bag::id;
namespace asio {
template <> struct is_executor<thread_executor> : std::true_type {};
}
// Base class for all thread-safe queue implementations.
class queue_impl_base
{

View File

@ -145,10 +145,6 @@ private:
bool stopped_ = false;
};
namespace asio {
template <> struct is_executor<priority_scheduler::executor_type> : std::true_type {};
}
int main()
{
priority_scheduler sched;

View File

@ -251,10 +251,6 @@ private:
std::shared_ptr<std::size_t> work_count_;
};
namespace asio {
template <> struct is_executor<fork_executor> : std::true_type {};
}
// Helper class to automatically join a fork_executor when exiting a scope.
class join_guard
{

View File

@ -96,10 +96,6 @@ public:
execution_context::id thread_executor::thread_bag::id;
namespace asio {
template <> struct is_executor<thread_executor> : std::true_type {};
}
// Base class for all thread-safe queue implementations.
class queue_impl_base
{

View File

@ -144,10 +144,6 @@ private:
bool stopped_ = false;
};
namespace asio {
template <> struct is_executor<priority_scheduler::executor_type> : std::true_type {};
}
int main()
{
priority_scheduler sched;