Skip to content

Commit

Permalink
Purge use of lambdas because of UB
Browse files Browse the repository at this point in the history
  • Loading branch information
atrantan committed May 16, 2017
1 parent a0b15e8 commit 4657f0e
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 106 deletions.
81 changes: 5 additions & 76 deletions hpx/lcos/spmd_block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <hpx/runtime/launch_policy.hpp>
#include <hpx/runtime/naming/name.hpp>
#include <hpx/runtime/serialization/serialize.hpp>
#include <hpx/traits/concepts.hpp>
#include <hpx/traits/is_action.hpp>
#include <hpx/traits/is_execution_policy.hpp>
#include <hpx/util/unused.hpp>
Expand All @@ -39,30 +40,12 @@ namespace hpx { namespace lcos
struct extract_first_parameter
{};

// Specialization for lambdas
template <typename ClassType, typename ReturnType>
struct extract_first_parameter<ReturnType(ClassType::*)() const>
{
using type = std::false_type;
};

// Specialization for actions
template <>
struct extract_first_parameter< hpx::util::tuple<> >
{
using type = std::false_type;
};

// Specialization for lambdas
template <typename ClassType,
typename ReturnType, typename Arg0, typename... Args>
struct extract_first_parameter<
ReturnType(ClassType::*)(Arg0, Args...) const>
{
using type = typename std::decay<Arg0>::type;
};

// Specialization for actions
template <typename Arg0, typename... Args>
struct extract_first_parameter< hpx::util::tuple<Arg0, Args...> >
{
Expand Down Expand Up @@ -127,36 +110,11 @@ namespace hpx { namespace lcos
void serialize(Archive &, unsigned) {}
};


// Helper for define_spmd_block()
namespace detail
{
// Overload for lambdas
template <typename F>
typename std::enable_if_t<!hpx::traits::is_action<F>::value>
initialize_if_lambda(F && f)
{
auto dummy = hpx::actions::lambda_to_action(f);
HPX_UNUSED(dummy);
}

// Overload for actions
template <typename F>
typename std::enable_if_t<hpx::traits::is_action<F>::value>
initialize_if_lambda(F &&)
{}
}

// Helpers for bulk_execute() invoked in define_spmd_block()
namespace detail
{
template <typename F, bool Condition =
hpx::traits::is_action<F>::value >
struct spmd_block_helper;

// Overload for actions
template <typename F>
struct spmd_block_helper<F,true>
struct spmd_block_helper
{
std::string name_;
std::size_t num_images_;
Expand All @@ -180,34 +138,6 @@ namespace hpx { namespace lcos
std::forward<Ts>(ts)...);
}
};

// Overload for lambdas
template <typename F>
struct spmd_block_helper<F,false>
{
std::string name_;
std::size_t num_images_;

template <typename ... Ts>
void operator()(std::size_t image_id, Ts && ... ts) const
{
using first_type =
typename hpx::lcos::detail::extract_first_parameter<
decltype(&F::operator())>::type;

static_assert(std::is_same<spmd_block, first_type>::value,
"define_spmd_block() needs a lambda that " \
"has at least a spmd_block as 1st argument");

spmd_block block(name_, num_images_, image_id);

int * dummy = nullptr;
hpx::util::invoke(
reinterpret_cast<const F&>(*dummy),
std::move(block),
std::forward<Ts>(ts)...);
}
};
}

// Helper for define_spmd_block()
Expand Down Expand Up @@ -241,7 +171,9 @@ namespace hpx { namespace lcos
};
}

template <typename F, typename ... Args>
template <typename F, typename ... Args,
HPX_CONCEPT_REQUIRES_(hpx::traits::is_action<F>::value)
>
hpx::future<void>
define_spmd_block(std::string && name, std::size_t images_per_locality,
F && f, Args && ... args)
Expand All @@ -256,9 +188,6 @@ namespace hpx { namespace lcos
typename hpx::actions::make_action<
decltype( &helper_type::call ), &helper_type::call >::type;

// Initialize f at compile-time in case when f is a lambda function
hpx::lcos::detail::initialize_if_lambda(f);

helper_action_type act;

std::size_t num_images
Expand Down
36 changes: 6 additions & 30 deletions tests/unit/lcos/global_spmd_block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

std::size_t images_per_locality = 4;
std::size_t iterations = 20;
boost::atomic<std::size_t> c1(0), c2(0);
boost::atomic<std::size_t> c(0);

void bulk_test_function(hpx::lcos::spmd_block block)
{
Expand All @@ -31,9 +31,9 @@ void bulk_test_function(hpx::lcos::spmd_block block)
i<iterations;
i++, test_count+=images_per_locality)
{
++c2;
++c;
block.sync_all();
HPX_TEST_EQ(c2, test_count);
HPX_TEST_EQ(c, test_count);
block.sync_all();
}
}
Expand All @@ -44,35 +44,11 @@ int main()
{
bulk_test_action act;

auto bulk_test =
[](hpx::lcos::spmd_block block)
{
std::size_t num_images
= hpx::get_num_localities(hpx::launch::sync) * images_per_locality;

HPX_TEST_EQ(block.get_num_images(), num_images);
HPX_TEST_EQ(block.this_image() < num_images, true);

for(std::size_t i=0, test_count = images_per_locality;
i<iterations;
i++, test_count+=images_per_locality)
{
++c1;
block.sync_all();
HPX_TEST_EQ(c1, test_count);
block.sync_all();
}
};

hpx::future<void> join1 =
hpx::lcos::define_spmd_block(
"block1", images_per_locality, std::move(bulk_test));

hpx::future<void> join2 =
hpx::future<void> join =
hpx::lcos::define_spmd_block(
"block2", images_per_locality, std::move(act));
"block1", images_per_locality, std::move(act));

hpx::wait_all(join1,join2);
hpx::wait_all(join);

return 0;
}

0 comments on commit 4657f0e

Please sign in to comment.