From 5ab9a7667ad26eef4b5ba0b575596536f6b0fd84 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Fri, 7 Aug 2015 12:09:34 -0500 Subject: [PATCH] Implement parallel::executor_traits for thread-executors - this unifies the two executor categories we have - introduce a new threads::service_executor type as a generic equivalent to the pre-existing concrete service-executors - minor fly-by changes to the parallel::executor_traits main template --- .../executors/detail/thread_executor.hpp | 63 ----- hpx/parallel/executors/executor_traits.hpp | 14 +- hpx/parallel/executors/service_executors.hpp | 69 +----- .../executors/this_thread_executors.hpp | 55 +---- .../executors/thread_executor_traits.hpp | 223 ++++++++++++++++++ .../executors/thread_pool_executors.hpp | 123 ++++------ .../threads/executors/service_executors.hpp | 81 ++++++- .../executors/this_thread_executors.hpp | 1 - .../executors/thread_pool_executors.hpp | 3 +- .../parallel/executors/service_executors.cpp | 2 +- 10 files changed, 359 insertions(+), 275 deletions(-) delete mode 100644 hpx/parallel/executors/detail/thread_executor.hpp create mode 100644 hpx/parallel/executors/thread_executor_traits.hpp diff --git a/hpx/parallel/executors/detail/thread_executor.hpp b/hpx/parallel/executors/detail/thread_executor.hpp deleted file mode 100644 index e0c42db22e2a..000000000000 --- a/hpx/parallel/executors/detail/thread_executor.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2007-2015 Hartmut Kaiser -// -// 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) - -/// \file parallel/executors/thread_executor.hpp - -#if !defined(HPX_PARALLEL_EXECUTORS_THREAD_EXECUTOR_MAY_15_2015_0546PM) -#define HPX_PARALLEL_EXECUTORS_THREAD_EXECUTOR_MAY_15_2015_0546PM - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v3) -{ - /////////////////////////////////////////////////////////////////////////// - namespace detail - { - /// \cond NOINTERNAL - struct threads_executor : executor_tag - { - // Associate the auto_chunk_size executor parameters type as a - // default with all executors derived from this. - typedef auto_chunk_size executor_parameters_type; - - threads_executor(threads::executor exec) - : exec_(exec) - {} - - template - hpx::future::type() - >::type> - async_execute(F && f) - { - return hpx::async(exec_, std::forward(f)); - } - - std::size_t os_thread_count() - { - return hpx::get_os_thread_count(exec_); - } - - bool has_pending_closures() const - { - return exec_.num_pending_closures() != 0; - } - - private: - threads::executor exec_; - }; - /// \endcond - } -}}} - -#endif diff --git a/hpx/parallel/executors/executor_traits.hpp b/hpx/parallel/executors/executor_traits.hpp index 001fb255300a..6b7169988f76 100644 --- a/hpx/parallel/executors/executor_traits.hpp +++ b/hpx/parallel/executors/executor_traits.hpp @@ -13,13 +13,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -207,9 +205,9 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v3) for (auto const& elem: shape) { - results.push_back( - exec.async_execute(hpx::util::deferred_call(f, elem)) - ); + results.push_back(exec.async_execute( + hpx::util::deferred_call(std::forward(f), elem) + )); } return results; @@ -267,9 +265,9 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v3) for (auto const& elem: shape) { - results.push_back( - exec.async_execute(hpx::util::deferred_call(f, elem)) - ); + results.push_back(exec.async_execute( + hpx::util::deferred_call(std::forward(f), elem) + )); } return hpx::util::unwrapped(results); diff --git a/hpx/parallel/executors/service_executors.hpp b/hpx/parallel/executors/service_executors.hpp index a075ccff0cfe..92e7e9fdf87e 100644 --- a/hpx/parallel/executors/service_executors.hpp +++ b/hpx/parallel/executors/service_executors.hpp @@ -9,68 +9,13 @@ #define HPX_PARALLEL_EXECUTORS_SERVICE_EXECUTORS_MAY_15_2015_0548PM #include +#include #include -#include +#include #include -#include -#include -#include - -#include - -#include namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v3) { - /////////////////////////////////////////////////////////////////////////// - /// The type of the HPX thread pool to use for a given service_executor - /// - /// This enum type allows to specify the kind of the HPX thread pool to use - /// for a given \a service_executor. - BOOST_SCOPED_ENUM_START(service_executor_type) - { - io_thread_pool, ///< Selects creating a service executor using - ///< the I/O pool of threads - parcel_thread_pool, ///< Selects creating a service executor using - ///< the parcel pool of threads - timer_thread_pool, ///< Selects creating a service executor using - ///< the timer pool of threads - main_thread ///< Selects creating a service executor using - ///< the main thread - }; - BOOST_SCOPED_ENUM_END - - namespace detail - { - /// \cond NOINTERNAL - inline threads::executor - get_service_executor(BOOST_SCOPED_ENUM(service_executor_type) t) - { - switch(t) - { - case service_executor_type::io_thread_pool: - return threads::executors::io_pool_executor(); - - case service_executor_type::parcel_thread_pool: - return threads::executors::parcel_pool_executor(); - - case service_executor_type::timer_thread_pool: - return threads::executors::timer_pool_executor(); - - case service_executor_type::main_thread: - return threads::executors::main_pool_executor(); - - default: - break; - } - - HPX_THROW_EXCEPTION(bad_parameter, - "hpx::parallel::v3::detail::get_service_executor", - "unknown pool executor type"); - } - /// \endcond - } - /// A \a service_executor exposes one of the predefined HPX thread pools /// through an executor interface. /// @@ -80,7 +25,7 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v3) /// struct service_executor #if !defined(DOXYGEN) - : detail::threads_executor + : threads::executors::service_executor #endif { // Associate the static_chunk_size executor parameters type as a default @@ -90,9 +35,13 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v3) /// Create a new service executor for the given HPX thread pool /// /// \param t [in] Specifies the HPX thread pool to encapsulate + /// \param name_suffix [in] The name suffix to use for the underlying + /// thread pool /// - service_executor(BOOST_SCOPED_ENUM(service_executor_type) t) - : threads_executor(detail::get_service_executor(t)) + service_executor( + BOOST_SCOPED_ENUM(threads::executors::service_executor_type) t, + char const* name_suffix = "") + : threads::executors::service_executor(t, name_suffix) {} }; }}} diff --git a/hpx/parallel/executors/this_thread_executors.hpp b/hpx/parallel/executors/this_thread_executors.hpp index 82e1b268a5ba..74f8b2532cb2 100644 --- a/hpx/parallel/executors/this_thread_executors.hpp +++ b/hpx/parallel/executors/this_thread_executors.hpp @@ -9,65 +9,22 @@ #define HPX_PARALLEL_EXECUTORS_THIS_THREAD_EXECUTORS_JUL_16_2015_0809PM #include -#include -#include -#include #include -#include - -#include +#include +#include namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v3) { /////////////////////////////////////////////////////////////////////////// #if defined(HPX_HAVE_STATIC_SCHEDULER) - struct this_thread_static_queue_executor -#if !defined(DOXYGEN) - : detail::threads_executor -#endif - { - /// Creates a new local_queue_executor - /// - explicit this_thread_static_queue_executor() - : threads_executor( - threads::executors::this_thread_static_queue_executor()) - {} - }; -#endif - -#if defined(HPX_HAVE_STATIC_PRIORITY_SCHEDULER) - struct this_thread_static_priority_queue_executor -#if !defined(DOXYGEN) - : detail::threads_executor -#endif - { - /// Creates a new static_priority_queue_executor - /// - explicit this_thread_static_priority_queue_executor() - : threads_executor( - threads::executors::this_thread_static_priority_queue_executor()) - {} - }; -#endif - - namespace detail - { - /// \cond NOINTERNAL -#if defined(HPX_HAVE_STATIC_SCHEDULER) - template <> - struct is_executor - : std::true_type - {}; + typedef threads::executors::this_thread_static_queue_executor + this_thread_static_queue_executor; #endif #if defined(HPX_HAVE_STATIC_PRIORITY_SCHEDULER) - template <> - struct is_executor - : std::true_type - {}; + typedef threads::executors::this_thread_static_priority_queue_executor + this_thread_static_priority_queue_executor; #endif - /// \endcond - } }}} #endif diff --git a/hpx/parallel/executors/thread_executor_traits.hpp b/hpx/parallel/executors/thread_executor_traits.hpp new file mode 100644 index 000000000000..79e6ea81b8a5 --- /dev/null +++ b/hpx/parallel/executors/thread_executor_traits.hpp @@ -0,0 +1,223 @@ +// Copyright (c) 2007-2015 Hartmut Kaiser +// +// 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) + +/// \file parallel/executors/thread_executor_traits.hpp + +#if !defined(HPX_PARALLEL_THREAD_EXECUTOR_TRAITS_AUG_07_2015_0826AM) +#define HPX_PARALLEL_THREAD_EXECUTOR_TRAITS_AUG_07_2015_0826AM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v3) +{ + /////////////////////////////////////////////////////////////////////////// + /// Specialization for executor_traits for types which conform to + /// traits::is_threads_executor + template + struct executor_traits::value + >::type> + { + /// The type of the executor associated with this instance of + /// \a executor_traits + typedef Executor executor_type; + + /// The category of agents created by the bulk-form execute() and + /// async_execute(). All threads::executors create parallel execution + /// agents + /// + typedef parallel_execution_tag execution_category; + + /// The type of future returned by async_execute(). All + /// threads::executors return hpx::future. + /// + template + struct future + { + typedef hpx::future type; + }; + + /// \brief Singleton form of asynchronous fire & forget execution agent + /// creation. + /// + /// This asynchronously (fire & forget) creates a single function + /// invocation f() using the associated executor. All + /// threads::executors invoke hpx::apply(sched, f). + /// + /// \param sched [in] The executor object to use for scheduling of the + /// function \a f. + /// \param f [in] The function which will be scheduled using the + /// given executor. + /// + template + static void apply_execute(executor_type& sched, F && f) + { + hpx::apply(sched, std::forward(f)); + } + + /// \brief Singleton form of asynchronous execution agent creation. + /// + /// This asynchronously creates a single function invocation f() using + /// the associated executor. All threads::executors invoke + /// hpx::async(sched, f). + /// + /// \param sched [in] The executor object to use for scheduling of the + /// function \a f. + /// \param f [in] The function which will be scheduled using the + /// given executor. + /// + /// \returns f()'s result through a future + /// + template + static hpx::future< + typename hpx::util::result_of< + typename hpx::util::decay::type() + >::type> + async_execute(executor_type& sched, F && f) + { + return hpx::async(sched, std::forward(f)); + } + + /// \brief Singleton form of synchronous execution agent creation. + /// + /// This synchronously creates a single function invocation f() using + /// the associated executor. The execution of the supplied function + /// synchronizes with the caller. All threads::executors invoke + /// hpx::async(sched, f).get(). + /// + /// \param sched [in] The executor object to use for scheduling of the + /// function \a f. + /// \param f [in] The function which will be scheduled using the + /// given executor. + /// + /// \returns f()'s result through a future + /// + template + static typename hpx::util::result_of< + typename hpx::util::decay::type() + >::type + execute(executor_type& sched, F && f) + { + return hpx::async(sched, std::forward(f)).get(); + } + + /// \brief Bulk form of asynchronous execution agent creation + /// + /// This asynchronously creates a group of function invocations f(i) + /// whose ordering is given by the execution_category associated with + /// the executor. + /// + /// Here \a i takes on all values in the index space implied by shape. + /// All exceptions thrown by invocations of f(i) are reported in a + /// manner consistent with parallel algorithm execution through the + /// returned future. + /// + /// \param sched [in] The executor object to use for scheduling of the + /// function \a f. + /// \param f [in] The function which will be scheduled using the + /// given executor. + /// \param shape [in] The shape objects which defines the iteration + /// boundaries for the arguments to be passed to \a f. + /// + /// \returns The return type of \a executor_type::async_execute if + /// defined by \a executor_type. Otherwise a vector + /// of futures holding the returned value of each invocation + /// of \a f. + /// + template + static std::vector::type + > > + async_execute(executor_type& sched, F && f, Shape const& shape) + { + std::vector::type + > > results; + + for (auto const& elem: shape) + results.push_back(hpx::async(sched, std::forward(f), elem)); + + return results; + } + + /// \brief Bulk form of synchronous execution agent creation + /// + /// This synchronously creates a group of function invocations f(i) + /// whose ordering is given by the execution_category associated with + /// the executor. The function synchronizes the execution of all + /// scheduled functions with the caller. + /// + /// Here \a i takes on all values in the index space implied by shape. + /// All exceptions thrown by invocations of f(i) are reported in a + /// manner consistent with parallel algorithm execution through the + /// returned future. + /// + /// \param sched [in] The executor object to use for scheduling of the + /// function \a f. + /// \param f [in] The function which will be scheduled using the + /// given executor. + /// \param shape [in] The shape objects which defines the iteration + /// boundaries for the arguments to be passed to \a f. + /// + /// \returns The return type of \a executor_type::execute if defined + /// by \a executor_type. Otherwise a vector holding the + /// returned value of each invocation of \a f except when + /// \a f returns void, which case void is returned. + /// + template + static typename detail::bulk_execute_result::type + execute(executor_type& sched, F && f, Shape const& shape) + { + std::vector::type + > > results; + + for (auto const& elem: shape) + results.push_back(hpx::async(sched, std::forward(f), elem)); + + return hpx::util::unwrapped(results); + } + + /// Retrieve the number of (kernel-)threads used by the associated + /// executor. All threads::executors invoke + /// hpx::get_os_thread_count(sched). + /// + /// \param sched [in] The executor object to use for the number of + /// os-threads used to schedule tasks. + /// + /// \note This calls exec.os_thread_count() if it exists; + /// otherwise it executes hpx::get_os_thread_count(). + /// + static std::size_t os_thread_count(executor_type const& sched) + { + return hpx::get_os_thread_count(sched); + } + + /// Retrieve whether this executor has operations pending or not. + /// All threads::executors invoke sched.num_pending_closures(). + /// + /// \param sched [in] The executor object to use for querying the + /// number of pending tasks. + /// + static bool has_pending_closures(executor_type& sched) + { + return sched.num_pending_closures(); + } + }; +}}} + +#endif diff --git a/hpx/parallel/executors/thread_pool_executors.hpp b/hpx/parallel/executors/thread_pool_executors.hpp index 132cbcf53470..a43ebccabf7f 100644 --- a/hpx/parallel/executors/thread_pool_executors.hpp +++ b/hpx/parallel/executors/thread_pool_executors.hpp @@ -9,102 +9,59 @@ #define HPX_PARALLEL_EXECUTORS_THREAD_POOL_EXECUTORS_MAY_15_2015_0548PM #include -#include -#include -#include #include -#include - -#include +#include +#include namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v3) { /////////////////////////////////////////////////////////////////////////// #if defined(HPX_HAVE_LOCAL_SCHEDULER) - struct local_queue_executor -#if !defined(DOXYGEN) - : detail::threads_executor -#endif - { - /// Creates a new local_queue_executor - /// - /// \param max_punits [in] The maximum number of processing units to - /// associate with the newly created executor. - /// \param min_punits [in] The minimum number of processing units to - /// associate with the newly created executor - /// (default: 1). - /// - explicit local_queue_executor(std::size_t max_punits, - std::size_t min_punits = 1) - : threads_executor(threads::executors::local_queue_executor( - max_punits, min_punits)) - {} - }; + /// Creates a new local_queue_executor + /// + /// \param max_punits [in] The maximum number of processing units to + /// associate with the newly created executor. + /// \param min_punits [in] The minimum number of processing units to + /// associate with the newly created executor + /// (default: 1). + /// + typedef threads::executors::local_queue_executor local_queue_executor; #endif #if defined(HPX_HAVE_STATIC_SCHEDULER) - struct static_queue_executor -#if !defined(DOXYGEN) - : detail::threads_executor -#endif - { - /// Creates a new static_queue_executor - /// - /// \param max_punits [in] The maximum number of processing units to - /// associate with the newly created executor. - /// \param min_punits [in] The minimum number of processing units to - /// associate with the newly created executor - /// (default: 1). - /// - explicit static_queue_executor(std::size_t max_punits, - std::size_t min_punits = 1) - : threads_executor(threads::executors::static_queue_executor( - max_punits, min_punits)) - {} - }; + /// Creates a new static_queue_executor + /// + /// \param max_punits [in] The maximum number of processing units to + /// associate with the newly created executor. + /// \param min_punits [in] The minimum number of processing units to + /// associate with the newly created executor + /// (default: 1). + /// + typedef threads::executors::static_queue_executor static_queue_executor; #endif - /////////////////////////////////////////////////////////////////////////// - struct local_priority_queue_executor -#if !defined(DOXYGEN) - : detail::threads_executor -#endif - { - /// Creates a new local_priority_queue_executor - /// - /// \param max_punits [in] The maximum number of processing units to - /// associate with the newly created executor. - /// \param min_punits [in] The minimum number of processing units to - /// associate with the newly created executor - /// (default: 1). - /// - explicit local_priority_queue_executor(std::size_t max_punits, - std::size_t min_punits = 1) - : threads_executor(threads::executors::local_priority_queue_executor( - max_punits, min_punits)) - {} - }; + /// Creates a new local_priority_queue_executor + /// + /// \param max_punits [in] The maximum number of processing units to + /// associate with the newly created executor. + /// \param min_punits [in] The minimum number of processing units to + /// associate with the newly created executor + /// (default: 1). + /// + typedef threads::executors::local_priority_queue_executor + local_priority_queue_executor; #if defined(HPX_HAVE_STATIC_PRIORITY_SCHEDULER) - struct static_priority_queue_executor -#if !defined(DOXYGEN) - : detail::threads_executor -#endif - { - /// Creates a new static_priority_queue_executor - /// - /// \param max_punits [in] The maximum number of processing units to - /// associate with the newly created executor. - /// \param min_punits [in] The minimum number of processing units to - /// associate with the newly created executor - /// (default: 1). - /// - explicit static_priority_queue_executor(std::size_t max_punits, - std::size_t min_punits = 1) - : threads_executor(threads::executors::static_priority_queue_executor( - max_punits, min_punits)) - {} - }; + /// Creates a new static_priority_queue_executor + /// + /// \param max_punits [in] The maximum number of processing units to + /// associate with the newly created executor. + /// \param min_punits [in] The minimum number of processing units to + /// associate with the newly created executor + /// (default: 1). + /// + typedef threads::executors::static_priority_queue_executor + static_priority_queue_executor; #endif }}} diff --git a/hpx/runtime/threads/executors/service_executors.hpp b/hpx/runtime/threads/executors/service_executors.hpp index d941cecf9d05..7630abe04973 100644 --- a/hpx/runtime/threads/executors/service_executors.hpp +++ b/hpx/runtime/threads/executors/service_executors.hpp @@ -6,13 +6,13 @@ #if !defined(HPX_RUNTIME_THREADS_EXECUTORS_SERVICE_EXECUTOR_JAN_13_2013_0222PM) #define HPX_RUNTIME_THREADS_EXECUTORS_SERVICE_EXECUTOR_JAN_13_2013_0222PM -#include -#include +#include #include #include #include #include +#include #include @@ -70,32 +70,97 @@ namespace hpx { namespace threads { namespace executors } /////////////////////////////////////////////////////////////////////////// + /// The type of the HPX thread pool to use for a given service_executor + /// + /// This enum type allows to specify the kind of the HPX thread pool to use + /// for a given \a service_executor. + BOOST_SCOPED_ENUM_START(service_executor_type) + { + io_thread_pool, ///< Selects creating a service executor using + ///< the I/O pool of threads + parcel_thread_pool, ///< Selects creating a service executor using + ///< the parcel pool of threads + timer_thread_pool, ///< Selects creating a service executor using + ///< the timer pool of threads + main_thread ///< Selects creating a service executor using + ///< the main thread + }; + BOOST_SCOPED_ENUM_END + + namespace detail + { + /// \cond NOINTERNAL + inline threads::detail::scheduled_executor_base* + get_service_executor(BOOST_SCOPED_ENUM(service_executor_type) t, + char const* name_suffix = "") + { + switch(t) + { + case service_executor_type::io_thread_pool: + return new detail::service_executor("io-pool"); + + case service_executor_type::parcel_thread_pool: + { + char const* suffix = *name_suffix ? name_suffix : "-tcp"; + return new detail::service_executor("parcel-pool", suffix); + } + + case service_executor_type::timer_thread_pool: + return new detail::service_executor("timer-pool"); + + case service_executor_type::main_thread: + return new detail::service_executor("main-pool"); + + default: + break; + } + + HPX_THROW_EXCEPTION(bad_parameter, + "hpx::threads::detail::get_service_executor", + "unknown pool executor type"); + return 0; + } + /// \endcond + } + + /////////////////////////////////////////////////////////////////////////// + struct service_executor : public scheduled_executor + { + service_executor(BOOST_SCOPED_ENUM(service_executor_type) t, + char const* name_suffix = "") + : scheduled_executor(detail::get_service_executor(t, name_suffix)) + {} + }; + struct io_pool_executor : public scheduled_executor { io_pool_executor() - : scheduled_executor(new detail::service_executor("io-pool")) + : scheduled_executor(detail::get_service_executor( + service_executor_type::io_thread_pool)) {} }; struct parcel_pool_executor : public scheduled_executor { - parcel_pool_executor(char const* pool_name_suffix = "-tcp") - : scheduled_executor( - new detail::service_executor("parcel-pool", pool_name_suffix)) + parcel_pool_executor(char const* name_suffix = "-tcp") + : scheduled_executor(detail::get_service_executor( + service_executor_type::parcel_thread_pool, name_suffix)) {} }; struct timer_pool_executor : public scheduled_executor { timer_pool_executor() - : scheduled_executor(new detail::service_executor("timer-pool")) + : scheduled_executor(detail::get_service_executor( + service_executor_type::timer_thread_pool)) {} }; struct main_pool_executor : public scheduled_executor { main_pool_executor() - : scheduled_executor(new detail::service_executor("main-pool")) + : scheduled_executor(detail::get_service_executor( + service_executor_type::main_thread)) {} }; }}} diff --git a/hpx/runtime/threads/executors/this_thread_executors.hpp b/hpx/runtime/threads/executors/this_thread_executors.hpp index e883ce9537d6..3f304602adda 100644 --- a/hpx/runtime/threads/executors/this_thread_executors.hpp +++ b/hpx/runtime/threads/executors/this_thread_executors.hpp @@ -10,7 +10,6 @@ #if defined(HPX_HAVE_STATIC_SCHEDULER) || defined(HPX_HAVE_STATIC_PRIORITY_SCHEDULER) -#include #include #include #include diff --git a/hpx/runtime/threads/executors/thread_pool_executors.hpp b/hpx/runtime/threads/executors/thread_pool_executors.hpp index 2e4e6d142ca4..5306b621fe36 100644 --- a/hpx/runtime/threads/executors/thread_pool_executors.hpp +++ b/hpx/runtime/threads/executors/thread_pool_executors.hpp @@ -6,8 +6,7 @@ #if !defined(HPX_RUNTIME_THREADS_EXECUTORS_SERIAL_EXECUTOR_JAN_11_2013_0831PM) #define HPX_RUNTIME_THREADS_EXECUTORS_SERIAL_EXECUTOR_JAN_11_2013_0831PM -#include -#include +#include #include #include #include diff --git a/tests/unit/parallel/executors/service_executors.cpp b/tests/unit/parallel/executors/service_executors.cpp index d516b97a4d77..91364160883c 100644 --- a/tests/unit/parallel/executors/service_executors.cpp +++ b/tests/unit/parallel/executors/service_executors.cpp @@ -81,7 +81,7 @@ void test_service_executor(Executor& exec) int hpx_main(int argc, char* argv[]) { - using hpx::parallel::service_executor_type; + using hpx::threads::executors::service_executor_type; { hpx::parallel::service_executor exec(service_executor_type::io_thread_pool);