From a1f71f95c4b81e56904898f3e77e3c81f39597f3 Mon Sep 17 00:00:00 2001 From: Christopher Kohlhoff Date: Wed, 10 Aug 2016 19:36:11 +1000 Subject: [PATCH] Make is_executor<> trait automatic. --- asio/include/asio/bind_executor.hpp | 13 +- asio/include/asio/detail/is_executor.hpp | 126 ++++++++++++++++++ asio/include/asio/executor.hpp | 5 - asio/include/asio/executor_work_guard.hpp | 1 + asio/include/asio/io_context.hpp | 6 - asio/include/asio/io_context_strand.hpp | 5 - asio/include/asio/is_executor.hpp | 18 ++- asio/include/asio/strand.hpp | 6 - asio/include/asio/system_executor.hpp | 5 - asio/include/asio/thread_pool.hpp | 5 - .../examples/cpp11/executors/fork_join.cpp | 4 - .../src/examples/cpp11/executors/pipeline.cpp | 4 - .../cpp11/executors/priority_scheduler.cpp | 4 - .../examples/cpp14/executors/fork_join.cpp | 4 - .../src/examples/cpp14/executors/pipeline.cpp | 4 - .../cpp14/executors/priority_scheduler.cpp | 4 - 16 files changed, 146 insertions(+), 68 deletions(-) create mode 100644 asio/include/asio/detail/is_executor.hpp diff --git a/asio/include/asio/bind_executor.hpp b/asio/include/asio/bind_executor.hpp index 562ce189..f74a8e3a 100644 --- a/asio/include/asio/bind_executor.hpp +++ b/asio/include/asio/bind_executor.hpp @@ -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 protected: template 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(*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 class executor_binder_base - : protected Executor { protected: template 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(*this); + return this->executor_; } #if defined(GENERATING_DOCUMENTATION) diff --git a/asio/include/asio/detail/is_executor.hpp b/asio/include/asio/detail/is_executor.hpp new file mode 100644 index 00000000..e5f57b1d --- /dev/null +++ b/asio/include/asio/detail/is_executor.hpp @@ -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 +struct executor_memfns_derived + : T, executor_memfns_base +{ +}; + +template +struct executor_memfns_check +{ +}; + +template +char (&context_memfn_helper(...))[2]; + +template +char context_memfn_helper( + executor_memfns_check< + void (executor_memfns_base::*)(), + &executor_memfns_derived::context>*); + +template +char (&on_work_started_memfn_helper(...))[2]; + +template +char on_work_started_memfn_helper( + executor_memfns_check< + void (executor_memfns_base::*)(), + &executor_memfns_derived::on_work_started>*); + +template +char (&on_work_finished_memfn_helper(...))[2]; + +template +char on_work_finished_memfn_helper( + executor_memfns_check< + void (executor_memfns_base::*)(), + &executor_memfns_derived::on_work_finished>*); + +template +char (&dispatch_memfn_helper(...))[2]; + +template +char dispatch_memfn_helper( + executor_memfns_check< + void (executor_memfns_base::*)(), + &executor_memfns_derived::dispatch>*); + +template +char (&post_memfn_helper(...))[2]; + +template +char post_memfn_helper( + executor_memfns_check< + void (executor_memfns_base::*)(), + &executor_memfns_derived::post>*); + +template +char (&defer_memfn_helper(...))[2]; + +template +char defer_memfn_helper( + executor_memfns_check< + void (executor_memfns_base::*)(), + &executor_memfns_derived::defer>*); + +template +struct is_executor_class + : integral_constant(0)) != 1 && + sizeof(on_work_started_memfn_helper(0)) != 1 && + sizeof(on_work_finished_memfn_helper(0)) != 1 && + sizeof(dispatch_memfn_helper(0)) != 1 && + sizeof(post_memfn_helper(0)) != 1 && + sizeof(defer_memfn_helper(0)) != 1> +{ +}; + +template +struct is_executor + : conditional::value, + is_executor_class, + false_type>::type +{ +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_IS_EXECUTOR_HPP diff --git a/asio/include/asio/executor.hpp b/asio/include/asio/executor.hpp index d1d6fd3c..928c6be9 100644 --- a/asio/include/asio/executor.hpp +++ b/asio/include/asio/executor.hpp @@ -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 : true_type {}; -#endif // !defined(GENERATING_DOCUMENTATION) - } // namespace asio ASIO_USES_ALLOCATOR(asio::executor) diff --git a/asio/include/asio/executor_work_guard.hpp b/asio/include/asio/executor_work_guard.hpp index 5774d210..1906af8b 100644 --- a/asio/include/asio/executor_work_guard.hpp +++ b/asio/include/asio/executor_work_guard.hpp @@ -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" diff --git a/asio/include/asio/io_context.hpp b/asio/include/asio/io_context.hpp index 96a0a339..f18414d6 100644 --- a/asio/include/asio/io_context.hpp +++ b/asio/include/asio/io_context.hpp @@ -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 : true_type {}; -#endif // !defined(GENERATING_DOCUMENTATION) - - /// (Deprecated: Use executor_work_guard.) Class to inform the io_context when /// it has work to do. /** diff --git a/asio/include/asio/io_context_strand.hpp b/asio/include/asio/io_context_strand.hpp index 8fe6c14f..78bb8547 100644 --- a/asio/include/asio/io_context_strand.hpp +++ b/asio/include/asio/io_context_strand.hpp @@ -370,11 +370,6 @@ private: asio::detail::strand_service::implementation_type impl_; }; -#if !defined(GENERATING_DOCUMENTATION) -template <> -struct is_executor : true_type {}; -#endif // !defined(GENERATING_DOCUMENTATION) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/asio/include/asio/is_executor.hpp b/asio/include/asio/is_executor.hpp index 59981ad9..10f7d24d 100644 --- a/asio/include/asio/is_executor.hpp +++ b/asio/include/asio/is_executor.hpp @@ -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 -struct is_executor : false_type {}; +struct is_executor +#if defined(GENERATING_DOCUMENTATION) + : integral_constant +#else // defined(GENERATING_DOCUMENTATION) + : asio::detail::is_executor +#endif // defined(GENERATING_DOCUMENTATION) +{ +}; } // namespace asio diff --git a/asio/include/asio/strand.hpp b/asio/include/asio/strand.hpp index 488b540c..17a5ffcb 100644 --- a/asio/include/asio/strand.hpp +++ b/asio/include/asio/strand.hpp @@ -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 -struct is_executor > : true_type {}; -#endif // !defined(GENERATING_DOCUMENTATION) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/asio/include/asio/system_executor.hpp b/asio/include/asio/system_executor.hpp index e227687f..73180fd0 100644 --- a/asio/include/asio/system_executor.hpp +++ b/asio/include/asio/system_executor.hpp @@ -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 : true_type {}; -#endif // !defined(GENERATING_DOCUMENTATION) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/asio/include/asio/thread_pool.hpp b/asio/include/asio/thread_pool.hpp index f3182bfc..f1935065 100644 --- a/asio/include/asio/thread_pool.hpp +++ b/asio/include/asio/thread_pool.hpp @@ -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 : true_type {}; -#endif // !defined(GENERATING_DOCUMENTATION) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/asio/src/examples/cpp11/executors/fork_join.cpp b/asio/src/examples/cpp11/executors/fork_join.cpp index f9dcdb39..c9961247 100644 --- a/asio/src/examples/cpp11/executors/fork_join.cpp +++ b/asio/src/examples/cpp11/executors/fork_join.cpp @@ -252,10 +252,6 @@ private: std::shared_ptr work_count_; }; -namespace asio { - template <> struct is_executor : std::true_type {}; -} - // Helper class to automatically join a fork_executor when exiting a scope. class join_guard { diff --git a/asio/src/examples/cpp11/executors/pipeline.cpp b/asio/src/examples/cpp11/executors/pipeline.cpp index 4159333d..a851e983 100644 --- a/asio/src/examples/cpp11/executors/pipeline.cpp +++ b/asio/src/examples/cpp11/executors/pipeline.cpp @@ -101,10 +101,6 @@ public: execution_context::id thread_executor::thread_bag::id; -namespace asio { - template <> struct is_executor : std::true_type {}; -} - // Base class for all thread-safe queue implementations. class queue_impl_base { diff --git a/asio/src/examples/cpp11/executors/priority_scheduler.cpp b/asio/src/examples/cpp11/executors/priority_scheduler.cpp index 34bb5039..c98dd1d5 100644 --- a/asio/src/examples/cpp11/executors/priority_scheduler.cpp +++ b/asio/src/examples/cpp11/executors/priority_scheduler.cpp @@ -145,10 +145,6 @@ private: bool stopped_ = false; }; -namespace asio { - template <> struct is_executor : std::true_type {}; -} - int main() { priority_scheduler sched; diff --git a/asio/src/examples/cpp14/executors/fork_join.cpp b/asio/src/examples/cpp14/executors/fork_join.cpp index 918376ba..a0cafd64 100644 --- a/asio/src/examples/cpp14/executors/fork_join.cpp +++ b/asio/src/examples/cpp14/executors/fork_join.cpp @@ -251,10 +251,6 @@ private: std::shared_ptr work_count_; }; -namespace asio { - template <> struct is_executor : std::true_type {}; -} - // Helper class to automatically join a fork_executor when exiting a scope. class join_guard { diff --git a/asio/src/examples/cpp14/executors/pipeline.cpp b/asio/src/examples/cpp14/executors/pipeline.cpp index 77a5c0a2..1bee173f 100644 --- a/asio/src/examples/cpp14/executors/pipeline.cpp +++ b/asio/src/examples/cpp14/executors/pipeline.cpp @@ -96,10 +96,6 @@ public: execution_context::id thread_executor::thread_bag::id; -namespace asio { - template <> struct is_executor : std::true_type {}; -} - // Base class for all thread-safe queue implementations. class queue_impl_base { diff --git a/asio/src/examples/cpp14/executors/priority_scheduler.cpp b/asio/src/examples/cpp14/executors/priority_scheduler.cpp index 37665082..ae2ea184 100644 --- a/asio/src/examples/cpp14/executors/priority_scheduler.cpp +++ b/asio/src/examples/cpp14/executors/priority_scheduler.cpp @@ -144,10 +144,6 @@ private: bool stopped_ = false; }; -namespace asio { - template <> struct is_executor : std::true_type {}; -} - int main() { priority_scheduler sched;