mirror of
https://github.com/Naios/continuable.git
synced 2025-12-07 01:06:44 +08:00
Partial conversion of the async traversal unit test
This commit is contained in:
parent
4b00f5ff8a
commit
f935d78c99
@ -22,65 +22,6 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <continuable/continuable-traverse-async.hpp>
|
|
||||||
|
|
||||||
#include "test-continuable.hpp"
|
|
||||||
|
|
||||||
using std::get;
|
|
||||||
using std::make_tuple;
|
|
||||||
using std::tuple;
|
|
||||||
|
|
||||||
using cti::async_traverse_complete_tag;
|
|
||||||
using cti::async_traverse_detach_tag;
|
|
||||||
using cti::async_traverse_visit_tag;
|
|
||||||
using cti::traverse_pack_async;
|
|
||||||
|
|
||||||
struct my_visitor : std::enable_shared_from_this<my_visitor> {
|
|
||||||
virtual ~my_visitor() = default;
|
|
||||||
|
|
||||||
bool operator()(async_traverse_visit_tag, std::size_t i) {
|
|
||||||
(void)i;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename N>
|
|
||||||
void operator()(async_traverse_detach_tag, std::size_t i, N&& next) {
|
|
||||||
(void)i;
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void operator()(async_traverse_complete_tag, T&& pack) {
|
|
||||||
(void)pack;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST(misc_as_test, my_test) {
|
|
||||||
cti::traverse_pack_async(my_visitor{}, 0, 1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copyright (c) 2017 Denis Blank
|
|
||||||
// Copyright Andrey Semashev 2007 - 2013.
|
|
||||||
//
|
|
||||||
// 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)
|
|
||||||
|
|
||||||
// TODO Remove the boost dependency
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <hpx/config.hpp>
|
|
||||||
#include <hpx/util/atomic_count.hpp>
|
|
||||||
#include <hpx/util/lightweight_test.hpp>
|
|
||||||
#include <hpx/util/pack_traversal_async.hpp>
|
|
||||||
#include <hpx/util/tuple.hpp>
|
|
||||||
#include <hpx/util/unused.hpp>
|
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -90,144 +31,69 @@ TEST(misc_as_test, my_test) {
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#if defined(HPX_HAVE_CXX11_STD_ARRAY)
|
#include <continuable/continuable-traverse-async.hpp>
|
||||||
#include <array>
|
#include <continuable/detail/traits.hpp>
|
||||||
#endif
|
#include <continuable/detail/util.hpp>
|
||||||
|
|
||||||
using hpx::util::async_traverse_complete_tag;
|
#include "test-continuable.hpp"
|
||||||
using hpx::util::async_traverse_detach_tag;
|
|
||||||
using hpx::util::async_traverse_visit_tag;
|
using std::get;
|
||||||
using hpx::util::make_tuple;
|
using std::make_tuple;
|
||||||
using hpx::util::traverse_pack_async;
|
using std::tuple;
|
||||||
using hpx::util::tuple;
|
|
||||||
|
using cti::async_traverse_complete_tag;
|
||||||
|
using cti::async_traverse_detach_tag;
|
||||||
|
using cti::async_traverse_in_place_tag;
|
||||||
|
using cti::async_traverse_visit_tag;
|
||||||
|
using cti::detail::util::unused;
|
||||||
|
using cti::traverse_pack_async;
|
||||||
|
|
||||||
/// A tag which isn't accepted by any mapper
|
/// A tag which isn't accepted by any mapper
|
||||||
struct not_accepted_tag
|
struct not_accepted_tag {};
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
struct thread_safe_counter
|
|
||||||
{
|
|
||||||
typedef hpx::util::atomic_count type;
|
|
||||||
|
|
||||||
static unsigned int load(hpx::util::atomic_count const& counter) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<unsigned int>(static_cast<long>(counter));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void increment(hpx::util::atomic_count& counter) noexcept
|
|
||||||
{
|
|
||||||
++counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int decrement(hpx::util::atomic_count& counter) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<unsigned int>(--counter);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Derived, typename CounterPolicy = thread_safe_counter>
|
|
||||||
class intrusive_ref_counter;
|
|
||||||
|
|
||||||
template <typename Derived, typename CounterPolicy>
|
|
||||||
void intrusive_ptr_add_ref(
|
|
||||||
intrusive_ref_counter<Derived, CounterPolicy> const* p) noexcept;
|
|
||||||
|
|
||||||
template <typename Derived, typename CounterPolicy>
|
|
||||||
void intrusive_ptr_release(
|
|
||||||
intrusive_ref_counter<Derived, CounterPolicy> const* p) noexcept;
|
|
||||||
|
|
||||||
template <typename Derived, typename CounterPolicy>
|
|
||||||
class intrusive_ref_counter
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
typedef typename CounterPolicy::type counter_type;
|
|
||||||
|
|
||||||
mutable counter_type ref_counter;
|
|
||||||
|
|
||||||
public:
|
|
||||||
intrusive_ref_counter() noexcept : ref_counter(1) {}
|
|
||||||
|
|
||||||
unsigned int use_count() const noexcept
|
|
||||||
{
|
|
||||||
return CounterPolicy::load(ref_counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
~intrusive_ref_counter() = default;
|
|
||||||
|
|
||||||
friend void intrusive_ptr_add_ref<Derived, CounterPolicy>(
|
|
||||||
intrusive_ref_counter<Derived, CounterPolicy> const* p)
|
|
||||||
noexcept;
|
|
||||||
|
|
||||||
friend void intrusive_ptr_release<Derived, CounterPolicy>(
|
|
||||||
intrusive_ref_counter<Derived, CounterPolicy> const* p)
|
|
||||||
noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Derived, typename CounterPolicy>
|
|
||||||
inline void intrusive_ptr_add_ref(
|
|
||||||
intrusive_ref_counter<Derived, CounterPolicy> const* p) noexcept
|
|
||||||
{
|
|
||||||
CounterPolicy::increment(p->ref_counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Derived, typename CounterPolicy>
|
|
||||||
inline void intrusive_ptr_release(
|
|
||||||
intrusive_ref_counter<Derived, CounterPolicy> const* p) noexcept
|
|
||||||
{
|
|
||||||
if (CounterPolicy::decrement(p->ref_counter) == 0)
|
|
||||||
delete static_cast<Derived const*>(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Child>
|
template <typename Child>
|
||||||
class async_counter_base : public intrusive_ref_counter<Child>
|
class async_counter_base : public std::enable_shared_from_this<Child> {
|
||||||
{
|
|
||||||
std::size_t counter_ = 0;
|
std::size_t counter_ = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
async_counter_base() = default;
|
async_counter_base() = default;
|
||||||
|
|
||||||
virtual ~async_counter_base() {}
|
virtual ~async_counter_base() {
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t const& counter() const noexcept
|
std::size_t const& counter() const noexcept {
|
||||||
{
|
|
||||||
return counter_;
|
return counter_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t& counter() noexcept
|
std::size_t& counter() noexcept {
|
||||||
{
|
|
||||||
return counter_;
|
return counter_;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t ArgCount>
|
template <std::size_t ArgCount>
|
||||||
struct async_increasing_int_sync_visitor
|
struct async_increasing_int_sync_visitor
|
||||||
: async_counter_base<async_increasing_int_sync_visitor<ArgCount>>
|
: async_counter_base<async_increasing_int_sync_visitor<ArgCount>> {
|
||||||
{
|
explicit async_increasing_int_sync_visitor(int /*dummy*/) {
|
||||||
explicit async_increasing_int_sync_visitor(int dummy) {}
|
}
|
||||||
|
|
||||||
bool operator()(async_traverse_visit_tag, std::size_t i)
|
bool operator()(async_traverse_visit_tag, std::size_t i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(i, this->counter());
|
EXPECT_EQ(i, this->counter());
|
||||||
++this->counter();
|
++this->counter();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N>
|
template <typename N>
|
||||||
void operator()(async_traverse_detach_tag, std::size_t i, N&& next)
|
void operator()(async_traverse_detach_tag, std::size_t i, N&& next) {
|
||||||
{
|
unused(i);
|
||||||
HPX_UNUSED(i);
|
unused(next);
|
||||||
HPX_UNUSED(next);
|
|
||||||
|
|
||||||
// Should never be called!
|
// Should never be called!
|
||||||
HPX_TEST(false);
|
EXPECT_TRUE(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void operator()(async_traverse_complete_tag, T&& pack)
|
void operator()(async_traverse_complete_tag, T&& pack) {
|
||||||
{
|
unused(pack);
|
||||||
HPX_UNUSED(pack);
|
|
||||||
|
|
||||||
EXPECT_EQ(this->counter(), ArgCount);
|
EXPECT_EQ(this->counter(), ArgCount);
|
||||||
++this->counter();
|
++this->counter();
|
||||||
@ -236,29 +102,26 @@ struct async_increasing_int_sync_visitor
|
|||||||
|
|
||||||
template <std::size_t ArgCount>
|
template <std::size_t ArgCount>
|
||||||
struct async_increasing_int_visitor
|
struct async_increasing_int_visitor
|
||||||
: async_counter_base<async_increasing_int_visitor<ArgCount>>
|
: async_counter_base<async_increasing_int_visitor<ArgCount>> {
|
||||||
{
|
explicit async_increasing_int_visitor(int /*dummy*/) {
|
||||||
explicit async_increasing_int_visitor(int dummy) {}
|
}
|
||||||
|
|
||||||
bool operator()(async_traverse_visit_tag, std::size_t i) const
|
bool operator()(async_traverse_visit_tag, std::size_t i) const {
|
||||||
{
|
|
||||||
EXPECT_EQ(i, this->counter());
|
EXPECT_EQ(i, this->counter());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N>
|
template <typename N>
|
||||||
void operator()(async_traverse_detach_tag, std::size_t i, N&& next)
|
void operator()(async_traverse_detach_tag, std::size_t i, N&& next) {
|
||||||
{
|
unused(i);
|
||||||
HPX_UNUSED(i);
|
|
||||||
|
|
||||||
++this->counter();
|
++this->counter();
|
||||||
std::forward<N>(next)();
|
std::forward<N>(next)();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void operator()(async_traverse_complete_tag, T&& pack)
|
void operator()(async_traverse_complete_tag, T&& pack) {
|
||||||
{
|
unused(pack);
|
||||||
HPX_UNUSED(pack);
|
|
||||||
|
|
||||||
EXPECT_EQ(this->counter(), ArgCount);
|
EXPECT_EQ(this->counter(), ArgCount);
|
||||||
++this->counter();
|
++this->counter();
|
||||||
@ -266,13 +129,12 @@ struct async_increasing_int_visitor
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t ArgCount, typename... Args>
|
template <std::size_t ArgCount, typename... Args>
|
||||||
void test_async_traversal_base(Args&&... args)
|
void test_async_traversal_base(Args&&... args) {
|
||||||
{
|
|
||||||
// Test that every element is traversed in the correct order
|
// Test that every element is traversed in the correct order
|
||||||
// when we detach the control flow on every visit.
|
// when we detach the control flow on every visit.
|
||||||
{
|
{
|
||||||
auto result = traverse_pack_async(
|
auto result =
|
||||||
hpx::util::async_traverse_in_place_tag<
|
traverse_pack_async(async_traverse_in_place_tag<
|
||||||
async_increasing_int_sync_visitor<ArgCount>>{},
|
async_increasing_int_sync_visitor<ArgCount>>{},
|
||||||
42, args...);
|
42, args...);
|
||||||
EXPECT_EQ(result->counter(), ArgCount + 1U);
|
EXPECT_EQ(result->counter(), ArgCount + 1U);
|
||||||
@ -282,28 +144,20 @@ void test_async_traversal_base(Args&&... args)
|
|||||||
// when we detach the control flow on every visit.
|
// when we detach the control flow on every visit.
|
||||||
{
|
{
|
||||||
auto result = traverse_pack_async(
|
auto result = traverse_pack_async(
|
||||||
hpx::util::async_traverse_in_place_tag<
|
async_traverse_in_place_tag<async_increasing_int_visitor<ArgCount>>{},
|
||||||
async_increasing_int_visitor<ArgCount>>{},
|
|
||||||
42, args...);
|
42, args...);
|
||||||
EXPECT_EQ(result->counter(), ArgCount + 1U);
|
EXPECT_EQ(result->counter(), ArgCount + 1U);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_async_traversal()
|
void test_async_traversal() {
|
||||||
{
|
|
||||||
// Just test everything using a casual int pack
|
// Just test everything using a casual int pack
|
||||||
test_async_traversal_base<4U>(not_accepted_tag{},
|
test_async_traversal_base<4U>(not_accepted_tag{}, 0U, 1U, not_accepted_tag{},
|
||||||
0U,
|
2U, 3U, not_accepted_tag{});
|
||||||
1U,
|
|
||||||
not_accepted_tag{},
|
|
||||||
2U,
|
|
||||||
3U,
|
|
||||||
not_accepted_tag{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ContainerFactory>
|
template <typename ContainerFactory>
|
||||||
void test_async_container_traversal_impl(ContainerFactory&& container_of)
|
void test_async_container_traversal_impl(ContainerFactory&& container_of) {
|
||||||
{
|
|
||||||
// Test by passing a containers in the middle
|
// Test by passing a containers in the middle
|
||||||
test_async_traversal_base<4U>(0U, container_of(1U, 2U), 3U);
|
test_async_traversal_base<4U>(0U, container_of(1U, 2U), 3U);
|
||||||
// Test by splitting the pack in two containers
|
// Test by splitting the pack in two containers
|
||||||
@ -313,29 +167,22 @@ void test_async_container_traversal_impl(ContainerFactory&& container_of)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct common_container_factory
|
struct common_container_factory {
|
||||||
{
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
T operator()(Args&&... args)
|
T operator()(Args&&... args) {
|
||||||
{
|
|
||||||
return T{std::forward<Args>(args)...};
|
return T{std::forward<Args>(args)...};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(HPX_HAVE_CXX11_STD_ARRAY)
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct array_container_factory
|
struct array_container_factory {
|
||||||
{
|
|
||||||
template <typename... Args, typename Array = std::array<T, sizeof...(Args)>>
|
template <typename... Args, typename Array = std::array<T, sizeof...(Args)>>
|
||||||
Array operator()(Args&&... args)
|
Array operator()(Args&&... args) {
|
||||||
{
|
|
||||||
return Array{{std::forward<Args>(args)...}};
|
return Array{{std::forward<Args>(args)...}};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
static void test_async_container_traversal()
|
void test_async_container_traversal() {
|
||||||
{
|
|
||||||
{
|
{
|
||||||
common_container_factory<std::vector<std::size_t>> factory;
|
common_container_factory<std::vector<std::size_t>> factory;
|
||||||
test_async_container_traversal_impl(factory);
|
test_async_container_traversal_impl(factory);
|
||||||
@ -351,45 +198,37 @@ static void test_async_container_traversal()
|
|||||||
test_async_container_traversal_impl(factory);
|
test_async_container_traversal_impl(factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HPX_HAVE_CXX11_STD_ARRAY)
|
|
||||||
{
|
{
|
||||||
array_container_factory<std::size_t> factory;
|
array_container_factory<std::size_t> factory;
|
||||||
test_async_container_traversal_impl(factory);
|
test_async_container_traversal_impl(factory);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_async_tuple_like_traversal()
|
void test_async_tuple_like_traversal() {
|
||||||
{
|
|
||||||
// Test by passing a tuple in the middle
|
// Test by passing a tuple in the middle
|
||||||
test_async_traversal_base<4U>(
|
test_async_traversal_base<4U>(not_accepted_tag{}, 0U,
|
||||||
not_accepted_tag{}, 0U, make_tuple(1U, not_accepted_tag{}, 2U), 3U);
|
make_tuple(1U, not_accepted_tag{}, 2U), 3U);
|
||||||
// Test by splitting the pack in two tuples
|
// Test by splitting the pack in two tuples
|
||||||
test_async_traversal_base<4U>(
|
test_async_traversal_base<4U>(make_tuple(0U, not_accepted_tag{}, 1U),
|
||||||
make_tuple(0U, not_accepted_tag{}, 1U), make_tuple(2U, 3U));
|
make_tuple(2U, 3U));
|
||||||
// Test by passing a huge tuple to the traversal
|
// Test by passing a huge tuple to the traversal
|
||||||
test_async_traversal_base<4U>(make_tuple(0U, 1U, 2U, 3U));
|
test_async_traversal_base<4U>(make_tuple(0U, 1U, 2U, 3U));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T,
|
template <typename T, typename... Args,
|
||||||
typename... Args,
|
|
||||||
typename Vector = std::vector<typename std::decay<T>::type>>
|
typename Vector = std::vector<typename std::decay<T>::type>>
|
||||||
Vector vector_of(T&& first, Args&&... args)
|
Vector vector_of(T&& first, Args&&... args) {
|
||||||
{
|
|
||||||
return Vector{std::forward<T>(first), std::forward<Args>(args)...};
|
return Vector{std::forward<T>(first), std::forward<Args>(args)...};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_async_mixed_traversal()
|
void test_async_mixed_traversal() {
|
||||||
{
|
|
||||||
using container_t = std::vector<std::size_t>;
|
using container_t = std::vector<std::size_t>;
|
||||||
|
|
||||||
// Test hierarchies where container and tuple like types are mixed
|
// Test hierarchies where container and tuple like types are mixed
|
||||||
test_async_traversal_base<4U>(
|
test_async_traversal_base<4U>(0U, make_tuple(container_t{1U, 2U}), 3U);
|
||||||
0U, hpx::util::make_tuple(container_t{1U, 2U}), 3U);
|
|
||||||
|
|
||||||
test_async_traversal_base<4U>(
|
test_async_traversal_base<4U>(
|
||||||
hpx::util::make_tuple(
|
make_tuple(0U, vector_of(not_accepted_tag{}), vector_of(vector_of(1U))),
|
||||||
0U, vector_of(not_accepted_tag{}), vector_of(vector_of(1U))),
|
|
||||||
make_tuple(2U, 3U));
|
make_tuple(2U, 3U));
|
||||||
|
|
||||||
test_async_traversal_base<4U>(
|
test_async_traversal_base<4U>(
|
||||||
@ -398,33 +237,29 @@ static void test_async_mixed_traversal()
|
|||||||
|
|
||||||
template <std::size_t ArgCount>
|
template <std::size_t ArgCount>
|
||||||
struct async_unique_sync_visitor
|
struct async_unique_sync_visitor
|
||||||
: async_counter_base<async_unique_sync_visitor<ArgCount>>
|
: async_counter_base<async_unique_sync_visitor<ArgCount>> {
|
||||||
{
|
explicit async_unique_sync_visitor(int /*dummy*/) {
|
||||||
explicit async_unique_sync_visitor(int dummy) {}
|
}
|
||||||
|
|
||||||
bool operator()(async_traverse_visit_tag, std::unique_ptr<std::size_t>& i)
|
bool operator()(async_traverse_visit_tag, std::unique_ptr<std::size_t>& i) {
|
||||||
{
|
|
||||||
EXPECT_EQ(*i, this->counter());
|
EXPECT_EQ(*i, this->counter());
|
||||||
++this->counter();
|
++this->counter();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N>
|
template <typename N>
|
||||||
void operator()(async_traverse_detach_tag,
|
void operator()(async_traverse_detach_tag, std::unique_ptr<std::size_t>& i,
|
||||||
std::unique_ptr<std::size_t>& i,
|
N&& next) {
|
||||||
N&& next)
|
unused(i);
|
||||||
{
|
unused(next);
|
||||||
HPX_UNUSED(i);
|
|
||||||
HPX_UNUSED(next);
|
|
||||||
|
|
||||||
// Should never be called!
|
// Should never be called!
|
||||||
HPX_TEST(false);
|
EXPECT_TRUE(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void operator()(async_traverse_complete_tag, T&& pack)
|
void operator()(async_traverse_complete_tag, T&& pack) {
|
||||||
{
|
unused(pack);
|
||||||
HPX_UNUSED(pack);
|
|
||||||
|
|
||||||
EXPECT_EQ(this->counter(), ArgCount);
|
EXPECT_EQ(this->counter(), ArgCount);
|
||||||
++this->counter();
|
++this->counter();
|
||||||
@ -432,113 +267,87 @@ struct async_unique_sync_visitor
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t ArgCount>
|
template <std::size_t ArgCount>
|
||||||
struct async_unique_visitor : async_counter_base<async_unique_visitor<ArgCount>>
|
struct async_unique_visitor
|
||||||
{
|
: async_counter_base<async_unique_visitor<ArgCount>> {
|
||||||
explicit async_unique_visitor(int dummy) {}
|
explicit async_unique_visitor(int /*dummy*/) {
|
||||||
|
}
|
||||||
|
|
||||||
bool operator()(async_traverse_visit_tag,
|
bool operator()(async_traverse_visit_tag,
|
||||||
std::unique_ptr<std::size_t>& i) const
|
std::unique_ptr<std::size_t>& i) const {
|
||||||
{
|
|
||||||
EXPECT_EQ(*i, this->counter());
|
EXPECT_EQ(*i, this->counter());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N>
|
template <typename N>
|
||||||
void operator()(async_traverse_detach_tag,
|
void operator()(async_traverse_detach_tag, std::unique_ptr<std::size_t>& i,
|
||||||
std::unique_ptr<std::size_t>& i,
|
N&& next) {
|
||||||
N&& next)
|
unused(i);
|
||||||
{
|
|
||||||
HPX_UNUSED(i);
|
|
||||||
|
|
||||||
++this->counter();
|
++this->counter();
|
||||||
std::forward<N>(next)();
|
std::forward<N>(next)();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void operator()(async_traverse_complete_tag, T&& pack)
|
void operator()(async_traverse_complete_tag, T&& pack) {
|
||||||
{
|
unused(pack);
|
||||||
HPX_UNUSED(pack);
|
|
||||||
|
|
||||||
EXPECT_EQ(this->counter(), ArgCount);
|
EXPECT_EQ(this->counter(), ArgCount);
|
||||||
++this->counter();
|
++this->counter();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void test_async_move_only_traversal()
|
template <typename T>
|
||||||
{
|
constexpr auto of(T i) {
|
||||||
auto const of = [](std::size_t i) {
|
return std::make_unique<T>(i);
|
||||||
return std::unique_ptr<std::size_t>(new std::size_t(i));
|
|
||||||
};
|
|
||||||
|
|
||||||
{
|
|
||||||
auto result = traverse_pack_async(
|
|
||||||
hpx::util::async_traverse_in_place_tag<
|
|
||||||
async_unique_sync_visitor<4>>{},
|
|
||||||
42, of(0), of(1), of(2), of(3));
|
|
||||||
EXPECT_EQ(result->counter(), 5U);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto result = traverse_pack_async(
|
|
||||||
hpx::util::async_traverse_in_place_tag<
|
|
||||||
async_unique_visitor<4>>{},
|
|
||||||
42, of(0), of(1), of(2), of(3));
|
|
||||||
EXPECT_EQ(result->counter(), 5U);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct invalidate_visitor : async_counter_base<invalidate_visitor>
|
TEST(async_traverse_in_place, construct_inplace_sync) {
|
||||||
{
|
auto result = traverse_pack_async(
|
||||||
explicit invalidate_visitor(int dummy) {}
|
async_traverse_in_place_tag<async_unique_sync_visitor<4>>{}, 42, of(0),
|
||||||
|
of(1), of(2), of(3));
|
||||||
|
EXPECT_EQ(result->counter(), 5U);
|
||||||
|
}
|
||||||
|
|
||||||
bool operator()(async_traverse_visit_tag, std::shared_ptr<int>& i) const
|
TEST(async_traverse_in_place, construct_inplace_async) {
|
||||||
{
|
auto result = traverse_pack_async(
|
||||||
|
async_traverse_in_place_tag<async_unique_visitor<4>>{}, 42, of(0), of(1),
|
||||||
|
of(2), of(3));
|
||||||
|
EXPECT_EQ(result->counter(), 5U);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct invalidate_visitor : async_counter_base<invalidate_visitor> {
|
||||||
|
explicit invalidate_visitor(int /*dummy*/) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(async_traverse_visit_tag, std::shared_ptr<int>& i) const {
|
||||||
EXPECT_EQ(*i, 22);
|
EXPECT_EQ(*i, 22);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N>
|
template <typename N>
|
||||||
void operator()(async_traverse_detach_tag,
|
void operator()(async_traverse_detach_tag, std::shared_ptr<int>& i,
|
||||||
std::shared_ptr<int>& i,
|
N&& next) {
|
||||||
N&& next)
|
unused(i);
|
||||||
{
|
|
||||||
HPX_UNUSED(i);
|
|
||||||
|
|
||||||
std::forward<N>(next)();
|
std::forward<N>(next)();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test whether the passed pack was passed as r-value reference
|
// Test whether the passed pack was passed as r-value reference
|
||||||
void operator()(async_traverse_complete_tag,
|
void operator()(async_traverse_complete_tag,
|
||||||
tuple<std::shared_ptr<int>>&& pack) const
|
tuple<std::shared_ptr<int>>&& pack) const {
|
||||||
{
|
|
||||||
// Invalidate the moved object
|
// Invalidate the moved object
|
||||||
tuple<std::shared_ptr<int>> moved = std::move(pack);
|
tuple<std::shared_ptr<int>> moved = std::move(pack);
|
||||||
|
|
||||||
HPX_UNUSED(moved);
|
unused(moved);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check whether the arguments are invalidated (moved out) when called
|
// Check whether the arguments are invalidated (moved out) when called
|
||||||
static void test_async_complete_invalidation()
|
TEST(async_complete_invalidation, check_whether_frame_released) {
|
||||||
{
|
|
||||||
auto value = std::make_shared<int>(22);
|
auto value = std::make_shared<int>(22);
|
||||||
|
|
||||||
auto frame = traverse_pack_async(
|
auto frame = traverse_pack_async(
|
||||||
hpx::util::async_traverse_in_place_tag<invalidate_visitor>{},
|
async_traverse_in_place_tag<invalidate_visitor>{}, 42, value);
|
||||||
42, value);
|
|
||||||
|
|
||||||
EXPECT_EQ(value.use_count(), 1U);
|
EXPECT_EQ(value.use_count(), 1L);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int, char**)
|
|
||||||
{
|
|
||||||
test_async_traversal();
|
|
||||||
test_async_container_traversal();
|
|
||||||
test_async_tuple_like_traversal();
|
|
||||||
test_async_mixed_traversal();
|
|
||||||
test_async_move_only_traversal();
|
|
||||||
test_async_complete_invalidation();
|
|
||||||
|
|
||||||
return hpx::util::report_errors();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user