Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid using util::function for thread function wrappers #3114

Merged
merged 1 commit into from Jan 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
159 changes: 120 additions & 39 deletions hpx/runtime/threads/thread_helpers.hpp
@@ -1,4 +1,5 @@
// Copyright (c) 2007-2015 Hartmut Kaiser
// Copyright (c) 2018 Thomas Heller
// Copyright (c) 2011 Bryce Lelbach
// Copyright (c) 2008-2009 Chirag Dekate, Anshul Tandon
//
Expand All @@ -18,12 +19,15 @@
#include <hpx/runtime/threads/thread_enums.hpp>
#include <hpx/util_fwd.hpp>
#include <hpx/util/unique_function.hpp>
#include <hpx/util/register_locks.hpp>
#include <hpx/util/steady_clock.hpp>
#include <hpx/util/thread_description.hpp>

#include <chrono>
#include <cstddef>
#include <cstdint>
#include <type_traits>
#include <utility>

///////////////////////////////////////////////////////////////////////////////
namespace hpx { namespace threads
Expand Down Expand Up @@ -757,6 +761,19 @@ namespace hpx { namespace applier
threads::thread_stacksize stacksize = threads::thread_stacksize_default,
error_code& ec = throws);

///////////////////////////////////////////////////////////////////////////
/// \brief Create a new \a thread using the given data.
///
/// \note This function is completely equivalent to the first overload
/// of threads#register_thread_plain above, except that part of the
/// parameters are passed as members of the threads#thread_init_data
/// object.
///
HPX_API_EXPORT threads::thread_id_type register_thread_plain(
threads::thread_init_data& data,
threads::thread_state_enum initial_state = threads::pending,
bool run_now = true, error_code& ec = throws);

///////////////////////////////////////////////////////////////////////////
/// \brief Create a new \a thread using the given function as the work to
/// be executed.
Expand All @@ -770,15 +787,65 @@ namespace hpx { namespace applier
/// \note All other arguments are equivalent to those of the function
/// \a threads#register_thread_plain
///
HPX_API_EXPORT threads::thread_id_type register_thread(
util::unique_function_nonser<void(threads::thread_state_ex_enum)> && func,
namespace detail
{
template <typename F>
struct thread_function
{
F f;

inline threads::thread_result_type operator()(threads::thread_arg_type)
{
// execute the actual thread function
f(threads::wait_signaled);

// Verify that there are no more registered locks for this
// OS-thread. This will throw if there are still any locks
// held.
util::force_error_on_lock();

return threads::thread_result_type(threads::terminated, nullptr);
}
};

template <typename F>
struct thread_function_nullary
{
F f;

inline threads::thread_result_type operator()(threads::thread_arg_type)
{
// execute the actual thread function
f();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The forward has no effect here. It should rather be removed on the other spot. Good catch.


// Verify that there are no more registered locks for this
// OS-thread. This will throw if there are still any locks
// held.
util::force_error_on_lock();

return threads::thread_result_type(threads::terminated, nullptr);
}
};
}

template <typename F>
threads::thread_id_type register_thread(
F && func,
util::thread_description const& description = util::thread_description(),
threads::thread_state_enum initial_state = threads::pending,
bool run_now = true,
threads::thread_priority priority = threads::thread_priority_normal,
std::size_t os_thread = std::size_t(-1),
threads::thread_stacksize stacksize = threads::thread_stacksize_default,
error_code& ec = throws);
error_code& ec = throws)
{
threads::thread_function_type thread_func(
detail::thread_function<typename std::decay<F>::type>{
std::forward<F>(func)});
return register_thread_plain(std::move(thread_func),
description, initial_state, run_now, priority, os_thread, stacksize,
ec);
}

///////////////////////////////////////////////////////////////////////////
/// \brief Create a new \a thread using the given function as the work to
Expand All @@ -792,28 +859,24 @@ namespace hpx { namespace applier
/// \note All other arguments are equivalent to those of the function
/// \a threads#register_thread_plain
///
HPX_API_EXPORT threads::thread_id_type register_thread_nullary(
util::unique_function_nonser<void()> && func,
template <typename F>
threads::thread_id_type register_thread_nullary(
F && func,
util::thread_description const& description = util::thread_description(),
threads::thread_state_enum initial_state = threads::pending,
bool run_now = true,
threads::thread_priority priority = threads::thread_priority_normal,
std::size_t os_thread = std::size_t(-1),
threads::thread_stacksize stacksize = threads::thread_stacksize_default,
error_code& ec = throws);

///////////////////////////////////////////////////////////////////////////
/// \brief Create a new \a thread using the given data.
///
/// \note This function is completely equivalent to the first overload
/// of threads#register_thread_plain above, except that part of the
/// parameters are passed as members of the threads#thread_init_data
/// object.
///
HPX_API_EXPORT threads::thread_id_type register_thread_plain(
threads::thread_init_data& data,
threads::thread_state_enum initial_state = threads::pending,
bool run_now = true, error_code& ec = throws);
error_code& ec = throws)
{
threads::thread_function_type thread_func(
detail::thread_function_nullary<typename std::decay<F>::type>{
std::forward<F>(func)});
return register_thread_plain(std::move(thread_func),
description, initial_state, run_now, priority, os_thread, stacksize,
ec);
}

///////////////////////////////////////////////////////////////////////////
/// \brief Create a new work item using the given function as the
Expand Down Expand Up @@ -873,6 +936,20 @@ namespace hpx { namespace applier
threads::thread_stacksize stacksize = threads::thread_stacksize_default,
error_code& ec = throws);

///////////////////////////////////////////////////////////////////////////
/// \brief Create a new work item using the given function as the
/// work to be executed.
///
/// \note This function is completely equivalent to the first overload
/// of threads#register_work_plain above, except that part of the
/// parameters are passed as members of the threads#thread_init_data
/// object.
///
HPX_API_EXPORT void register_work_plain(
threads::thread_init_data& data,
threads::thread_state_enum initial_state = threads::pending,
error_code& ec = throws);

///////////////////////////////////////////////////////////////////////////
/// \brief Create a new work item using the given function as the
/// work to be executed.
Expand All @@ -886,14 +963,23 @@ namespace hpx { namespace applier
/// \note All other arguments are equivalent to those of the function
/// \a threads#register_work_plain
///
HPX_API_EXPORT void register_work(
util::unique_function_nonser<void(threads::thread_state_ex_enum)> && func,
template <typename F>
void register_work(
F && func,
util::thread_description const& description = util::thread_description(),
threads::thread_state_enum initial_state = threads::pending,
threads::thread_priority priority = threads::thread_priority_normal,
std::size_t os_thread = std::size_t(-1),
threads::thread_stacksize stacksize = threads::thread_stacksize_default,
error_code& ec = throws);
error_code& ec = throws)
{
threads::thread_function_type thread_func(
detail::thread_function<typename std::decay<F>::type>{
std::forward<F>(func)});
return register_work_plain(std::move(thread_func),
description, 0, initial_state, priority, os_thread, stacksize,
ec);
}

///////////////////////////////////////////////////////////////////////////
/// \brief Create a new work item using the given function as the
Expand All @@ -907,28 +993,23 @@ namespace hpx { namespace applier
/// \note All other arguments are equivalent to those of the function
/// \a threads#register_work_plain
///
HPX_API_EXPORT void register_work_nullary(
util::unique_function_nonser<void()> && func,
template <typename F>
void register_work_nullary(
F && func,
util::thread_description const& description = util::thread_description(),
threads::thread_state_enum initial_state = threads::pending,
threads::thread_priority priority = threads::thread_priority_normal,
std::size_t os_thread = std::size_t(-1),
threads::thread_stacksize stacksize = threads::thread_stacksize_default,
error_code& ec = throws);

///////////////////////////////////////////////////////////////////////////
/// \brief Create a new work item using the given function as the
/// work to be executed.
///
/// \note This function is completely equivalent to the first overload
/// of threads#register_work_plain above, except that part of the
/// parameters are passed as members of the threads#thread_init_data
/// object.
///
HPX_API_EXPORT void register_work_plain(
threads::thread_init_data& data,
threads::thread_state_enum initial_state = threads::pending,
error_code& ec = throws);
error_code& ec = throws)
{
threads::thread_function_type thread_func(
detail::thread_function_nullary<typename std::decay<F>::type>{
std::forward<F>(func)});
return register_work_plain(std::move(thread_func),
description, 0, initial_state, priority, os_thread, stacksize,
ec);
}
}}

///////////////////////////////////////////////////////////////////////////////
Expand Down
135 changes: 0 additions & 135 deletions src/runtime/applier/applier.cpp
Expand Up @@ -31,90 +31,6 @@
namespace hpx { namespace applier
{
///////////////////////////////////////////////////////////////////////////
static inline threads::thread_result_type thread_function(
util::unique_function_nonser<void(threads::thread_state_ex_enum)> func)
{
// execute the actual thread function
func(threads::wait_signaled);

// Verify that there are no more registered locks for this
// OS-thread. This will throw if there are still any locks
// held.
util::force_error_on_lock();

return threads::thread_result_type(threads::terminated, nullptr);
}

static inline threads::thread_result_type thread_function_nullary(
util::unique_function_nonser<void()> func)
{
// execute the actual thread function
func();

// Verify that there are no more registered locks for this
// OS-thread. This will throw if there are still any locks
// held.
util::force_error_on_lock();

return threads::thread_result_type(threads::terminated, nullptr);
}

///////////////////////////////////////////////////////////////////////////
threads::thread_id_type register_thread_nullary(
util::unique_function_nonser<void()> && func,
util::thread_description const& desc,
threads::thread_state_enum state, bool run_now,
threads::thread_priority priority, std::size_t os_thread,
threads::thread_stacksize stacksize, error_code& ec)
{
hpx::applier::applier* app = hpx::applier::get_applier_ptr();
if (nullptr == app)
{
HPX_THROWS_IF(ec, invalid_status,
"hpx::applier::register_thread_nullary",
"global applier object is not accessible");
return threads::invalid_thread_id;
}

util::thread_description d =
desc ? desc : util::thread_description(func, "register_thread_nullary");

threads::thread_init_data data(
util::bind(util::one_shot(&thread_function_nullary), std::move(func)),
d, 0, priority, os_thread, threads::get_stack_size(stacksize));

threads::thread_id_type id = threads::invalid_thread_id;
app->get_thread_manager().register_thread(data, id, state, run_now, ec);
return id;
}

threads::thread_id_type register_thread(
util::unique_function_nonser<void(threads::thread_state_ex_enum)> && func,
util::thread_description const& desc, threads::thread_state_enum state,
bool run_now, threads::thread_priority priority, std::size_t os_thread,
threads::thread_stacksize stacksize, error_code& ec)
{
hpx::applier::applier* app = hpx::applier::get_applier_ptr();
if (nullptr == app)
{
HPX_THROWS_IF(ec, invalid_status,
"hpx::applier::register_thread",
"global applier object is not accessible");
return threads::invalid_thread_id;
}

util::thread_description d =
desc ? desc : util::thread_description(func, "register_thread");

threads::thread_init_data data(
util::bind(util::one_shot(&thread_function), std::move(func)),
d, 0, priority, os_thread, threads::get_stack_size(stacksize));

threads::thread_id_type id = threads::invalid_thread_id;
app->get_thread_manager().register_thread(data, id, state, run_now, ec);
return id;
}

threads::thread_id_type register_thread_plain(
threads::thread_function_type && func,
util::thread_description const& desc, threads::thread_state_enum state,
Expand Down Expand Up @@ -160,57 +76,6 @@ namespace hpx { namespace applier
}

///////////////////////////////////////////////////////////////////////////
void register_work_nullary(
util::unique_function_nonser<void()> && func,
util::thread_description const& desc,
threads::thread_state_enum state, threads::thread_priority priority,
std::size_t os_thread, threads::thread_stacksize stacksize,
error_code& ec)
{
hpx::applier::applier* app = hpx::applier::get_applier_ptr();
if (nullptr == app)
{
HPX_THROWS_IF(ec, invalid_status,
"hpx::applier::register_work_nullary",
"global applier object is not accessible");
return;
}

util::thread_description d =
desc ? desc : util::thread_description(func, "register_work_nullary");

threads::thread_init_data data(
util::bind(util::one_shot(&thread_function_nullary), std::move(func)),
d, 0, priority, os_thread, threads::get_stack_size(stacksize));

app->get_thread_manager().register_work(data, state, ec);
}

void register_work(
util::unique_function_nonser<void(threads::thread_state_ex_enum)> && func,
util::thread_description const& desc, threads::thread_state_enum state,
threads::thread_priority priority, std::size_t os_thread,
threads::thread_stacksize stacksize, error_code& ec)
{
hpx::applier::applier* app = hpx::applier::get_applier_ptr();
if (nullptr == app)
{
HPX_THROWS_IF(ec, invalid_status,
"hpx::applier::register_work",
"global applier object is not accessible");
return;
}

util::thread_description d =
desc ? desc : util::thread_description(func, "register_work");

threads::thread_init_data data(
util::bind(util::one_shot(&thread_function), std::move(func)),
d, 0, priority, os_thread, threads::get_stack_size(stacksize));

app->get_thread_manager().register_work(data, state, ec);
}

void register_work_plain(
threads::thread_function_type && func,
util::thread_description const& desc, naming::address::address_type lva,
Expand Down