Skip to content

Commit

Permalink
Merge pull request #2676 from STEllAR-GROUP/parallel_destroy
Browse files Browse the repository at this point in the history
Adding parallel::destroy and destroy_n
  • Loading branch information
hkaiser committed Jun 9, 2017
2 parents b9574d6 + a81886e commit 179850d
Show file tree
Hide file tree
Showing 10 changed files with 1,320 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/CMakeLists.txt
Expand Up @@ -63,6 +63,7 @@ set(doxygen_dependencies
"${PROJECT_SOURCE_DIR}/hpx/parallel/algorithms/all_any_none.hpp"
"${PROJECT_SOURCE_DIR}/hpx/parallel/algorithms/copy.hpp"
"${PROJECT_SOURCE_DIR}/hpx/parallel/algorithms/count.hpp"
"${PROJECT_SOURCE_DIR}/hpx/parallel/algorithms/destroy.hpp"
"${PROJECT_SOURCE_DIR}/hpx/parallel/algorithms/equal.hpp"
"${PROJECT_SOURCE_DIR}/hpx/parallel/algorithms/exclusive_scan.hpp"
"${PROJECT_SOURCE_DIR}/hpx/parallel/algorithms/fill.hpp"
Expand Down
4 changes: 4 additions & 0 deletions docs/hpx.idx
Expand Up @@ -176,6 +176,10 @@ parallel::copy_n "copy_n" "hpx\.parallel\.v1\.copy_n.*"
parallel::count "count" "hpx\.parallel\.v1\.count$"
parallel::count_if "count_if" "hpx\.parallel\.v1\.count_if.*"

# hpx/parallel/algorithms/destroy.hpp
parallel::destroy "destroy" "hpx\.parallel\.v1\.destroy$.*"
parallel::destroy_n "destroy_n" "hpx\.parallel\.v1\.destroy_n.*"

# hpx/parallel/algorithms/equal.hpp
parallel::equal "equal" "hpx\.parallel\.v1\.equal_id.*"

Expand Down
10 changes: 10 additions & 0 deletions docs/manual/parallel_algorithms.qbk
Expand Up @@ -462,6 +462,16 @@ __hpx__ provides implementations of the following parallel algorithms:

[table Dynamic Memory Management (In Header: `<hpx/include/parallel_memory.hpp>`)
[[Name] [Description] [In Header] [Algorithm page at cppreference.com]]
[[ [algoref destroy] ]
[Destroys a range of objects.]
[`<hpx/include/parallel_destroy.hpp>`]
[[cpprefmemdocs destroy]]
]
[[ [algoref destroy_n] ]
[Destroys a range of objects.]
[`<hpx/include/parallel_destroy.hpp>`]
[[cpprefmemdocs destroy_n]]
]
[[ [algoref uninitialized_copy] ]
[Copies a range of objects to an uninitialized area of memory.]
[`<hpx/include/parallel_uninitialized_copy.hpp>`]
Expand Down
12 changes: 12 additions & 0 deletions hpx/include/parallel_destroy.hpp
@@ -0,0 +1,12 @@
// Copyright (c) 2007-2017 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)

#if !defined(HPX_PARALLEL_DESTROY_JUN_02_2017_1042AM)
#define HPX_PARALLEL_DESTROY_JUN_02_2017_1042AM

#include <hpx/parallel/algorithms/destroy.hpp>

#endif

289 changes: 289 additions & 0 deletions hpx/parallel/algorithms/destroy.hpp
@@ -0,0 +1,289 @@
// Copyright (c) 2014-2017 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/algorithms/destroy.hpp

#if !defined(HPX_PARALLEL_DETAIL_destroy_JUN_01_2017_1049AM)
#define HPX_PARALLEL_DETAIL_destroy_JUN_01_2017_1049AM

#include <hpx/config.hpp>
#include <hpx/traits/is_iterator.hpp>
#include <hpx/util/void_guard.hpp>

#include <hpx/parallel/algorithms/detail/dispatch.hpp>
#include <hpx/parallel/algorithms/detail/is_negative.hpp>
#include <hpx/parallel/execution_policy.hpp>
#include <hpx/parallel/util/detail/algorithm_result.hpp>
#include <hpx/parallel/util/loop.hpp>
#include <hpx/parallel/util/foreach_partitioner.hpp>
#include <hpx/parallel/util/projection_identity.hpp>

#include <algorithm>
#include <cstddef>
#include <iterator>
#include <memory>
#include <type_traits>
#include <utility>
#include <vector>

namespace hpx { namespace parallel { inline namespace v1
{
///////////////////////////////////////////////////////////////////////////
// destroy
namespace detail
{
/// \cond NOINTERNAL

// provide our own implementation of std::destroy
// as some versions of MSVC horribly fail at compiling it for some types
// T
template <typename FwdIter>
void std_destroy(FwdIter first, FwdIter last)
{
typedef typename std::iterator_traits<FwdIter>::value_type
value_type;

for (/* */; first != last; ++first)
{
std::addressof(*first)->~value_type();
}
}

///////////////////////////////////////////////////////////////////////
template <typename ExPolicy, typename FwdIter>
typename util::detail::algorithm_result<ExPolicy, FwdIter>::type
parallel_sequential_destroy_n(
ExPolicy && policy, FwdIter first, std::size_t count)
{
if (count == 0)
{
return util::detail::algorithm_result<ExPolicy, FwdIter>::get(
std::move(first));
}

return util::foreach_partitioner<ExPolicy>::call(
std::forward<ExPolicy>(policy), first, count,
[](FwdIter first, std::size_t count, std::size_t)
{
typedef typename std::iterator_traits<FwdIter>::value_type
value_type;

return util::loop_n<ExPolicy>(first, count,
[](FwdIter it)
{
std::addressof(*it)->~value_type();
});
},
util::projection_identity());
}

///////////////////////////////////////////////////////////////////////
template <typename FwdIter>
struct destroy
: public detail::algorithm<destroy<FwdIter> >
{
destroy()
: destroy::algorithm("destroy")
{}

template <typename ExPolicy>
static hpx::util::unused_type
sequential(ExPolicy, FwdIter first, FwdIter last)
{
std_destroy(first, last);
return hpx::util::unused;
}

template <typename ExPolicy>
static typename util::detail::algorithm_result<ExPolicy>::type
parallel(ExPolicy && policy, FwdIter first, FwdIter last)
{
return util::detail::algorithm_result<ExPolicy>::get(
parallel_sequential_destroy_n(
std::forward<ExPolicy>(policy), first,
std::distance(first, last)));
}
};
/// \endcond
}

/// Destroys objects of type typename iterator_traits<ForwardIt>::value_type
/// in the range [first, last).
///
/// \note Complexity: Performs exactly \a last - \a first operations.
///
/// \tparam ExPolicy The type of the execution policy to use (deduced).
/// It describes the manner in which the execution
/// of the algorithm may be parallelized and the manner
/// in which it executes the assignments.
/// \tparam FwdIter The type of the source iterators used (deduced).
/// This iterator type must meet the requirements of an
/// forward iterator.
///
/// \param policy The execution policy to use for the scheduling of
/// the iterations.
/// \param first Refers to the beginning of the sequence of elements
/// the algorithm will be applied to.
/// \param last Refers to the end of the sequence of elements the
/// algorithm will be applied to.
///
/// The operations in the parallel \a destroy
/// algorithm invoked with an execution policy object of type \a sequenced_policy
/// execute in sequential order in the calling thread.
///
/// The operations in the parallel \a destroy
/// algorithm invoked with an execution policy object of type \a parallel_policy
/// or \a parallel_task_policy are permitted to execute in an
/// unordered fashion in unspecified threads, and indeterminately sequenced
/// within each thread.
///
/// \returns The \a destroy algorithm returns a
/// \a hpx::future<void>, if the execution policy is of type
/// \a sequenced_task_policy or
/// \a parallel_task_policy and returns \a void otherwise.
///
template <typename ExPolicy, typename FwdIter,
HPX_CONCEPT_REQUIRES_(
execution::is_execution_policy<ExPolicy>::value &&
hpx::traits::is_iterator<FwdIter>::value)>
typename util::detail::algorithm_result<ExPolicy>::type
destroy(ExPolicy && policy, FwdIter first, FwdIter last)
{
static_assert(
(hpx::traits::is_forward_iterator<FwdIter>::value),
"Required at least forward iterator.");

typedef std::integral_constant<bool,
execution::is_sequenced_execution_policy<ExPolicy>::value
> is_seq;

return detail::destroy<FwdIter>().call(
std::forward<ExPolicy>(policy), is_seq(), first, last);
}

///////////////////////////////////////////////////////////////////////////
// destroy_n
namespace detail
{
/// \cond NOINTERNAL

// provide our own implementation of std::destroy
// as some versions of MSVC horribly fail at compiling it for some
// types T
template <typename FwdIter>
FwdIter std_destroy_n(FwdIter first, std::size_t count)
{
typedef typename std::iterator_traits<FwdIter>::value_type
value_type;

for (/* */; count != 0; (void) ++first, --count)
{
std::addressof(*first)->~value_type();
}

return first;
}

template <typename FwdIter>
struct destroy_n
: public detail::algorithm<
destroy_n<FwdIter>, FwdIter>
{
destroy_n()
: destroy_n::algorithm("destroy_n")
{}

template <typename ExPolicy>
static FwdIter sequential(ExPolicy, FwdIter first, std::size_t count)
{
return std_destroy_n(first, count);
}

template <typename ExPolicy>
static typename util::detail::algorithm_result<
ExPolicy, FwdIter
>::type
parallel(ExPolicy && policy, FwdIter first, std::size_t count)
{
return parallel_sequential_destroy_n(
std::forward<ExPolicy>(policy), first, count);
}
};
/// \endcond
}

/// Destroys objects of type typename iterator_traits<ForwardIt>::value_type
/// in the range [first, first + count).
///
/// \note Complexity: Performs exactly \a count operations, if
/// count > 0, no assignments otherwise.
///
/// \tparam ExPolicy The type of the execution policy to use (deduced).
/// It describes the manner in which the execution
/// of the algorithm may be parallelized and the manner
/// in which it executes the assignments.
/// \tparam FwdIter The type of the source iterators used (deduced).
/// This iterator type must meet the requirements of an
/// forward iterator.
/// \tparam Size The type of the argument specifying the number of
/// elements to apply this algorithm to.
///
/// \param policy The execution policy to use for the scheduling of
/// the iterations.
/// \param first Refers to the beginning of the sequence of elements
/// the algorithm will be applied to.
/// \param count Refers to the number of elements starting at
/// \a first the algorithm will be applied to.
///
/// The operations in the parallel \a destroy_n
/// algorithm invoked with an execution policy object of type
/// \a sequenced_policy execute in sequential order in the
/// calling thread.
///
/// The operations in the parallel \a destroy_n
/// algorithm invoked with an execution policy object of type
/// \a parallel_policy or
/// \a parallel_task_policy are permitted to execute in an
/// unordered fashion in unspecified threads, and indeterminately sequenced
/// within each thread.
///
/// \returns The \a destroy_n algorithm returns a
/// \a hpx::future<FwdIter> if the execution policy is of type
/// \a sequenced_task_policy or
/// \a parallel_task_policy and
/// returns \a FwdIter otherwise.
/// The \a destroy_n algorithm returns the
/// iterator to the element in the source range, one past
/// the last element constructed.
///
template <typename ExPolicy, typename FwdIter, typename Size,
HPX_CONCEPT_REQUIRES_(
execution::is_execution_policy<ExPolicy>::value &&
hpx::traits::is_iterator<FwdIter>::value)>
typename util::detail::algorithm_result<ExPolicy, FwdIter>::type
destroy_n(ExPolicy && policy, FwdIter first, Size count)
{
static_assert(
(hpx::traits::is_forward_iterator<FwdIter>::value),
"Requires at least forward iterator.");

// if count is representing a negative value, we do nothing
if (detail::is_negative(count))
{
return util::detail::algorithm_result<ExPolicy, FwdIter>::get(
std::move(first));
}

typedef std::integral_constant<bool,
execution::is_sequenced_execution_policy<ExPolicy>::value
> is_seq;

return detail::destroy_n<FwdIter>().call(
std::forward<ExPolicy>(policy), is_seq(),
first, std::size_t(count));
}
}}}

#endif
1 change: 1 addition & 0 deletions hpx/parallel/memory.hpp
Expand Up @@ -11,6 +11,7 @@
/// See N4071: 1.3/3
#include <memory>

#include <hpx/parallel/algorithms/destroy.hpp>
#include <hpx/parallel/algorithms/uninitialized_copy.hpp>
#include <hpx/parallel/algorithms/uninitialized_default_construct.hpp>
#include <hpx/parallel/algorithms/uninitialized_fill.hpp>
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/parallel/algorithms/CMakeLists.txt
Expand Up @@ -24,6 +24,8 @@ set(tests
copyn
count
countif
destroy
destroyn
equal
equal_binary
exclusive_scan
Expand Down

0 comments on commit 179850d

Please sign in to comment.