From 9247bd84ba559a742354ba959111b3890dcf0ac1 Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Wed, 27 Feb 2019 17:51:28 +0100 Subject: [PATCH 01/15] Allow GlobRef conversion from child to parent --- dart-impl/mpi/src/dart_communication.c | 7 ++- dash/include/dash/GlobRef.h | 36 +++++++----- .../dash/iterator/internal/GlobRefBase.h | 4 +- dash/test/types/GlobRefTest.cc | 58 +++++++++++++++++-- 4 files changed, 79 insertions(+), 26 deletions(-) diff --git a/dart-impl/mpi/src/dart_communication.c b/dart-impl/mpi/src/dart_communication.c index 88ca9bc45..fd0cd4980 100644 --- a/dart-impl/mpi/src/dart_communication.c +++ b/dart-impl/mpi/src/dart_communication.c @@ -263,8 +263,11 @@ dart__mpi__get_basic( } if (remainder > 0) { - DART_LOG_TRACE("dart_get: MPI_Get (dest %p, size %zu)", - dest_ptr, remainder); + DART_LOG_TRACE( + "dart_get: MPI_Get (dest %p, size %zu, bytes: %zu)", + dest_ptr, + remainder, + remainder * dart__mpi__datatype_sizeof(dtype)); CHECK_MPI_RET( dart__mpi__get(dest_ptr, remainder, diff --git a/dash/include/dash/GlobRef.h b/dash/include/dash/GlobRef.h index bdb81d9f9..bc4d2a07a 100644 --- a/dash/include/dash/GlobRef.h +++ b/dash/include/dash/GlobRef.h @@ -71,32 +71,36 @@ class GlobRef { } + // clang-format off /** * Copy constructor, implicit if at least one of the following conditions is * satisfied: - * 1) value_type and _T are exactly the same types (including const and + * 1) value_type and _From are exactly the same types (including const and * volatile qualifiers - * 2) value_type and _T are the same types after removing const and + * 2) value_type and _From are the same types after removing const and * volatile qualifiers and value_type itself is const. */ + // clang-format on template < - typename _T, - long = internal::enable_implicit_copy_ctor::value> - constexpr GlobRef(const GlobRef<_T>& gref) + typename _From, + long = internal::enable_implicit_copy_ctor::value> + constexpr GlobRef(const GlobRef<_From>& gref) : GlobRef(gref.dart_gptr()) { } + // clang-format off /** * Copy constructor, explicit if the following conditions are satisfied. - * 1) value_type and _T are the same types after excluding const and + * 1) value_type and _From are the same types after excluding const and * volatile qualifiers - * 2) value_type is const and _T is non-const + * 2) value_type is const and _From is non-const */ + // clang-format on template < - typename _T, - int = internal::enable_explicit_copy_ctor::value> - explicit constexpr GlobRef(const GlobRef<_T>& gref) + typename _From, + int = internal::enable_explicit_copy_ctor::value> + explicit constexpr GlobRef(const GlobRef<_From>& gref) : GlobRef(gref.dart_gptr()) { } @@ -106,17 +110,17 @@ class GlobRef * avoid unintendet conversion */ template < - typename _T, - long = internal::enable_implicit_copy_ctor::value> - constexpr GlobRef(const GlobAsyncRef<_T>& gref) + typename _From, + long = internal::enable_implicit_copy_ctor::value> + constexpr GlobRef(const GlobAsyncRef<_From>& gref) : _gptr(gref.dart_gptr()) { } template < - typename _T, - int = internal::enable_explicit_copy_ctor::value> - explicit constexpr GlobRef(const GlobAsyncRef<_T>& gref) + typename _From, + int = internal::enable_explicit_copy_ctor::value> + explicit constexpr GlobRef(const GlobAsyncRef<_From>& gref) : GlobRef(gref.dart_gptr()) { } diff --git a/dash/include/dash/iterator/internal/GlobRefBase.h b/dash/include/dash/iterator/internal/GlobRefBase.h index cd3e66f3c..9f1a95972 100644 --- a/dash/include/dash/iterator/internal/GlobRefBase.h +++ b/dash/include/dash/iterator/internal/GlobRefBase.h @@ -30,9 +30,9 @@ using common_condition = std::is_same< template using enable_explicit_copy_ctor = null_v< typename std::enable_if< - common_condition::value && + (common_condition::value && !std::is_const::value && - std::is_const::value, + std::is_const::value) || std::is_base_of::value, LHS>::type>; template diff --git a/dash/test/types/GlobRefTest.cc b/dash/test/types/GlobRefTest.cc index f19db47a6..4acb4991c 100644 --- a/dash/test/types/GlobRefTest.cc +++ b/dash/test/types/GlobRefTest.cc @@ -1,20 +1,18 @@ - #include "../TestBase.h" #include "../TestLogHelpers.h" #include "GlobRefTest.h" #include -#include #include - +#include TEST_F(GlobRefTest, ArithmeticOps) { using value_t = int; using array_t = dash::Array; - array_t arr(dash::size()); - int neighbor = (dash::myid() + 1) % dash::size(); - dash::GlobRef gref = arr[neighbor]; + array_t arr(dash::size()); + int neighbor = (dash::myid() + 1) % dash::size(); + dash::GlobRef gref = arr[neighbor]; auto address_of_ref = dash::addressof(gref); @@ -58,3 +56,51 @@ TEST_F(GlobRefTest, ArithmeticOps) ASSERT_EQ_U(gref -= 1, 1); ASSERT_EQ_U(gref, 1); } + +struct Parent { + int x; +}; + +struct Child : public Parent { + int y; +}; + +namespace dash { +template <> +struct is_container_compatible : public std::true_type { +}; +} // namespace dash + +TEST_F(GlobRefTest, InheritanceTest) +{ + dash::Array array{100}; + + Child child; + child.x = 12; + child.y = 34; + + dash::fill(array.begin(), array.end(), child); + + array.barrier(); + + auto lpos = array.pattern().local(10); + + if (lpos.unit == static_cast(dash::myid())) { + child.x = 56; + child.y = 123; + array.local[lpos.index] = child; + } + + array.barrier(); + + auto asChild = array[10].get(); + + /* + * Here we explicitly cast it as Parent. In consequence, we read only 4 + * bytes (i.e., sizeof Parent), instead of 8. + */ + auto asParent = static_cast>(array[10]).get(); + + EXPECT_EQ_U(asParent.x, 56); + EXPECT_EQ_U(asChild.y, 123); +} From 5279b4b95302a304a9a68f147cd52f2eda0b1802 Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Thu, 28 Feb 2019 19:36:22 +0100 Subject: [PATCH 02/15] fix const correctness and inheritance semantics in GlobRef --- dash/include/dash/Types.h | 6 +- .../dash/iterator/internal/GlobRefBase.h | 28 ++++-- dash/test/types/GlobRefTest.cc | 98 ++++++++++++++++--- 3 files changed, 104 insertions(+), 28 deletions(-) diff --git a/dash/include/dash/Types.h b/dash/include/dash/Types.h index 6062565f7..86357e019 100644 --- a/dash/include/dash/Types.h +++ b/dash/include/dash/Types.h @@ -235,12 +235,8 @@ struct dart_punned_datatype { template struct is_container_compatible : public std::integral_constant::value -#ifdef DASH_HAVE_STD_TRIVIALLY_COPYABLE + std::is_default_constructible::value && std::is_trivially_copyable::value -#elif defined DASH_HAVE_TRIVIAL_COPY_INTRINSIC - && __has_trivial_copy(T) -#endif > { }; diff --git a/dash/include/dash/iterator/internal/GlobRefBase.h b/dash/include/dash/iterator/internal/GlobRefBase.h index 9f1a95972..bd24c69bc 100644 --- a/dash/include/dash/iterator/internal/GlobRefBase.h +++ b/dash/include/dash/iterator/internal/GlobRefBase.h @@ -27,20 +27,32 @@ using common_condition = std::is_same< typename std::remove_cv::type, typename std::remove_cv::type>; +/* + * A type is implicitly convertible to the other if + * we can + */ +template +using is_implicitly_convertible = std::is_convertible< + typename std::add_lvalue_reference::type, + typename std::add_lvalue_reference::type>; + template -using enable_explicit_copy_ctor = null_v< +using enable_implicit_copy_ctor = null_v< typename std::enable_if< - (common_condition::value && - !std::is_const::value && - std::is_const::value) || std::is_base_of::value, + is_implicitly_convertible::value, LHS>::type>; template -using enable_implicit_copy_ctor = null_v< +using enable_explicit_copy_ctor = null_v< typename std::enable_if< - std::is_same::value || - (common_condition::value && - std::is_const::value), + // 1) not implicitly convertible + !is_implicitly_convertible::value && + // 2.1) follows the rules of const correctness + std::is_assignable< + typename std::add_lvalue_reference::type, RHS> + ::value && + // 2.2) TODO: RHS is base of LHS and RHS must not be polymorphic... + true, LHS>::type>; // clang-format on diff --git a/dash/test/types/GlobRefTest.cc b/dash/test/types/GlobRefTest.cc index 4acb4991c..b5fc91f35 100644 --- a/dash/test/types/GlobRefTest.cc +++ b/dash/test/types/GlobRefTest.cc @@ -10,7 +10,9 @@ TEST_F(GlobRefTest, ArithmeticOps) { using value_t = int; using array_t = dash::Array; - array_t arr(dash::size()); + + array_t arr(dash::size()); + int neighbor = (dash::myid() + 1) % dash::size(); dash::GlobRef gref = arr[neighbor]; @@ -71,36 +73,102 @@ struct is_container_compatible : public std::true_type { }; } // namespace dash +static_assert(std::is_trivially_copy_constructible::value, ""); +static_assert(std::is_trivially_default_constructible::value, ""); +static_assert( + std::is_convertible< + std::add_lvalue_reference::type, + std::add_lvalue_reference::type>::value, + ""); +static_assert(std::is_assignable::value, ""); + +// clang-format off + +template +using common_condition = std::is_same< + typename std::remove_cv::type, + typename std::remove_cv::type>; + +template +using enable_explicit_copy_ctor = std::integral_constant::value && + !std::is_const::value && + std::is_const::value>; + +template +using enable_implicit_copy_ctor = std::integral_constant::value || + (common_condition::value && + std::is_const::value)>; + +// clang-format on + +TEST_F(GlobRefTest, ConstCorrectness) +{ + dash::Array dArray{100}; + std::array stdArray{}; + + // OK + int& ref = stdArray[0]; + dash::GlobRef gref = dArray[0]; + + // OK as well + int const& cref = ref; + dash::GlobRef cgref = gref; + + // NOT OK, because... + // We must not assign a non-const to const -> Compilation error + // int& ref2 = cref; + // dash::GlobRef gref2 = cgref; +} + TEST_F(GlobRefTest, InheritanceTest) { - dash::Array array{100}; + dash::Array dArray{100}; + std::array stdArray{}; Child child; child.x = 12; child.y = 34; - dash::fill(array.begin(), array.end(), child); + dash::fill(dArray.begin(), dArray.end(), child); + std::fill(stdArray.begin(), stdArray.end(), child); - array.barrier(); + dArray.barrier(); - auto lpos = array.pattern().local(10); + auto lpos = dArray.pattern().local(10); - if (lpos.unit == static_cast(dash::myid())) { - child.x = 56; - child.y = 123; - array.local[lpos.index] = child; + child.x = 56; + child.y = 123; + if (lpos.unit == dash::team_unit_t{dash::myid()}) { + dArray.local[lpos.index] = child; } - array.barrier(); + stdArray[lpos.index] = child; - auto asChild = array[10].get(); + dArray.barrier(); + + Child& asChild_array = stdArray[10]; + dash::GlobRef asChild_darray = dArray[10]; /* * Here we explicitly cast it as Parent. In consequence, we read only 4 * bytes (i.e., sizeof Parent), instead of 8. */ - auto asParent = static_cast>(array[10]).get(); - - EXPECT_EQ_U(asParent.x, 56); - EXPECT_EQ_U(asChild.y, 123); + Parent& asParent_array = stdArray[10]; + dash::GlobRef asParent_darray = dArray[10]; + + // static downcast is allowed with non-virtual base classes: + // see https://en.cppreference.com/w/cpp/language/static_cast, point 2 + Child& asChild_array2 = static_cast(asParent_array); + //TODO rko: Still to implement -> add in traits + //dash::GlobRef asChild_darray2 = static_cast>(asParent_darray); + + EXPECT_EQ_U(asParent_array.x, 56); + EXPECT_EQ_U(asChild_array.y, 123); + + EXPECT_EQ_U(static_cast(asChild_darray).y, 123); + //Look into the logs and grep for dart_get_blocking to see that we really + //get only 4 bytes instead of 8. + EXPECT_EQ_U(static_cast(asParent_darray).x, 56); } From 25885c9d6b36b9494cfbb43820702006dbe48342 Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Thu, 28 Feb 2019 19:39:23 +0100 Subject: [PATCH 03/15] remove boiler plate in Test --- dash/test/types/GlobRefTest.cc | 36 ---------------------------------- 1 file changed, 36 deletions(-) diff --git a/dash/test/types/GlobRefTest.cc b/dash/test/types/GlobRefTest.cc index b5fc91f35..29e805958 100644 --- a/dash/test/types/GlobRefTest.cc +++ b/dash/test/types/GlobRefTest.cc @@ -67,42 +67,6 @@ struct Child : public Parent { int y; }; -namespace dash { -template <> -struct is_container_compatible : public std::true_type { -}; -} // namespace dash - -static_assert(std::is_trivially_copy_constructible::value, ""); -static_assert(std::is_trivially_default_constructible::value, ""); -static_assert( - std::is_convertible< - std::add_lvalue_reference::type, - std::add_lvalue_reference::type>::value, - ""); -static_assert(std::is_assignable::value, ""); - -// clang-format off - -template -using common_condition = std::is_same< - typename std::remove_cv::type, - typename std::remove_cv::type>; - -template -using enable_explicit_copy_ctor = std::integral_constant::value && - !std::is_const::value && - std::is_const::value>; - -template -using enable_implicit_copy_ctor = std::integral_constant::value || - (common_condition::value && - std::is_const::value)>; - -// clang-format on - TEST_F(GlobRefTest, ConstCorrectness) { dash::Array dArray{100}; From 2960600f3dc5847aa596588e62af84c72e22ef39 Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Mon, 4 Mar 2019 17:36:54 +0100 Subject: [PATCH 04/15] static downcast from parent to child GlobRef --- .../dash/iterator/internal/GlobRefBase.h | 14 ++---- dash/test/types/GlobRefTest.cc | 47 +++++++++++++------ 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/dash/include/dash/iterator/internal/GlobRefBase.h b/dash/include/dash/iterator/internal/GlobRefBase.h index bd24c69bc..98708d6b0 100644 --- a/dash/include/dash/iterator/internal/GlobRefBase.h +++ b/dash/include/dash/iterator/internal/GlobRefBase.h @@ -22,11 +22,6 @@ struct null_v : std::integral_constant { // clang-format off -template -using common_condition = std::is_same< - typename std::remove_cv::type, - typename std::remove_cv::type>; - /* * A type is implicitly convertible to the other if * we can @@ -42,17 +37,18 @@ using enable_implicit_copy_ctor = null_v< is_implicitly_convertible::value, LHS>::type>; + template using enable_explicit_copy_ctor = null_v< typename std::enable_if< // 1) not implicitly convertible !is_implicitly_convertible::value && // 2.1) follows the rules of const correctness - std::is_assignable< + (std::is_constructible< typename std::add_lvalue_reference::type, RHS> - ::value && - // 2.2) TODO: RHS is base of LHS and RHS must not be polymorphic... - true, + ::value || + // 2.2) RHS is base of LHS and RHS must not be polymorphic... + std::is_base_of::value || !std::is_polymorphic::value), LHS>::type>; // clang-format on diff --git a/dash/test/types/GlobRefTest.cc b/dash/test/types/GlobRefTest.cc index 29e805958..44b6cd632 100644 --- a/dash/test/types/GlobRefTest.cc +++ b/dash/test/types/GlobRefTest.cc @@ -86,7 +86,7 @@ TEST_F(GlobRefTest, ConstCorrectness) // dash::GlobRef gref2 = cgref; } -TEST_F(GlobRefTest, InheritanceTest) +TEST_F(GlobRefTest, InheritanceConversionTest) { dash::Array dArray{100}; std::array stdArray{}; @@ -112,27 +112,46 @@ TEST_F(GlobRefTest, InheritanceTest) dArray.barrier(); - Child& asChild_array = stdArray[10]; - dash::GlobRef asChild_darray = dArray[10]; + Child& child_stdArray = stdArray[10]; + dash::GlobRef child_dArray = dArray[10]; /* * Here we explicitly cast it as Parent. In consequence, we read only 4 * bytes (i.e., sizeof Parent), instead of 8. */ - Parent& asParent_array = stdArray[10]; - dash::GlobRef asParent_darray = dArray[10]; + Parent& upcastParent_stdArray = stdArray[10]; + dash::GlobRef upcastParent_dArray = dArray[10]; + + auto const val = child; + auto const& cref = val; + // Child & ref = cref; + + // Why can we assign a const val to + auto& r_auto = val; + // But this does not work anymore... + // Child& r_Child = val; + + // The reason this works is the following + static_assert(std::is_same::value, ""); + // static_assert(std::is_constructible::value, ""); + + Parent const& r_upcast = r_auto; + Child const& r_downcast = static_cast(r_upcast); // static downcast is allowed with non-virtual base classes: // see https://en.cppreference.com/w/cpp/language/static_cast, point 2 - Child& asChild_array2 = static_cast(asParent_array); - //TODO rko: Still to implement -> add in traits - //dash::GlobRef asChild_darray2 = static_cast>(asParent_darray); + Child& downcastChild_stdArray = static_cast(upcastParent_stdArray); + dash::GlobRef downcastChild_dArray = + static_cast>(upcastParent_dArray); + + EXPECT_EQ_U(child_stdArray.y, 123); + EXPECT_EQ_U(static_cast(child_dArray).y, 123); - EXPECT_EQ_U(asParent_array.x, 56); - EXPECT_EQ_U(asChild_array.y, 123); + EXPECT_EQ_U(upcastParent_stdArray.x, 56); + EXPECT_EQ_U(downcastChild_stdArray.y, 123); - EXPECT_EQ_U(static_cast(asChild_darray).y, 123); - //Look into the logs and grep for dart_get_blocking to see that we really - //get only 4 bytes instead of 8. - EXPECT_EQ_U(static_cast(asParent_darray).x, 56); + // Look into the logs and grep for dart_get_blocking to see that we really + // get only 4 bytes instead of 8. + EXPECT_EQ_U(static_cast(upcastParent_dArray).x, 56); + EXPECT_EQ_U(static_cast(downcastChild_dArray).y, 123); } From af15e9755f387e7d4452fbabad2a11d66fef842c Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Mon, 4 Mar 2019 21:27:39 +0100 Subject: [PATCH 05/15] fix conversion rules for GlobRef and consider const correctness --- .../dash/iterator/internal/GlobRefBase.h | 27 ++++++++++--------- dash/test/types/GlobRefTest.cc | 14 +++++++--- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/dash/include/dash/iterator/internal/GlobRefBase.h b/dash/include/dash/iterator/internal/GlobRefBase.h index 98708d6b0..47cfc0d73 100644 --- a/dash/include/dash/iterator/internal/GlobRefBase.h +++ b/dash/include/dash/iterator/internal/GlobRefBase.h @@ -22,33 +22,34 @@ struct null_v : std::integral_constant { // clang-format off -/* - * A type is implicitly convertible to the other if - * we can - */ template using is_implicitly_convertible = std::is_convertible< typename std::add_lvalue_reference::type, typename std::add_lvalue_reference::type>; +template +using is_explicitly_convertible = std::integral_constant::value && + // 2.1) It is constructible or... + (std::is_constructible< + typename std::add_lvalue_reference::type, + typename std::add_lvalue_reference::type>::value || + // 2.2) if RHS is a base of RHS and both classes are non-polymorphic + (std::is_base_of::value + && !std::is_polymorphic::value + && !std::is_polymorphic::value))>; + template using enable_implicit_copy_ctor = null_v< typename std::enable_if< is_implicitly_convertible::value, LHS>::type>; - template using enable_explicit_copy_ctor = null_v< typename std::enable_if< - // 1) not implicitly convertible - !is_implicitly_convertible::value && - // 2.1) follows the rules of const correctness - (std::is_constructible< - typename std::add_lvalue_reference::type, RHS> - ::value || - // 2.2) RHS is base of LHS and RHS must not be polymorphic... - std::is_base_of::value || !std::is_polymorphic::value), + is_explicitly_convertible::value, LHS>::type>; // clang-format on diff --git a/dash/test/types/GlobRefTest.cc b/dash/test/types/GlobRefTest.cc index 44b6cd632..c3da3ed3d 100644 --- a/dash/test/types/GlobRefTest.cc +++ b/dash/test/types/GlobRefTest.cc @@ -128,12 +128,12 @@ TEST_F(GlobRefTest, InheritanceConversionTest) // Why can we assign a const val to auto& r_auto = val; - // But this does not work anymore... - // Child& r_Child = val; - // The reason this works is the following + // so auto include the const modifer as well. static_assert(std::is_same::value, ""); - // static_assert(std::is_constructible::value, ""); + + // But this does not work anymore... + // Child& r_Child = val; Parent const& r_upcast = r_auto; Child const& r_downcast = static_cast(r_upcast); @@ -155,3 +155,9 @@ TEST_F(GlobRefTest, InheritanceConversionTest) EXPECT_EQ_U(static_cast(upcastParent_dArray).x, 56); EXPECT_EQ_U(static_cast(downcastChild_dArray).y, 123); } + + +TEST_F(GlobRefTest, TypeTraits) +{ + //static_assert(! +} From c71b37374ad2e1282047c0e23f5d919fcf2d3309 Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Mon, 4 Mar 2019 21:28:27 +0100 Subject: [PATCH 06/15] disable const nonconst conversion in GlobRef and friends --- dash/test/iterator/GlobAsyncRefTest.cc | 6 +++--- dash/test/types/AtomicTest.cc | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dash/test/iterator/GlobAsyncRefTest.cc b/dash/test/iterator/GlobAsyncRefTest.cc index 6a671cc72..e433abb17 100644 --- a/dash/test/iterator/GlobAsyncRefTest.cc +++ b/dash/test/iterator/GlobAsyncRefTest.cc @@ -169,7 +169,7 @@ TEST_F(GlobAsyncRefTest, ConstTest) // assignment const -> const dash::GlobRef gref2 = carr[0]; // explicit conversion const->non-const - dash::GlobRef gref3(carr[0]); + //dash::GlobRef gref3(carr[0]); // should fail! //gref1.set(0); @@ -186,8 +186,8 @@ TEST_F(GlobAsyncRefTest, ConstTest) // assignment const -> const dash::GlobAsyncRef agref2 = carr.async[0]; // explicit conversion const->non-const - dash::GlobAsyncRef agref3 = - static_cast>(carr.async[0]); + //dash::GlobAsyncRef agref3 = + // static_cast>(carr.async[0]); dash::GlobAsyncRef agref4 = gref1; dash::GlobAsyncRef agref5{gref1}; diff --git a/dash/test/types/AtomicTest.cc b/dash/test/types/AtomicTest.cc index 364d2e0f8..5e858b7a3 100644 --- a/dash/test/types/AtomicTest.cc +++ b/dash/test/types/AtomicTest.cc @@ -652,8 +652,8 @@ TEST_F(AtomicTest, ConstTest) { // assignment const -> const dash::GlobRef> gref2 = carr[0]; // explicit conversion const->non-const - dash::GlobRef> gref3 = - static_cast>>(carr[0]); + //dash::GlobRef> gref3 = + // static_cast>>(carr[0]); // should fail! //gref1.add(1); @@ -670,8 +670,8 @@ TEST_F(AtomicTest, ConstTest) { // assignment const -> const dash::GlobAsyncRef> agref2 = carr.async[0]; // explicit conversion const->non-const - dash::GlobAsyncRef> agref3 = - static_cast>>(carr.async[0]); + //dash::GlobAsyncRef> agref3 = + // static_cast>>(carr.async[0]); // should fail! //agref1.add(1); From 9b904ebe99c63f979a5f8ed609bc906e8596a5fe Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Tue, 5 Mar 2019 21:54:38 +0100 Subject: [PATCH 07/15] conversion rules for GlobRef. More tests. --- dash/include/dash/GlobAsyncRef.h | 40 +++---- dash/include/dash/GlobRef.h | 40 +++---- dash/include/dash/atomic/GlobAtomicAsyncRef.h | 32 +++--- dash/include/dash/atomic/GlobAtomicRef.h | 40 +++---- .../dash/iterator/internal/GlobRefBase.h | 61 +++++++++-- dash/test/types/GlobRefTest.cc | 101 +++++++++++++++--- 6 files changed, 213 insertions(+), 101 deletions(-) diff --git a/dash/include/dash/GlobAsyncRef.h b/dash/include/dash/GlobAsyncRef.h index 87c4e1e19..21b40e99c 100644 --- a/dash/include/dash/GlobAsyncRef.h +++ b/dash/include/dash/GlobAsyncRef.h @@ -124,43 +124,43 @@ class GlobAsyncRef /** * Copy constructor, implicit if at least one of the following conditions is * satisfied: - * 1) value_type and _T are exactly the same types (including const and + * 1) value_type and From are exactly the same types (including const and * volatile qualifiers - * 2) value_type and _T are the same types after removing const and volatile + * 2) value_type and From are the same types after removing const and volatile * qualifiers and value_type itself is const. */ - template::value> - GlobAsyncRef(const GlobAsyncRef<_T>& gref) + template::value> + GlobAsyncRef(const GlobAsyncRef& gref) : GlobAsyncRef(gref.dart_gptr()) { } /** * Copy constructor, explicit if the following conditions are satisfied. - * 1) value_type and _T are the same types after excluding const and + * 1) value_type and From are the same types after excluding const and * volatile qualifiers - * 2) value_type is const and _T is non-const + * 2) value_type is const and From is non-const */ template < - typename _T, - long = internal::enable_explicit_copy_ctor::value> - explicit GlobAsyncRef(const GlobAsyncRef<_T>& gref) + typename From, + long = detail::enable_explicit_copy_ctor::value> + explicit GlobAsyncRef(const GlobAsyncRef& gref) : GlobAsyncRef(gref.dart_gptr()) { } template < - typename _T, - int = internal::enable_implicit_copy_ctor::value> - GlobAsyncRef(const GlobRef<_T>& gref) + typename From, + int = detail::enable_implicit_copy_ctor::value> + GlobAsyncRef(const GlobRef& gref) : GlobAsyncRef(gref.dart_gptr()) { } template < - typename _T, - long = internal::enable_explicit_copy_ctor::value> - explicit GlobAsyncRef(const GlobRef<_T>& gref) + typename From, + long = detail::enable_explicit_copy_ctor::value> + explicit GlobAsyncRef(const GlobRef& gref) : GlobAsyncRef(gref.dart_gptr()) { } @@ -192,20 +192,20 @@ class GlobAsyncRef * specified offset */ template - GlobAsyncRef::type> + GlobAsyncRef::type> member(size_t offs) const { - return GlobAsyncRef::type>(*this, offs); + return GlobAsyncRef::type>(*this, offs); } /** * Get the member via pointer to member */ template - GlobAsyncRef::type> + GlobAsyncRef::type> member( const MEMTYPE P::*mem) const { auto offs = (size_t) & (reinterpret_cast(0)->*mem); - return member::type>(offs); + return member::type>(offs); } /** diff --git a/dash/include/dash/GlobRef.h b/dash/include/dash/GlobRef.h index bc4d2a07a..2e514826a 100644 --- a/dash/include/dash/GlobRef.h +++ b/dash/include/dash/GlobRef.h @@ -83,11 +83,10 @@ class GlobRef // clang-format on template < typename _From, - long = internal::enable_implicit_copy_ctor::value> + long = detail::enable_implicit_copy_ctor<_From, value_type>::value> constexpr GlobRef(const GlobRef<_From>& gref) : GlobRef(gref.dart_gptr()) - { - } + {} // clang-format off /** @@ -99,7 +98,7 @@ class GlobRef // clang-format on template < typename _From, - int = internal::enable_explicit_copy_ctor::value> + int = detail::enable_explicit_copy_ctor<_From, value_type>::value> explicit constexpr GlobRef(const GlobRef<_From>& gref) : GlobRef(gref.dart_gptr()) { @@ -111,7 +110,7 @@ class GlobRef */ template < typename _From, - long = internal::enable_implicit_copy_ctor::value> + long = detail::enable_implicit_copy_ctor<_From, value_type>::value> constexpr GlobRef(const GlobAsyncRef<_From>& gref) : _gptr(gref.dart_gptr()) { @@ -119,7 +118,7 @@ class GlobRef template < typename _From, - int = internal::enable_explicit_copy_ctor::value> + int = detail::enable_explicit_copy_ctor<_From, value_type>::value> explicit constexpr GlobRef(const GlobAsyncRef<_From>& gref) : GlobRef(gref.dart_gptr()) { @@ -367,26 +366,27 @@ class GlobRef * Get a global ref to a member of a certain type at the * specified offset */ - template - GlobRef::type> - member(size_t offs) const { + template + auto member(size_t offs) const DASH_NOEXCEPT + { + using ref_t = GlobRef::value, + typename std::add_const::type, + MEMTYPE>::type>; + dart_gptr_t dartptr = _gptr; - DASH_ASSERT_RETURNS( - dart_gptr_incaddr(&dartptr, offs), - DART_OK); - return GlobRef::type>(dartptr); + DASH_ASSERT_RETURNS(dart_gptr_incaddr(&dartptr, offs), DART_OK); + + return ref_t{dartptr}; } /** * Get the member via pointer to member */ - template - GlobRef::type> - member( - const MEMTYPE P::*mem) const { - // TODO: Thaaaat ... looks hacky. - auto offs = (size_t) & (reinterpret_cast(0)->*mem); - return member::type>(offs); + template + auto member(const MEMTYPE P::*mem) const DASH_NOEXCEPT + { + return member(detail::offset_of(mem)); } /** diff --git a/dash/include/dash/atomic/GlobAtomicAsyncRef.h b/dash/include/dash/atomic/GlobAtomicAsyncRef.h index dfdf789f3..b2cd029ee 100644 --- a/dash/include/dash/atomic/GlobAtomicAsyncRef.h +++ b/dash/include/dash/atomic/GlobAtomicAsyncRef.h @@ -101,40 +101,40 @@ class GlobAsyncRef> /** * Copy constructor: Implicit if at least one of the following conditions is * satisfied: - * 1) value_type and _T are exactly the same types (including const and + * 1) value_type and From are exactly the same types (including const and * volatile qualifiers - * 2) value_type and _T are the same types after removing const and + * 2) value_type and From are the same types after removing const and * volatile qualifiers and value_type itself is const. */ - template::value> - GlobAsyncRef(const GlobAsyncRef>& gref) + template::value> + GlobAsyncRef(const GlobAsyncRef>& gref) : GlobAsyncRef(gref.dart_gptr()) { } /** * Copy constructor: Explicit if the following conditions are satisfied. - * 1) value_type and _T are the same types after excluding const and + * 1) value_type and From are the same types after excluding const and * volatile qualifiers - * 2) value_type is const and _T is non-const + * 2) value_type is const and From is non-const */ - template::value> + template::value> explicit - GlobAsyncRef(const GlobAsyncRef>& gref) + GlobAsyncRef(const GlobAsyncRef>& gref) : GlobAsyncRef(gref.dart_gptr()) { } - template::value> - GlobAsyncRef(const GlobRef>& gref) + template::value> + GlobAsyncRef(const GlobRef>& gref) : GlobAsyncRef(gref.dart_gptr()) { } - template::value> + template::value> explicit - GlobAsyncRef(const GlobRef>& gref) + GlobAsyncRef(const GlobRef>& gref) : GlobAsyncRef(gref.dart_gptr()) { } diff --git a/dash/include/dash/atomic/GlobAtomicRef.h b/dash/include/dash/atomic/GlobAtomicRef.h index a3cbc4af4..347aee9cf 100644 --- a/dash/include/dash/atomic/GlobAtomicRef.h +++ b/dash/include/dash/atomic/GlobAtomicRef.h @@ -92,29 +92,29 @@ class GlobRef> { /** * Copy constructor: Implicit if at least one of the following conditions is * satisfied: - * 1) value_type and _T are exactly the same types (including const and + * 1) value_type and From are exactly the same types (including const and * volatile qualifiers - * 2) value_type and _T are the same types after removing const and + * 2) value_type and From are the same types after removing const and * volatile qualifiers and value_type itself is const. */ template < - typename _T, - int = internal::enable_implicit_copy_ctor::value> - GlobRef(const GlobRef>& gref) + typename From, + int = detail::enable_implicit_copy_ctor::value> + GlobRef(const GlobRef>& gref) : GlobRef(gref.dart_gptr()) { } /** * Copy constructor: Explicit if the following conditions are satisfied. - * 1) value_type and _T are the same types after excluding const and + * 1) value_type and From are the same types after excluding const and * volatile qualifiers - * 2) value_type is const and _T is non-const + * 2) value_type is const and From is non-const */ template < - typename _T, - long = internal::enable_explicit_copy_ctor::value> - explicit GlobRef(const GlobRef>& gref) + typename From, + long = detail::enable_explicit_copy_ctor::value> + explicit GlobRef(const GlobRef>& gref) : GlobRef(gref.dart_gptr()) { } @@ -122,29 +122,29 @@ class GlobRef> { /** * Copy constructor: Implicit if at least one of the following conditions is * satisfied: - * 1) value_type and _T are exactly the same types (including const and + * 1) value_type and From are exactly the same types (including const and * volatile qualifiers - * 2) value_type and _T are the same types after removing const and + * 2) value_type and From are the same types after removing const and * volatile qualifiers and value_type itself is const. */ template < - typename _T, - int = internal::enable_implicit_copy_ctor::value> - GlobRef(const GlobAsyncRef>& gref) + typename From, + int = detail::enable_implicit_copy_ctor::value> + GlobRef(const GlobAsyncRef>& gref) : GlobRef(gref.dart_gptr()) { } /** * Copy constructor: Explicit if the following conditions are satisfied. - * 1) value_type and _T are the same types after excluding const and + * 1) value_type and From are the same types after excluding const and * volatile qualifiers - * 2) value_type is const and _T is non-const + * 2) value_type is const and From is non-const */ template < - typename _T, - long = internal::enable_explicit_copy_ctor::value> - explicit GlobRef(const GlobAsyncRef>& gref) + typename From, + long = detail::enable_explicit_copy_ctor::value> + explicit GlobRef(const GlobAsyncRef>& gref) : GlobRef(gref.dart_gptr()) { } diff --git a/dash/include/dash/iterator/internal/GlobRefBase.h b/dash/include/dash/iterator/internal/GlobRefBase.h index 47cfc0d73..c7dfe8c37 100644 --- a/dash/include/dash/iterator/internal/GlobRefBase.h +++ b/dash/include/dash/iterator/internal/GlobRefBase.h @@ -1,10 +1,12 @@ #ifndef DASH__ITERATOR__INTERNAL__GLOBREF_BASE_H__INCLUDED #define DASH__ITERATOR__INTERNAL__GLOBREF_BASE_H__INCLUDED +#include +#include #include namespace dash { -namespace internal { +namespace detail { template struct add_const_from_type { @@ -24,21 +26,49 @@ struct null_v : std::integral_constant { template using is_implicitly_convertible = std::is_convertible< - typename std::add_lvalue_reference::type, - typename std::add_lvalue_reference::type>; + typename std::add_lvalue_reference::type, + typename std::add_lvalue_reference::type>; +#if 0 template using is_explicitly_convertible = std::integral_constant::value && // 2.1) It is constructible or... (std::is_constructible< - typename std::add_lvalue_reference::type, - typename std::add_lvalue_reference::type>::value || + typename std::add_lvalue_reference::type, + typename std::add_lvalue_reference::type>::value || // 2.2) if RHS is a base of RHS and both classes are non-polymorphic - (std::is_base_of::value - && !std::is_polymorphic::value - && !std::is_polymorphic::value))>; + (std::conditional::value, + std::is_const, + std::true_type>::type::value + + && std::is_base_of::value + && !std::is_polymorphic::value + && !std::is_polymorphic::value))>; +#else +template +struct is_explicitly_convertible { + template + static void f(T); + + template + static constexpr auto test(int) + -> decltype(f(static_cast(std::declval())), true) + { + return true; + } + + template + static constexpr auto test(...) -> bool + { + return false; + } + + static bool const value = test(0); +}; +#endif + template using enable_implicit_copy_ctor = null_v< @@ -49,11 +79,22 @@ using enable_implicit_copy_ctor = null_v< template using enable_explicit_copy_ctor = null_v< typename std::enable_if< - is_explicitly_convertible::value, + !is_implicitly_convertible::value && + is_explicitly_convertible< + typename std::add_lvalue_reference::type, + typename std::add_lvalue_reference::type>::value, LHS>::type>; // clang-format on -} // namespace internal +template +inline std::size_t constexpr offset_of(T1 T2::*member) noexcept +{ + constexpr T2 dummy{}; + return std::size_t{std::uintptr_t(std::addressof(dummy.*member))} - + std::size_t{std::uintptr_t(std::addressof(dummy))}; +} + +} // namespace detail } // namespace dash #endif diff --git a/dash/test/types/GlobRefTest.cc b/dash/test/types/GlobRefTest.cc index c3da3ed3d..ebb122b12 100644 --- a/dash/test/types/GlobRefTest.cc +++ b/dash/test/types/GlobRefTest.cc @@ -73,12 +73,21 @@ TEST_F(GlobRefTest, ConstCorrectness) std::array stdArray{}; // OK - int& ref = stdArray[0]; + int & ref = stdArray[0]; dash::GlobRef gref = dArray[0]; // OK as well - int const& cref = ref; - dash::GlobRef cgref = gref; + int const &cref = ref; + // + // + dash::GlobRef cgref{gref}; + // + // + + static_assert( + dash::detail::is_implicitly_convertible::value, ""); + static_assert( + !dash::detail::is_implicitly_convertible::value, ""); // NOT OK, because... // We must not assign a non-const to const -> Compilation error @@ -112,35 +121,36 @@ TEST_F(GlobRefTest, InheritanceConversionTest) dArray.barrier(); - Child& child_stdArray = stdArray[10]; + Child & child_stdArray = stdArray[10]; dash::GlobRef child_dArray = dArray[10]; /* * Here we explicitly cast it as Parent. In consequence, we read only 4 * bytes (i.e., sizeof Parent), instead of 8. */ - Parent& upcastParent_stdArray = stdArray[10]; + Parent & upcastParent_stdArray = stdArray[10]; dash::GlobRef upcastParent_dArray = dArray[10]; auto const val = child; - auto const& cref = val; - // Child & ref = cref; + auto const &cref = val; // Why can we assign a const val to - auto& r_auto = val; + auto &r_auto = val; // The reason this works is the following - // so auto include the const modifer as well. - static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, ""); + // => auto type deduction includes the const modifer as well. + // However, the following is malformed. + // Child & ref = cref; // But this does not work anymore... // Child& r_Child = val; - Parent const& r_upcast = r_auto; - Child const& r_downcast = static_cast(r_upcast); + Parent const &r_upcast = r_auto; + Child const & r_downcast = static_cast(r_upcast); // static downcast is allowed with non-virtual base classes: // see https://en.cppreference.com/w/cpp/language/static_cast, point 2 - Child& downcastChild_stdArray = static_cast(upcastParent_stdArray); + Child &downcastChild_stdArray = static_cast(upcastParent_stdArray); dash::GlobRef downcastChild_dArray = static_cast>(upcastParent_dArray); @@ -156,8 +166,69 @@ TEST_F(GlobRefTest, InheritanceConversionTest) EXPECT_EQ_U(static_cast(downcastChild_dArray).y, 123); } +template +using dash_ref = dash::GlobRef; -TEST_F(GlobRefTest, TypeTraits) +TEST_F(GlobRefTest, ConversionRules) { - //static_assert(! + static_assert( + std::is_convertible, dash_ref>::value, "1.1"); + static_assert(std::is_convertible::value, "1.2"); + + static_assert( + !std::is_convertible, dash_ref>::value, "2.1"); + static_assert(!std::is_convertible::value, "2.2"); + + static_assert( + !std::is_convertible, dash_ref>::value, "3.1"); + static_assert(!std::is_convertible::value, "3.2"); + + static_assert( + std::is_convertible, dash_ref>::value, "4.1"); + static_assert(std::is_convertible::value, "4.2"); + + static_assert( + std::is_convertible, dash_ref>::value, + "5.1"); + static_assert(std::is_convertible::value, "5.2"); + + static_assert(!std::is_convertible::value, "6.1"); + + static_assert( + !std::is_convertible, dash_ref>::value, + "7.1"); + static_assert(!std::is_convertible::value, "7.2"); + static_assert( + !dash::detail::is_explicitly_convertible:: + value, + "7.3"); + static_assert( + !dash::detail::is_explicitly_convertible< + dash_ref, + dash_ref>::value, + "7.4"); + + static_assert(!std::is_convertible::value, "8.1"); + static_assert( + !std::is_convertible, dash_ref>::value, + "8.2"); + static_assert( + dash::detail::is_explicitly_convertible::value, + "8.3"); + static_assert( + dash::detail::is_explicitly_convertible< + dash_ref, + dash_ref>::value, + "8.4"); + + static_assert(!std::is_convertible::value, "9.1"); + static_assert( + !std::is_convertible, dash_ref>::value, "9.2"); + static_assert( + dash::detail::is_explicitly_convertible::value, + "9.3"); + static_assert( + dash::detail:: + is_explicitly_convertible, dash_ref>::value, + "9.4"); } From 5406418baead1c861b0df83425c50bb2586ab3e3 Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Tue, 5 Mar 2019 22:01:45 +0100 Subject: [PATCH 08/15] minor fix. --- dash/test/types/GlobRefTest.cc | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/dash/test/types/GlobRefTest.cc b/dash/test/types/GlobRefTest.cc index ebb122b12..88b0fef92 100644 --- a/dash/test/types/GlobRefTest.cc +++ b/dash/test/types/GlobRefTest.cc @@ -193,42 +193,41 @@ TEST_F(GlobRefTest, ConversionRules) static_assert(std::is_convertible::value, "5.2"); static_assert(!std::is_convertible::value, "6.1"); - static_assert( !std::is_convertible, dash_ref>::value, - "7.1"); - static_assert(!std::is_convertible::value, "7.2"); + "6.2"); + static_assert( !dash::detail::is_explicitly_convertible:: value, - "7.3"); + "6.3"); static_assert( !dash::detail::is_explicitly_convertible< dash_ref, dash_ref>::value, - "7.4"); + "6.4"); - static_assert(!std::is_convertible::value, "8.1"); + static_assert(!std::is_convertible::value, "7.1"); static_assert( !std::is_convertible, dash_ref>::value, - "8.2"); + "7.2"); static_assert( dash::detail::is_explicitly_convertible::value, - "8.3"); + "7.3"); static_assert( dash::detail::is_explicitly_convertible< dash_ref, dash_ref>::value, - "8.4"); + "7.4"); - static_assert(!std::is_convertible::value, "9.1"); + static_assert(!std::is_convertible::value, "8.1"); static_assert( - !std::is_convertible, dash_ref>::value, "9.2"); + !std::is_convertible, dash_ref>::value, "8.2"); static_assert( dash::detail::is_explicitly_convertible::value, - "9.3"); + "8.3"); static_assert( dash::detail:: is_explicitly_convertible, dash_ref>::value, - "9.4"); + "8.4"); } From fdfc1299248ea93c76a056ccddb19b64da589cc1 Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Wed, 6 Mar 2019 09:48:44 +0100 Subject: [PATCH 09/15] Code refactoring to better understand my intutions. --- dash/test/types/GlobRefTest.cc | 109 +++++++++++++++++---------------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/dash/test/types/GlobRefTest.cc b/dash/test/types/GlobRefTest.cc index 88b0fef92..9ab9eb50f 100644 --- a/dash/test/types/GlobRefTest.cc +++ b/dash/test/types/GlobRefTest.cc @@ -169,65 +169,68 @@ TEST_F(GlobRefTest, InheritanceConversionTest) template using dash_ref = dash::GlobRef; -TEST_F(GlobRefTest, ConversionRules) -{ - static_assert( - std::is_convertible, dash_ref>::value, "1.1"); - static_assert(std::is_convertible::value, "1.2"); +template < + class LHS, + class RHS, + bool expected_implicit, + bool expected_explicit> +struct StandardConformabilityTester { + static constexpr void test() + { + static_assert( + // First check if the implicit conversion rules match... + std::is_convertible::value == expected_implicit && + std::is_convertible, dash_ref>::value == + expected_implicit && + // Then the explicit rules... + dash::detail::is_explicitly_convertible::value == + expected_explicit && + dash::detail::is_explicitly_convertible< + dash_ref, + dash_ref>::value == expected_explicit, + ""); + } +}; - static_assert( - !std::is_convertible, dash_ref>::value, "2.1"); - static_assert(!std::is_convertible::value, "2.2"); +template +struct StandardConformabilityTester { + static constexpr void test() + { + // If we can implicitly convert we do not consider explicit conversion + // rules + static_assert( + std::is_convertible::value && + std::is_convertible, dash_ref>::value, + ""); + } +}; - static_assert( - !std::is_convertible, dash_ref>::value, "3.1"); - static_assert(!std::is_convertible::value, "3.2"); +TEST_F(GlobRefTest, ConversionRules) +{ + constexpr bool ignore = true; - static_assert( - std::is_convertible, dash_ref>::value, "4.1"); - static_assert(std::is_convertible::value, "4.2"); + // Rule 1: T &-> const T & + StandardConformabilityTester::test(); + // Rule 2: const T & -> int & + // Conversion Fails due to const correctness + StandardConformabilityTester::test(); - static_assert( - std::is_convertible, dash_ref>::value, - "5.1"); - static_assert(std::is_convertible::value, "5.2"); + // Rule 3: T & -> U & if T and U are not related (FAILS) + StandardConformabilityTester::test(); - static_assert(!std::is_convertible::value, "6.1"); - static_assert( - !std::is_convertible, dash_ref>::value, - "6.2"); + // Rule 4: Child & -> Parent & (Upcast) + StandardConformabilityTester::test(); - static_assert( - !dash::detail::is_explicitly_convertible:: - value, - "6.3"); - static_assert( - !dash::detail::is_explicitly_convertible< - dash_ref, - dash_ref>::value, - "6.4"); + // Rule 5.1: Child & -> const Parent & (Upcast to const) + // Rule 5.2: const Child & -> Parent & (FAILS, const correctness) + StandardConformabilityTester::test(); + StandardConformabilityTester::test(); - static_assert(!std::is_convertible::value, "7.1"); - static_assert( - !std::is_convertible, dash_ref>::value, - "7.2"); - static_assert( - dash::detail::is_explicitly_convertible::value, - "7.3"); - static_assert( - dash::detail::is_explicitly_convertible< - dash_ref, - dash_ref>::value, - "7.4"); + // Rule 6.1: Parent & -> const Child & + // Rule 6.2: Parent & -> Child & + // Explicit downcast (VALID) + // see https://en.cppreference.com/w/cpp/language/static_cast + StandardConformabilityTester::test(); + StandardConformabilityTester::test(); - static_assert(!std::is_convertible::value, "8.1"); - static_assert( - !std::is_convertible, dash_ref>::value, "8.2"); - static_assert( - dash::detail::is_explicitly_convertible::value, - "8.3"); - static_assert( - dash::detail:: - is_explicitly_convertible, dash_ref>::value, - "8.4"); } From 19663780554d81bb0c6944328128f7ff8d4e44ea Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Wed, 6 Mar 2019 16:27:50 +0100 Subject: [PATCH 10/15] introduce a base class for references for common code --- dash/include/dash/GlobRef.h | 255 +++++++----------- dash/include/dash/Shared.h | 4 +- dash/include/dash/iterator/GlobIter.h | 4 +- .../dash/iterator/internal/GlobRefBase.h | 85 ++++++ dash/test/types/GlobRefTest.cc | 1 + 5 files changed, 181 insertions(+), 168 deletions(-) diff --git a/dash/include/dash/GlobRef.h b/dash/include/dash/GlobRef.h index 2e514826a..e9e901f6d 100644 --- a/dash/include/dash/GlobRef.h +++ b/dash/include/dash/GlobRef.h @@ -1,108 +1,44 @@ #ifndef DASH__GLOBREF_H_ #define DASH__GLOBREF_H_ -#include #include #include namespace dash { -// forward declaration -template -class GlobAsyncRef; - // Forward declarations -template class GlobPtr; +template class GlobAsyncRef; template -class GlobRef +class GlobRef : public detail::GlobRefBase { - template - friend std::ostream & operator<<( - std::ostream & os, - const GlobRef & gref); - - template - friend class GlobRef; - + using base_t = detail::GlobRefBase; public: - using value_type = T; - using const_value_type = typename std::add_const::type; - using nonconst_value_type = typename std::remove_const::type; - using self_t = GlobRef; + using value_type = typename base_t::value_type; + using const_value_type = typename base_t::const_value_type; + using nonconst_value_type = typename base_t::nonconst_value_type; using const_type = GlobRef; +private: + template + friend class GlobRef; //required for .member() - template - friend class GlobPtr; - - template - friend class GlobIter; - template friend class GlobViewIter; -private: - /** - * PRIVATE: Constructor, creates an GlobRef object referencing an element in global - * memory. - */ - template - explicit constexpr GlobRef( - /// Pointer to referenced object in global memory - const GlobPtr & gptr) - : GlobRef(gptr.dart_gptr()) - { } + template + friend std::ostream & operator<<( + std::ostream & os, + const GlobRef & gref); public: - /** - * Reference semantics forbid declaration without definition. - */ - GlobRef() = delete; - - GlobRef(const GlobRef & other) = delete; + //inherit all constructors from parent class + using base_t::GlobRefBase; /** - * Constructor, creates an GlobRef object referencing an element in global - * memory. + * COPY Construction */ - explicit constexpr GlobRef(dart_gptr_t dart_gptr) - : _gptr(dart_gptr) - { - } - - // clang-format off - /** - * Copy constructor, implicit if at least one of the following conditions is - * satisfied: - * 1) value_type and _From are exactly the same types (including const and - * volatile qualifiers - * 2) value_type and _From are the same types after removing const and - * volatile qualifiers and value_type itself is const. - */ - // clang-format on - template < - typename _From, - long = detail::enable_implicit_copy_ctor<_From, value_type>::value> - constexpr GlobRef(const GlobRef<_From>& gref) - : GlobRef(gref.dart_gptr()) - {} - - // clang-format off - /** - * Copy constructor, explicit if the following conditions are satisfied. - * 1) value_type and _From are the same types after excluding const and - * volatile qualifiers - * 2) value_type is const and _From is non-const - */ - // clang-format on - template < - typename _From, - int = detail::enable_explicit_copy_ctor<_From, value_type>::value> - explicit constexpr GlobRef(const GlobRef<_From>& gref) - : GlobRef(gref.dart_gptr()) - { - } + GlobRef(const GlobRef & other) = default; /** * Constructor to convert \c GlobAsyncRef to GlobRef. Set to explicit to @@ -110,35 +46,26 @@ class GlobRef */ template < typename _From, - long = detail::enable_implicit_copy_ctor<_From, value_type>::value> + long = detail::enable_implicit_copy_ctor<_From, typename base_t::value_type>::value> constexpr GlobRef(const GlobAsyncRef<_From>& gref) - : _gptr(gref.dart_gptr()) + : base_t(gref.dart_gptr()) { } template < typename _From, - int = detail::enable_explicit_copy_ctor<_From, value_type>::value> + int = detail::enable_explicit_copy_ctor<_From, typename base_t::value_type>::value> explicit constexpr GlobRef(const GlobAsyncRef<_From>& gref) - : GlobRef(gref.dart_gptr()) + : base_t(gref.dart_gptr()) { } /** - * Move Constructor + * Copy Assignment: We copy the value behind this address, NOT the reference */ - GlobRef(self_t&& other) - :_gptr(std::move(other._gptr)) + const GlobRef & operator=(const GlobRef & other) const { - DASH_LOG_TRACE("GlobRef.GlobRef(GlobRef &&)", _gptr); - } - - /** - * Copy Assignment - */ - const self_t & operator=(const self_t & other) const - { - if (DART_GPTR_EQUAL(_gptr, other._gptr)) { + if (DART_GPTR_EQUAL(this->dart_gptr(), other.dart_gptr())) { return *this; } set(static_cast(other)); @@ -148,8 +75,9 @@ class GlobRef /** * Move Assignment: Redirects to Copy Assignment */ - self_t& operator=(self_t&& other) { - DASH_LOG_TRACE("GlobRef.operator=(GlobRef &&)", _gptr); + GlobRef& operator=(GlobRef&& other) { + auto dart_pointer = this->dart_gptr(); + DASH_LOG_TRACE("GlobRef.operator=(GlobRef &&)", dart_pointer); operator=(other); return *this; } @@ -157,7 +85,8 @@ class GlobRef /** * Value-assignment operator. */ - const self_t & operator=(const value_type& val) const { + auto& operator=(const value_type& val) const { + static_assert(!std::is_const::value, "must not be const"); set(val); return *this; } @@ -165,67 +94,44 @@ class GlobRef operator nonconst_value_type() const { DASH_LOG_TRACE("GlobRef.T()", "conversion operator"); - DASH_LOG_TRACE_VAR("GlobRef.T()", _gptr); + auto dart_pointer = this->dart_gptr(); + DASH_LOG_TRACE_VAR("GlobRef.T()", dart_pointer); nonconst_value_type t; - dash::internal::get_blocking(_gptr, &t, 1); - DASH_LOG_TRACE_VAR("GlobRef.T >", _gptr); + dash::internal::get_blocking(dart_pointer, &t, 1); return t; } - template - bool operator==(const GlobRef & other) const { - ValueT val = other.get(); - return operator==(val); - } - - template - bool operator!=(const GlobRef & other) const { - return !(*this == other); - } - - template - constexpr bool operator==(const ValueT& value) const - { - return static_cast(*this) == value; - } - - template - constexpr bool operator!=(const ValueT& value) const - { - return !(*this == value); - } - void set(const value_type & val) const { static_assert(std::is_same::value, "Cannot modify value referenced by GlobRef!"); DASH_LOG_TRACE_VAR("GlobRef.set()", val); - DASH_LOG_TRACE_VAR("GlobRef.set", _gptr); - // TODO: Clarify if dart-call can be avoided if - // _gptr->is_local() - dash::internal::put_blocking(_gptr, &val, 1); - DASH_LOG_TRACE_VAR("GlobRef.set >", _gptr); + auto dart_pointer = this->dart_gptr(); + DASH_LOG_TRACE_VAR("GlobRef.set", dart_pointer); + dash::internal::put_blocking(dart_pointer, &val, 1); } nonconst_value_type get() const { DASH_LOG_TRACE("T GlobRef.get()", "explicit get"); - DASH_LOG_TRACE_VAR("GlobRef.T()", _gptr); + auto dart_pointer = this->dart_gptr(); nonconst_value_type t; - dash::internal::get_blocking(_gptr, &t, 1); + dash::internal::get_blocking(dart_pointer, &t, 1); return t; } void get(nonconst_value_type *tptr) const { DASH_LOG_TRACE("GlobRef.get(T*)", "explicit get into provided ptr"); - DASH_LOG_TRACE_VAR("GlobRef.T()", _gptr); - dash::internal::get_blocking(_gptr, tptr, 1); + auto dart_pointer = this->dart_gptr(); + DASH_LOG_TRACE_VAR("GlobRef.T()", dart_pointer); + dash::internal::get_blocking(dart_pointer, tptr, 1); } void get(nonconst_value_type& tref) const { DASH_LOG_TRACE("GlobRef.get(T&)", "explicit get into provided ref"); - DASH_LOG_TRACE_VAR("GlobRef.T()", _gptr); - dash::internal::get_blocking(_gptr, &tref, 1); + auto dart_pointer = this->dart_gptr(); + DASH_LOG_TRACE_VAR("GlobRef.T()", dart_pointer); + dash::internal::get_blocking(dart_pointer, &tref, 1); } void @@ -233,8 +139,9 @@ class GlobRef static_assert(std::is_same::value, "Cannot assign to GlobRef!"); DASH_LOG_TRACE("GlobRef.put(T&)", "explicit put of provided ref"); - DASH_LOG_TRACE_VAR("GlobRef.T()", _gptr); - dash::internal::put_blocking(_gptr, &tref, 1); + auto dart_pointer = this->dart_gptr(); + DASH_LOG_TRACE_VAR("GlobRef.T()", dart_pointer); + dash::internal::put_blocking(dart_pointer, &tref, 1); } void @@ -242,11 +149,12 @@ class GlobRef static_assert(std::is_same::value, "Cannot modify value referenced by GlobRef!"); DASH_LOG_TRACE("GlobRef.put(T*)", "explicit put of provided ptr"); - DASH_LOG_TRACE_VAR("GlobRef.T()", _gptr); - dash::internal::put_blocking(_gptr, tptr, 1); + auto dart_pointer = this->dart_gptr(); + DASH_LOG_TRACE_VAR("GlobRef.T()", dart_pointer); + dash::internal::put_blocking(dart_pointer, tptr, 1); } - const self_t & + const GlobRef & operator+=(const nonconst_value_type& ref) const { static_assert(std::is_same::value, "Cannot modify value referenced by GlobRef!"); @@ -255,13 +163,13 @@ class GlobRef T add_val = ref; T old_val; dart_ret_t result = dart_fetch_and_op( - _gptr, + dart_pointer, reinterpret_cast(&add_val), reinterpret_cast(&old_val), dash::dart_datatype::value, dash::plus().dart_operation(), dash::Team::All().dart_id()); - dart_flush(_gptr); + dart_flush(dart_pointer); #else nonconst_value_type val = operator nonconst_value_type(); val += ref; @@ -270,7 +178,7 @@ class GlobRef return *this; } - const self_t & + const GlobRef & operator-=(const nonconst_value_type& ref) const { static_assert(std::is_same::value, "Cannot modify value referenced by GlobRef!"); @@ -280,7 +188,7 @@ class GlobRef return *this; } - const self_t & + const GlobRef & operator++() const { static_assert(std::is_same::value, "Cannot modify value referenced by GlobRef!"); @@ -299,7 +207,7 @@ class GlobRef return res; } - const self_t & + const GlobRef & operator--() const { static_assert(std::is_same::value, "Cannot modify value referenced by GlobRef!"); @@ -318,7 +226,7 @@ class GlobRef return res; } - const self_t & + const GlobRef & operator*=(const_value_type& ref) const { static_assert(std::is_same::value, "Cannot modify value referenced by GlobRef!"); @@ -328,7 +236,7 @@ class GlobRef return *this; } - const self_t & + const GlobRef & operator/=(const_value_type& ref) const { static_assert(std::is_same::value, "Cannot modify value referenced by GlobRef!"); @@ -338,7 +246,7 @@ class GlobRef return *this; } - const self_t & + const GlobRef & operator^=(const_value_type& ref) const { static_assert(std::is_same::value, "Cannot modify value referenced by GlobRef!"); @@ -348,18 +256,15 @@ class GlobRef return *this; } - constexpr dart_gptr_t dart_gptr() const noexcept { - return _gptr; - } - /** * Checks whether the globally referenced element is in * the calling unit's local memory. */ bool is_local() const { dart_team_unit_t luid; - dart_team_myid(_gptr.teamid, &luid); - return _gptr.unitid == luid.id; + auto dart_pointer = this->dart_gptr(); + dart_team_myid(dart_pointer.teamid, &luid); + return dart_pointer.unitid == luid.id; } /** @@ -374,7 +279,7 @@ class GlobRef typename std::add_const::type, MEMTYPE>::type>; - dart_gptr_t dartptr = _gptr; + dart_gptr_t dartptr = this->dart_gptr(); DASH_ASSERT_RETURNS(dart_gptr_incaddr(&dartptr, offs), DART_OK); return ref_t{dartptr}; @@ -400,8 +305,29 @@ class GlobRef b = tmp; } -private: - dart_gptr_t _gptr{}; + template + bool operator==(const GlobRef & other) const { + ValueT val = other.get(); + return operator==(val); + } + + template + bool operator!=(const GlobRef & other) const { + return !(*this == other); + } + + template + constexpr bool operator==(const ValueT& value) const + { + return static_cast(*this) == value; + } + + template + constexpr bool operator!=(const ValueT& value) const + { + return !(*this == value); + } + }; template @@ -410,13 +336,14 @@ std::ostream & operator<<( const GlobRef & gref) { char buf[100]; // + auto dart_pointer = gref.dart_gptr(); sprintf(buf, "(%06X|%02X|%04X|%04X|%016lX)", - gref._gptr.unitid, - gref._gptr.flags, - gref._gptr.segid, - gref._gptr.teamid, - gref._gptr.addr_or_offs.offset); + dart_pointer.unitid, + dart_pointer.flags, + dart_pointer.segid, + dart_pointer.teamid, + dart_pointer.addr_or_offs.offset); os << dash::typestr(gref) << buf; return os; } diff --git a/dash/include/dash/Shared.h b/dash/include/dash/Shared.h index 7b4b12541..c5eb78149 100644 --- a/dash/include/dash/Shared.h +++ b/dash/include/dash/Shared.h @@ -241,7 +241,7 @@ class Shared { DASH_LOG_DEBUG_VAR("Shared.cget", m_owner); DASH_LOG_DEBUG_VAR("Shared.get", m_glob_pointer); DASH_ASSERT(static_cast(m_glob_pointer)); - return reference(m_glob_pointer.dart_gptr()); + return reference(m_glob_pointer); } /** @@ -253,7 +253,7 @@ class Shared { DASH_LOG_DEBUG_VAR("Shared.get", m_owner); DASH_LOG_DEBUG_VAR("Shared.get", m_glob_pointer); DASH_ASSERT(m_glob_pointer); - return const_reference(m_glob_pointer.dart_gptr()); + return const_reference(m_glob_pointer); } /** diff --git a/dash/include/dash/iterator/GlobIter.h b/dash/include/dash/iterator/GlobIter.h index ef7b48c52..83cb3679d 100644 --- a/dash/include/dash/iterator/GlobIter.h +++ b/dash/include/dash/iterator/GlobIter.h @@ -370,6 +370,7 @@ class GlobIter : public std::iterator< "(index:", g_index, ") ->", "(unit:", local_pos.unit, " index:", local_pos.index, ")"); auto const dart_ptr = _get_pointer_at(local_pos); + return reference(dart_ptr); } @@ -675,8 +676,7 @@ class GlobIter : public std::iterator< private: - dart_gptr_t _get_pointer_at(typename pattern_type::local_index_t pos) const { - + auto _get_pointer_at(typename pattern_type::local_index_t pos) const { auto dart_pointer = static_cast(_globmem->begin()); DASH_ASSERT(pos.index >= 0); diff --git a/dash/include/dash/iterator/internal/GlobRefBase.h b/dash/include/dash/iterator/internal/GlobRefBase.h index c7dfe8c37..2124650fe 100644 --- a/dash/include/dash/iterator/internal/GlobRefBase.h +++ b/dash/include/dash/iterator/internal/GlobRefBase.h @@ -5,7 +5,14 @@ #include #include +#include + namespace dash { + +/// Forward declarations +template +class GlobPtr; + namespace detail { template @@ -95,6 +102,84 @@ inline std::size_t constexpr offset_of(T1 T2::*member) noexcept std::size_t{std::uintptr_t(std::addressof(dummy))}; } +template +class GlobRefBase { + public: + using value_type = T; + using const_value_type = typename std::add_const::type; + using nonconst_value_type = typename std::remove_const::type; + + protected: + /** + * PRIVATE: Constructor, creates an GlobRefBase object referencing an + * element in global memory. + */ + explicit constexpr GlobRefBase(dart_gptr_t dart_gptr) + : m_dart_pointer(dart_gptr) + { + } + + public: + constexpr GlobRefBase() = delete; + + GlobRefBase(GlobRefBase const&) = default; + GlobRefBase(GlobRefBase&&) noexcept = default; + + /** + * Constructor: creates an GlobRefBase object referencing an element in + * global memory. + */ + template + explicit constexpr GlobRefBase( + /// Pointer to referenced object in global memory + const GlobPtr& gptr) + : GlobRefBase(gptr.dart_gptr()) + { + } + + // clang-format off + /** + * Copy constructor, implicit if at least one of the following conditions is + * satisfied: + * 1) value_type and _From are exactly the same types (including const and + * volatile qualifiers + * 2) value_type and _From are the same types after removing const and + * volatile qualifiers and value_type itself is const. + */ + // clang-format on + template < + typename _From, + long = detail::enable_implicit_copy_ctor<_From, value_type>::value> + constexpr GlobRefBase(const GlobRefBase<_From>& gref) noexcept + : GlobRefBase(gref.dart_gptr()) + { + } + + // clang-format off + /** + * Copy constructor, explicit if the following conditions are satisfied. + * 1) value_type and _From are the same types after excluding const and + * volatile qualifiers + * 2) value_type is const and _From is non-const + */ + // clang-format on + template < + typename _From, + int = detail::enable_explicit_copy_ctor<_From, value_type>::value> + explicit constexpr GlobRefBase(const GlobRefBase<_From>& gref) noexcept + : GlobRefBase(gref.dart_gptr()) + { + } + + constexpr dart_gptr_t dart_gptr() const noexcept + { + return this->m_dart_pointer; + } + + private: + dart_gptr_t m_dart_pointer{DART_GPTR_NULL}; +}; + } // namespace detail } // namespace dash #endif diff --git a/dash/test/types/GlobRefTest.cc b/dash/test/types/GlobRefTest.cc index 9ab9eb50f..fec540520 100644 --- a/dash/test/types/GlobRefTest.cc +++ b/dash/test/types/GlobRefTest.cc @@ -14,6 +14,7 @@ TEST_F(GlobRefTest, ArithmeticOps) array_t arr(dash::size()); int neighbor = (dash::myid() + 1) % dash::size(); + dash::GlobRef gref = arr[neighbor]; auto address_of_ref = dash::addressof(gref); From bdb922710a559fc3feee490ab7809f1dbfe1114e Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Fri, 8 Mar 2019 21:56:11 +0100 Subject: [PATCH 11/15] better code, progress regarding const correctness --- dash/include/dash/GlobPtr.h | 62 +++++++++------ dash/include/dash/GlobRef.h | 27 +++---- dash/include/dash/TypeTraits.h | 20 +++++ dash/include/dash/algorithm/SUMMA.h | 2 - dash/include/dash/iterator/GlobIter.h | 4 +- dash/include/dash/iterator/GlobViewIter.h | 4 +- .../dash/iterator/internal/GlobRefBase.h | 75 ++++++++++++++++++- dash/test/iterator/GlobAsyncRefTest.cc | 7 +- dash/test/types/GlobRefTest.cc | 21 +++--- 9 files changed, 157 insertions(+), 65 deletions(-) create mode 100644 dash/include/dash/TypeTraits.h diff --git a/dash/include/dash/GlobPtr.h b/dash/include/dash/GlobPtr.h index a78da4cd6..29ba89729 100644 --- a/dash/include/dash/GlobPtr.h +++ b/dash/include/dash/GlobPtr.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -25,7 +26,7 @@ bool operator!=(const dart_gptr_t &lhs, const dart_gptr_t &rhs); namespace dash { - // Forward-declarations +// Forward-declarations template class GlobRef; @@ -45,7 +46,7 @@ dash::gptrdiff_t distance( */ template class GlobPtr { -private: + private: typedef GlobPtr self_t; using local_pointer_traits = @@ -53,19 +54,22 @@ class GlobPtr { using memory_traits = dash::memory_space_traits; -public: - typedef ElementType value_type; - typedef GlobPtr const_type; - typedef typename GlobMemT::index_type index_type; - typedef typename GlobMemT::size_type size_type; - typedef index_type gptrdiff_t; + public: + typedef ElementType value_type; + typedef typename GlobMemT::index_type index_type; + typedef typename GlobMemT::size_type size_type; + typedef index_type gptrdiff_t; typedef typename local_pointer_traits::template rebind local_type; - typedef typename local_pointer_traits::template rebind + typedef typename local_pointer_traits::template rebind< + typename std::add_const::type> const_local_type; + typedef GlobPtr::type, GlobMemT> + const_type; + typedef GlobMemT memory_type; /** @@ -74,7 +78,7 @@ class GlobPtr { template using rebind = dash::GlobPtr; -public: + public: template friend class GlobPtr; @@ -86,10 +90,11 @@ class GlobPtr { friend dash::gptrdiff_t distance( GlobPtr gbegin, GlobPtr gend); -private: + private: // Raw global pointer used to initialize this pointer instance dart_gptr_t m_dart_pointer = DART_GPTR_NULL; -public: + + public: /** * Default constructor, underlying global address is unspecified. */ @@ -357,9 +362,13 @@ class GlobPtr { /** * Subscript operator. */ - constexpr GlobRef operator[](gptrdiff_t n) const + constexpr auto operator[](gptrdiff_t n) const noexcept { - return GlobRef(self_t((*this) + n)); + auto const_ptr = const_type{*this}; + const_ptr += n; + + return GlobRef::type>( + std::move(const_ptr)); } /** @@ -367,7 +376,9 @@ class GlobPtr { */ GlobRef operator[](gptrdiff_t n) { - return GlobRef(self_t((*this) + n)); + auto ptr = *this; + ptr += n; + return GlobRef(std::move(ptr)); } /** @@ -383,7 +394,9 @@ class GlobPtr { */ constexpr GlobRef operator*() const { - return GlobRef(*this); + auto const_ptr = const_type{*this}; + return GlobRef::type>( + std::move(const_ptr)); } /** @@ -409,7 +422,8 @@ class GlobPtr { * GlobPtr instance, or \c nullptr if the referenced element * is not local to the calling unit. */ - const value_type * local() const { + const value_type *local() const + { void *addr = nullptr; if (dart_gptr_getaddr(m_dart_pointer, &addr) == DART_OK) { return static_cast(addr); @@ -439,7 +453,7 @@ class GlobPtr { return !DART_GPTR_ISNULL(m_dart_pointer); } -private: + private: void increment(size_type offs) { if (offs == 0) { @@ -453,8 +467,9 @@ class GlobPtr { "cannot increment a global null pointer"); } - auto& reg = dash::internal::MemorySpaceRegistry::GetInstance(); - auto const * mem_space = static_cast(reg.lookup(m_dart_pointer)); + auto & reg = dash::internal::MemorySpaceRegistry::GetInstance(); + auto const *mem_space = + static_cast(reg.lookup(m_dart_pointer)); // get a new dart with the requested offset auto const newPtr = dash::internal::increment( m_dart_pointer, @@ -540,14 +555,13 @@ dash::gptrdiff_t distance( using memory_space_traits = dash::memory_space_traits; auto const begin = static_cast(gbegin); - auto const end = static_cast(gbegin); + auto const end = static_cast(gbegin); DASH_ASSERT_EQ(begin.teamid, end.teamid, "teamid must be equal"); DASH_ASSERT_EQ(begin.segid, end.segid, "segid must be equal"); - auto & reg = dash::internal::MemorySpaceRegistry::GetInstance(); - auto const *mem_space = - static_cast(reg.lookup(begin)); + auto & reg = dash::internal::MemorySpaceRegistry::GetInstance(); + auto const *mem_space = static_cast(reg.lookup(begin)); return dash::internal::distance( static_cast(gbegin), diff --git a/dash/include/dash/GlobRef.h b/dash/include/dash/GlobRef.h index e9e901f6d..2c93c9a63 100644 --- a/dash/include/dash/GlobRef.h +++ b/dash/include/dash/GlobRef.h @@ -23,9 +23,6 @@ class GlobRef : public detail::GlobRefBase friend class GlobRef; //required for .member() - template - friend class GlobViewIter; - template friend std::ostream & operator<<( std::ostream & os, @@ -33,13 +30,20 @@ class GlobRef : public detail::GlobRefBase public: //inherit all constructors from parent class - using base_t::GlobRefBase; + using detail::GlobRefBase::GlobRefBase; /** * COPY Construction */ GlobRef(const GlobRef & other) = default; + /** + * MOVE Construction + */ + GlobRef(GlobRef && other) = default; + +#if 0 + //TODO remove /** * Constructor to convert \c GlobAsyncRef to GlobRef. Set to explicit to * avoid unintendet conversion @@ -59,6 +63,7 @@ class GlobRef : public detail::GlobRefBase : base_t(gref.dart_gptr()) { } +#endif /** * Copy Assignment: We copy the value behind this address, NOT the reference @@ -158,23 +163,9 @@ class GlobRef : public detail::GlobRefBase operator+=(const nonconst_value_type& ref) const { static_assert(std::is_same::value, "Cannot modify value referenced by GlobRef!"); -#if 0 - // TODO: Alternative implementation, possibly more efficient: - T add_val = ref; - T old_val; - dart_ret_t result = dart_fetch_and_op( - dart_pointer, - reinterpret_cast(&add_val), - reinterpret_cast(&old_val), - dash::dart_datatype::value, - dash::plus().dart_operation(), - dash::Team::All().dart_id()); - dart_flush(dart_pointer); - #else nonconst_value_type val = operator nonconst_value_type(); val += ref; operator=(val); - #endif return *this; } diff --git a/dash/include/dash/TypeTraits.h b/dash/include/dash/TypeTraits.h new file mode 100644 index 000000000..f0ea348a3 --- /dev/null +++ b/dash/include/dash/TypeTraits.h @@ -0,0 +1,20 @@ +#ifndef DASH__TYPE_TRAITS_H_ +#define DASH__TYPE_TRAITS_H_ + +#include + +/// Forward decls + +namespace dash { +template +class Atomic; +} + +namespace std { +template +struct add_const> { + using type = dash::Atomic::type>; +}; +} // namespace std + +#endif diff --git a/dash/include/dash/algorithm/SUMMA.h b/dash/include/dash/algorithm/SUMMA.h index 5681ca525..ff83e8eb7 100644 --- a/dash/include/dash/algorithm/SUMMA.h +++ b/dash/include/dash/algorithm/SUMMA.h @@ -429,8 +429,6 @@ void summa( // Block coordinates for next block multiplication result: l_block_c_get = l_block_c_comp; l_block_c_get_view = l_block_c_comp_view; - l_block_c_get_row = l_block_c_get_row; - l_block_c_get_col = l_block_c_get_col; DASH_LOG_TRACE("dash::summa", "summa.block.comp", "C.local.block", "l_block_idx:", lb, "row:", l_block_c_comp_row, diff --git a/dash/include/dash/iterator/GlobIter.h b/dash/include/dash/iterator/GlobIter.h index 83cb3679d..4360637aa 100644 --- a/dash/include/dash/iterator/GlobIter.h +++ b/dash/include/dash/iterator/GlobIter.h @@ -371,7 +371,7 @@ class GlobIter : public std::iterator< "(unit:", local_pos.unit, " index:", local_pos.index, ")"); auto const dart_ptr = _get_pointer_at(local_pos); - return reference(dart_ptr); + return reference{pointer{dart_ptr}}; } /** @@ -391,7 +391,7 @@ class GlobIter : public std::iterator< "(index:", g_index, ") ->", "(unit:", local_pos.unit, " index:", local_pos.index, ")"); auto const dart_ptr = _get_pointer_at(local_pos); - return const_reference(dart_ptr); + return const_reference{const_pointer{dart_ptr}}; } /** diff --git a/dash/include/dash/iterator/GlobViewIter.h b/dash/include/dash/iterator/GlobViewIter.h index a91900ee5..70f47d09e 100644 --- a/dash/include/dash/iterator/GlobViewIter.h +++ b/dash/include/dash/iterator/GlobViewIter.h @@ -497,7 +497,7 @@ class GlobViewIter // Global reference to element at given position: auto const dart_pointer = _get_pointer_at(local_pos); - return reference(dart_pointer); + return reference{pointer{dart_pointer}}; } /** @@ -526,7 +526,7 @@ class GlobViewIter // Global reference to element at given position: auto const dart_pointer = _get_pointer_at(local_pos); - return const_reference(dart_pointer); + return const_reference{const_pointer{dart_pointer}}; } /** diff --git a/dash/include/dash/iterator/internal/GlobRefBase.h b/dash/include/dash/iterator/internal/GlobRefBase.h index 2124650fe..25503414c 100644 --- a/dash/include/dash/iterator/internal/GlobRefBase.h +++ b/dash/include/dash/iterator/internal/GlobRefBase.h @@ -5,6 +5,7 @@ #include #include +#include #include namespace dash { @@ -114,10 +115,14 @@ class GlobRefBase { * PRIVATE: Constructor, creates an GlobRefBase object referencing an * element in global memory. */ - explicit constexpr GlobRefBase(dart_gptr_t dart_gptr) + explicit constexpr GlobRefBase(dart_gptr_t const& dart_gptr) : m_dart_pointer(dart_gptr) { } + explicit constexpr GlobRefBase(dart_gptr_t&& dart_gptr) + : m_dart_pointer(std::move(dart_gptr)) + { + } public: constexpr GlobRefBase() = delete; @@ -129,14 +134,26 @@ class GlobRefBase { * Constructor: creates an GlobRefBase object referencing an element in * global memory. */ - template + template explicit constexpr GlobRefBase( /// Pointer to referenced object in global memory - const GlobPtr& gptr) + const GlobPtr& gptr) : GlobRefBase(gptr.dart_gptr()) { } + /** + * Constructor: creates an GlobRefBase object referencing an element in + * global memory. + */ + template + explicit constexpr GlobRefBase( + /// Pointer to referenced object in global memory + GlobPtr&& gptr) + : GlobRefBase(std::move(gptr.dart_gptr())) + { + } + // clang-format off /** * Copy constructor, implicit if at least one of the following conditions is @@ -155,6 +172,24 @@ class GlobRefBase { { } + // clang-format off + /** + * Copy constructor, implicit if at least one of the following conditions is + * satisfied: + * 1) value_type and _From are exactly the same types (including const and + * volatile qualifiers + * 2) value_type and _From are the same types after removing const and + * volatile qualifiers and value_type itself is const. + */ + // clang-format on + template < + typename _From, + long = detail::enable_implicit_copy_ctor<_From, value_type>::value> + constexpr GlobRefBase(GlobRefBase<_From>&& gref) noexcept + : GlobRefBase(std::move(gref.dart_gptr())) + { + } + // clang-format off /** * Copy constructor, explicit if the following conditions are satisfied. @@ -171,11 +206,43 @@ class GlobRefBase { { } - constexpr dart_gptr_t dart_gptr() const noexcept + // clang-format off + /** + * Copy constructor, explicit if the following conditions are satisfied. + * 1) value_type and _From are the same types after excluding const and + * volatile qualifiers + * 2) value_type is const and _From is non-const + */ + // clang-format on + template < + typename _From, + int = detail::enable_explicit_copy_ctor<_From, value_type>::value> + explicit constexpr GlobRefBase(GlobRefBase<_From>&& gref) noexcept + : GlobRefBase(std::move(gref.dart_gptr())) + { + } + + constexpr dart_gptr_t const& dart_gptr() const & noexcept { return this->m_dart_pointer; } + constexpr dart_gptr_t const&& dart_gptr() const && noexcept + { + return std::move(this->m_dart_pointer); + } + + constexpr dart_gptr_t& dart_gptr() & noexcept + { + return this->m_dart_pointer; + } + + constexpr dart_gptr_t&& dart_gptr() && noexcept + { + return std::move(this->m_dart_pointer); + } + + private: dart_gptr_t m_dart_pointer{DART_GPTR_NULL}; }; diff --git a/dash/test/iterator/GlobAsyncRefTest.cc b/dash/test/iterator/GlobAsyncRefTest.cc index e433abb17..bd30e8e5c 100644 --- a/dash/test/iterator/GlobAsyncRefTest.cc +++ b/dash/test/iterator/GlobAsyncRefTest.cc @@ -86,6 +86,8 @@ TEST_F(GlobAsyncRefTest, GetSet) { ASSERT_EQ_U(left_neighbor, array.local[0]); } +#if 0 +//TODO remove refactor TEST_F(GlobAsyncRefTest, Conversion) { // Initialize values: @@ -97,11 +99,12 @@ TEST_F(GlobAsyncRefTest, Conversion) auto gref_async = static_cast>( array[dash::myid().id]); - auto gref_sync = static_cast>( - array.async[dash::myid().id]); + auto gref_sync = + array[dash::myid().id]; ASSERT_EQ_U(gref_async.is_local(), true); ASSERT_EQ_U(gref_sync.is_local(), true); } +#endif struct mytype {int a; double b; }; diff --git a/dash/test/types/GlobRefTest.cc b/dash/test/types/GlobRefTest.cc index fec540520..f5481fb83 100644 --- a/dash/test/types/GlobRefTest.cc +++ b/dash/test/types/GlobRefTest.cc @@ -13,9 +13,9 @@ TEST_F(GlobRefTest, ArithmeticOps) array_t arr(dash::size()); - int neighbor = (dash::myid() + 1) % dash::size(); + int neighbor = (dash::myid() + 1) % dash::size(); - dash::GlobRef gref = arr[neighbor]; + dash::GlobRef gref = arr[neighbor]; auto address_of_ref = dash::addressof(gref); @@ -210,28 +210,27 @@ TEST_F(GlobRefTest, ConversionRules) { constexpr bool ignore = true; - // Rule 1: T &-> const T & + // Rule 1.1: T &-> const T & StandardConformabilityTester::test(); - // Rule 2: const T & -> int & + // Rule 1.2: const T & -> int & // Conversion Fails due to const correctness StandardConformabilityTester::test(); - // Rule 3: T & -> U & if T and U are not related (FAILS) + // Rule 2: T & -> U & if T and U are not related (FAILS) StandardConformabilityTester::test(); - // Rule 4: Child & -> Parent & (Upcast) + // Rule 3: Child & -> Parent & (Upcast) StandardConformabilityTester::test(); - // Rule 5.1: Child & -> const Parent & (Upcast to const) - // Rule 5.2: const Child & -> Parent & (FAILS, const correctness) + // Rule 4.1: Child & -> const Parent & (Upcast to const) + // Rule 4.2: const Child & -> Parent & (FAILS, const correctness) StandardConformabilityTester::test(); StandardConformabilityTester::test(); - // Rule 6.1: Parent & -> const Child & - // Rule 6.2: Parent & -> Child & + // Rule 5.1: Parent & -> const Child & + // Rule 5.2: Parent & -> Child & // Explicit downcast (VALID) // see https://en.cppreference.com/w/cpp/language/static_cast StandardConformabilityTester::test(); StandardConformabilityTester::test(); - } From 9d1358f359b8f508ac6c976aae8fedd0cff76e9e Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Sat, 9 Mar 2019 10:20:43 +0100 Subject: [PATCH 12/15] remove dead code --- dash/include/dash/GlobRef.h | 23 ----------------------- dash/test/iterator/GlobAsyncRefTest.cc | 20 -------------------- 2 files changed, 43 deletions(-) diff --git a/dash/include/dash/GlobRef.h b/dash/include/dash/GlobRef.h index 2c93c9a63..cbf74a5ef 100644 --- a/dash/include/dash/GlobRef.h +++ b/dash/include/dash/GlobRef.h @@ -42,29 +42,6 @@ class GlobRef : public detail::GlobRefBase */ GlobRef(GlobRef && other) = default; -#if 0 - //TODO remove - /** - * Constructor to convert \c GlobAsyncRef to GlobRef. Set to explicit to - * avoid unintendet conversion - */ - template < - typename _From, - long = detail::enable_implicit_copy_ctor<_From, typename base_t::value_type>::value> - constexpr GlobRef(const GlobAsyncRef<_From>& gref) - : base_t(gref.dart_gptr()) - { - } - - template < - typename _From, - int = detail::enable_explicit_copy_ctor<_From, typename base_t::value_type>::value> - explicit constexpr GlobRef(const GlobAsyncRef<_From>& gref) - : base_t(gref.dart_gptr()) - { - } -#endif - /** * Copy Assignment: We copy the value behind this address, NOT the reference */ diff --git a/dash/test/iterator/GlobAsyncRefTest.cc b/dash/test/iterator/GlobAsyncRefTest.cc index bd30e8e5c..5066358e7 100644 --- a/dash/test/iterator/GlobAsyncRefTest.cc +++ b/dash/test/iterator/GlobAsyncRefTest.cc @@ -86,26 +86,6 @@ TEST_F(GlobAsyncRefTest, GetSet) { ASSERT_EQ_U(left_neighbor, array.local[0]); } -#if 0 -//TODO remove refactor -TEST_F(GlobAsyncRefTest, Conversion) -{ - // Initialize values: - dash::Array array(dash::size()); - for (auto li = 0; li < array.lcapacity(); ++li) { - array.local[li] = dash::myid().id; - } - array.barrier(); - - auto gref_async = static_cast>( - array[dash::myid().id]); - auto gref_sync = - array[dash::myid().id]; - ASSERT_EQ_U(gref_async.is_local(), true); - ASSERT_EQ_U(gref_sync.is_local(), true); -} -#endif - struct mytype {int a; double b; }; std::ostream& From 83921059eb95ad38c73da6e3294870c269014c5d Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Sat, 9 Mar 2019 12:01:36 +0100 Subject: [PATCH 13/15] minor changes in conversion rules of GlobPtr --- dash/include/dash/GlobPtr.h | 15 +++++++-------- dash/include/dash/TypeTraits.h | 6 +++++- dash/include/dash/algorithm/Fill.h | 3 ++- dash/include/dash/io/hdf5/StorageDriver.h | 2 -- dash/include/dash/iterator/internal/GlobRefBase.h | 5 ++--- dash/include/dash/memory/GlobStaticMem.h | 1 - 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/dash/include/dash/GlobPtr.h b/dash/include/dash/GlobPtr.h index 29ba89729..8a152fa02 100644 --- a/dash/include/dash/GlobPtr.h +++ b/dash/include/dash/GlobPtr.h @@ -140,14 +140,13 @@ class GlobPtr { //clang-format on template < typename From, - typename = typename std::enable_if< - // We always allow GlobPtr -> GlobPtr or the other way) - // or if From is assignable to To (value_type) - dash::internal::is_pointer_assignable< - typename dash::remove_atomic::type, - typename dash::remove_atomic::type>::value> - - ::type> + typename = typename std::enable_if::type>::type, + // To pointer + typename std::add_pointer< + typename dash::remove_atomic::type>::type>::value>> constexpr GlobPtr(const GlobPtr &other) : m_dart_pointer(other.m_dart_pointer) { diff --git a/dash/include/dash/TypeTraits.h b/dash/include/dash/TypeTraits.h index f0ea348a3..48675c43c 100644 --- a/dash/include/dash/TypeTraits.h +++ b/dash/include/dash/TypeTraits.h @@ -6,15 +6,19 @@ /// Forward decls namespace dash { + template class Atomic; -} + +} // namespace dash namespace std { + template struct add_const> { using type = dash::Atomic::type>; }; + } // namespace std #endif diff --git a/dash/include/dash/algorithm/Fill.h b/dash/include/dash/algorithm/Fill.h index edbaa26c6..6b5bf9624 100644 --- a/dash/include/dash/algorithm/Fill.h +++ b/dash/include/dash/algorithm/Fill.h @@ -40,7 +40,6 @@ void fill( /// Value which will be assigned to the elements in range [first, last) const typename GlobIterType::value_type & value) { - typedef typename GlobIterType::index_type index_t; typedef typename GlobIterType::value_type value_t; // Global iterators to local range: @@ -49,6 +48,8 @@ void fill( value_t * llast = index_range.end; #ifdef DASH_ENABLE_OPENMP + typedef typename GlobIterType::index_type index_t; + dash::util::UnitLocality uloc; auto n_threads = uloc.num_domain_threads(); auto nlocal = llast - lfirst; diff --git a/dash/include/dash/io/hdf5/StorageDriver.h b/dash/include/dash/io/hdf5/StorageDriver.h index 53053386f..f41af43df 100644 --- a/dash/include/dash/io/hdf5/StorageDriver.h +++ b/dash/include/dash/io/hdf5/StorageDriver.h @@ -133,9 +133,7 @@ class StoreHDF { typename dash::view_traits::origin_type::value_type>) { using Container_t = typename dash::view_traits::origin_type; using pattern_t = typename Container_t::pattern_type; - using extent_t = typename pattern_t::size_type; using index_t = typename Container_t::index_type; - using value_t = typename Container_t::value_type; constexpr auto ndim = pattern_t::ndim(); diff --git a/dash/include/dash/iterator/internal/GlobRefBase.h b/dash/include/dash/iterator/internal/GlobRefBase.h index 25503414c..65a708af6 100644 --- a/dash/include/dash/iterator/internal/GlobRefBase.h +++ b/dash/include/dash/iterator/internal/GlobRefBase.h @@ -222,12 +222,12 @@ class GlobRefBase { { } - constexpr dart_gptr_t const& dart_gptr() const & noexcept + constexpr dart_gptr_t const& dart_gptr() const& noexcept { return this->m_dart_pointer; } - constexpr dart_gptr_t const&& dart_gptr() const && noexcept + constexpr dart_gptr_t const&& dart_gptr() const&& noexcept { return std::move(this->m_dart_pointer); } @@ -242,7 +242,6 @@ class GlobRefBase { return std::move(this->m_dart_pointer); } - private: dart_gptr_t m_dart_pointer{DART_GPTR_NULL}; }; diff --git a/dash/include/dash/memory/GlobStaticMem.h b/dash/include/dash/memory/GlobStaticMem.h index 8de001fc7..8ceedc6a5 100644 --- a/dash/include/dash/memory/GlobStaticMem.h +++ b/dash/include/dash/memory/GlobStaticMem.h @@ -333,7 +333,6 @@ inline void GlobStaticMem::do_deallocate( if (*m_team != dash::Team::Null()) { DASH_ASSERT_RETURNS(dart_barrier(m_team->dart_id()), DART_OK); - auto soon_to_be_lbegin = gptr; gptr.set_unit(m_team->myid()); auto* lbegin = gptr.local(); From f126a69d07cebf88428da57808f5dd5c397f5fa3 Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Thu, 28 Mar 2019 12:53:22 +0100 Subject: [PATCH 14/15] remove dead code --- dash/include/dash/Types.h | 36 --------------------- dash/include/dash/atomic/Type_traits.h | 43 -------------------------- 2 files changed, 79 deletions(-) delete mode 100644 dash/include/dash/atomic/Type_traits.h diff --git a/dash/include/dash/Types.h b/dash/include/dash/Types.h index 86357e019..1aae2ebe7 100644 --- a/dash/include/dash/Types.h +++ b/dash/include/dash/Types.h @@ -73,20 +73,6 @@ typedef internal::default_unsigned_index default_size_t; */ typedef internal::default_signed_index gptrdiff_t; -template< - dash::dim_t NumDimensions, - typename IndexType = dash::default_index_t> -struct Point { - ::std::array coords; -}; - -template< - dash::dim_t NumDimensions, - typename SizeType = dash::default_extent_t> -struct Extent { - ::std::array sizes; -}; - #ifdef DOXYGEN /** @@ -260,28 +246,6 @@ struct is_arithmetic dash::dart_datatype::value != DART_TYPE_UNDEFINED > { }; -/** - * Type trait indicating whether a type has a comparision operator== - * defined. - * \code - * bool test = has_operator_equal::value; - * bool test = has_operator_equal::value; - * \endcode - */ -template -struct has_operator_equal_impl -{ - template - static auto test(U*) -> decltype(std::declval() == std::declval()); - template - static auto test(...) -> std::false_type; - - using type = typename std::is_same(0))>::type; -}; - -template -struct has_operator_equal : has_operator_equal_impl::type {}; - /** * Convencience wrapper to determine the DART type and number of elements * required for the given template parameter type \c T and the desired number of diff --git a/dash/include/dash/atomic/Type_traits.h b/dash/include/dash/atomic/Type_traits.h deleted file mode 100644 index fc0cc4500..000000000 --- a/dash/include/dash/atomic/Type_traits.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef DASH__ATOMIC__TYPE_TRAITS_INCLUDED -#define DASH__ATOMIC__TYPE_TRAITS_INCLUDED - -namespace dash { - -// forward decl atomic type for only importing traits without full blown atomic -// type support -template -class Atomic; - -/** - * type traits for \c dash::Atomic - * - * true if type is atomic - * false otherwise - */ -template -struct is_atomic { - static constexpr bool value = false; -}; -template -struct is_atomic> { - static constexpr bool value = true; -}; - -/** - * type traits for \c dash::Atomic - * - * returns the sub type of a \cdash::Atomic - */ -template -struct remove_atomic { - typedef T type; -}; -template -struct remove_atomic> { - typedef T type; -}; - -} // namespace dash - -#endif // DASH__ATOMIC__TYPE_TRAITS_INCLUDED - From 410f4a441e6609172e4a951954897186f950883e Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Thu, 28 Mar 2019 12:54:11 +0100 Subject: [PATCH 15/15] centralize all traits in a single header --- dash/include/dash/Atomic.h | 54 ++++++------ dash/include/dash/Coarray.h | 2 - dash/include/dash/GlobPtr.h | 1 - dash/include/dash/TypeTraits.h | 83 ++++++++++++++++++- dash/include/dash/Types.h | 21 ----- dash/include/dash/atomic/GlobAtomicRef.h | 5 +- .../dash/iterator/internal/GlobRefBase.h | 1 - 7 files changed, 110 insertions(+), 57 deletions(-) diff --git a/dash/include/dash/Atomic.h b/dash/include/dash/Atomic.h index bd600d901..2c238609c 100644 --- a/dash/include/dash/Atomic.h +++ b/dash/include/dash/Atomic.h @@ -2,10 +2,10 @@ #define DASH__ATOMIC_H__INCLUDED #include +#include -#include #include - +#include namespace dash { @@ -46,32 +46,33 @@ namespace dash { * \endcode */ template -class Atomic -{ +class Atomic { static_assert( - dash::is_atomic_compatible::value, - "Type not supported for atomic operations"); + dash::is_atomic_compatible::value, + "Type not supported for atomic operations"); -private: - T _value; + private: + T _value; typedef Atomic self_t; -public: + public: typedef T value_type; constexpr Atomic() = default; constexpr Atomic(const Atomic& other) = default; constexpr Atomic(Atomic&& other) = default; - self_t& operator=(const self_t& other) = default; - self_t& operator=(self_t&& other) = default; + self_t& operator=(const self_t& other) = default; + self_t& operator=(self_t&& other) = default; /** * Initializes the underlying value with desired. * The initialization is not atomic */ constexpr Atomic(T value) - : _value(value) { } + : _value(value) + { + } /** * Disabled assignment as this violates the atomic semantics @@ -87,38 +88,35 @@ class Atomic * As \c Atomic is implemented as phantom type, * the value has to be queried using the \c dash::GlobRef */ - operator T() = delete; + operator T() = delete; - constexpr bool operator==(const self_t & other) const { + constexpr bool operator==(const self_t& other) const + { return _value == other._value; } - constexpr bool operator!=(const self_t & other) const { + constexpr bool operator!=(const self_t& other) const + { return !(*this == other); } - template - friend std::ostream & operator<<( - std::ostream & os, - const Atomic & at); + template + friend std::ostream& operator<<(std::ostream& os, const Atomic& at); -}; // class Atomic +}; // class Atomic -template -std::ostream & operator<<( - std::ostream & os, - const Atomic & at) +template +std::ostream& operator<<(std::ostream& os, const Atomic& at) { std::ostringstream ss; ss << dash::typestr(at) << ""; return operator<<(os, ss.str()); } -} // namespace dash +} // namespace dash -#include -#include #include +#include #include -#endif // DASH__ATOMIC_H__INCLUDED +#endif // DASH__ATOMIC_H__INCLUDED diff --git a/dash/include/dash/Coarray.h b/dash/include/dash/Coarray.h index 6dd3cbb0a..7392ffc3b 100644 --- a/dash/include/dash/Coarray.h +++ b/dash/include/dash/Coarray.h @@ -17,8 +17,6 @@ #include -#include - /** * \defgroup DashCoarrayConcept Coarray Concept * diff --git a/dash/include/dash/GlobPtr.h b/dash/include/dash/GlobPtr.h index 8f2d6bb2d..1b76c1929 100644 --- a/dash/include/dash/GlobPtr.h +++ b/dash/include/dash/GlobPtr.h @@ -11,7 +11,6 @@ #include #include -#include #include #include diff --git a/dash/include/dash/TypeTraits.h b/dash/include/dash/TypeTraits.h index 48675c43c..7b412986a 100644 --- a/dash/include/dash/TypeTraits.h +++ b/dash/include/dash/TypeTraits.h @@ -3,8 +3,30 @@ #include -/// Forward decls +/////////////////////////////////////////////////////////////////////////////// +// Container Traits +/////////////////////////////////////////////////////////////////////////////// + +namespace dash { +/** + * Type trait indicating whether the specified type is eligible for + * elements of DASH containers. + */ +template +struct is_container_compatible + : public std::integral_constant< + bool, + std::is_default_constructible::value && + std::is_trivially_copyable::value> { +}; + +} // namespace dash +/////////////////////////////////////////////////////////////////////////////// +// Atomic Traits +/////////////////////////////////////////////////////////////////////////////// + +/// Forward decls namespace dash { template @@ -13,7 +35,11 @@ class Atomic; } // namespace dash namespace std { - +/** + * type traits for \c dash::Atomic + * + * returns an atomic with a const subtype + */ template struct add_const> { using type = dash::Atomic::type>; @@ -21,4 +47,57 @@ struct add_const> { } // namespace std +namespace dash { + +namespace detail { +template +struct remove_atomic_impl { + using type = T; +}; + +template +struct remove_atomic_impl> { + using type = T; +}; + +template +struct is_atomic_impl : std::false_type { +}; +template +struct is_atomic_impl> : std::true_type { +}; + +} // namespace detail + +/** + * type traits for \c dash::Atomic + * + * returns the sub type of a \cdash::Atomic + */ +template +struct remove_atomic { + using type = typename detail::remove_atomic_impl::type; +}; + +/** + * type traits for \c dash::Atomic + * + * true if type is atomic + * false otherwise + */ +template +struct is_atomic : detail::is_atomic_impl { +}; + +/** + * Type trait indicating whether a type can be used for global atomic + * operations. + */ +template +struct is_atomic_compatible + : public std::integral_constant::value> { +}; + +} // namespace dash + #endif diff --git a/dash/include/dash/Types.h b/dash/include/dash/Types.h index 1aae2ebe7..c5494c446 100644 --- a/dash/include/dash/Types.h +++ b/dash/include/dash/Types.h @@ -214,27 +214,6 @@ struct dart_punned_datatype { #endif // DOXYGEN -/** - * Type trait indicating whether the specified type is eligible for - * elements of DASH containers. - */ -template -struct is_container_compatible : - public std::integral_constant::value - && std::is_trivially_copyable::value - > -{ }; - -/** - * Type trait indicating whether a type can be used for global atomic - * operations. - */ -template -struct is_atomic_compatible -: public std::integral_constant::value> -{ }; - /** * Type trait indicating whether a type can be used for arithmetic * operations in global memory space. diff --git a/dash/include/dash/atomic/GlobAtomicRef.h b/dash/include/dash/atomic/GlobAtomicRef.h index 2decb611d..4c81b5d0f 100644 --- a/dash/include/dash/atomic/GlobAtomicRef.h +++ b/dash/include/dash/atomic/GlobAtomicRef.h @@ -1,8 +1,6 @@ #ifndef DASH__ATOMIC_GLOBREF_H_ #define DASH__ATOMIC_GLOBREF_H_ -#include -//#include #include #include @@ -16,6 +14,9 @@ class Atomic; template class GlobAsyncRef; +template +class GlobRef; + /** * Specialization for atomic values. All atomic operations are * \c const as the \c GlobRef does not own the atomic values. diff --git a/dash/include/dash/iterator/internal/GlobRefBase.h b/dash/include/dash/iterator/internal/GlobRefBase.h index 9e0c13609..68d3c9eb7 100644 --- a/dash/include/dash/iterator/internal/GlobRefBase.h +++ b/dash/include/dash/iterator/internal/GlobRefBase.h @@ -6,7 +6,6 @@ #include #include -#include #include namespace dash {