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/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/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/GlobPtr.h b/dash/include/dash/GlobPtr.h index b82000f10..1b76c1929 100644 --- a/dash/include/dash/GlobPtr.h +++ b/dash/include/dash/GlobPtr.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include @@ -25,7 +25,7 @@ bool operator!=(const dart_gptr_t &lhs, const dart_gptr_t &rhs); namespace dash { - // Forward-declarations +// Forward-declarations template class GlobRef; @@ -45,7 +45,7 @@ dash::gptrdiff_t distance( */ template class GlobPtr { -private: + private: typedef GlobPtr self_t; using local_pointer_traits = @@ -53,19 +53,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 +77,7 @@ class GlobPtr { template using rebind = dash::GlobPtr; -public: + public: template friend class GlobPtr; @@ -86,10 +89,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. */ @@ -135,15 +139,14 @@ 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> - constexpr GlobPtr(const GlobPtr &other) DASH_NOEXCEPT + 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) { } @@ -357,9 +360,13 @@ class GlobPtr { /** * Subscript operator. */ - constexpr GlobRef operator[](gptrdiff_t n) const DASH_NOEXCEPT + constexpr auto operator[](gptrdiff_t n) const DASH_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 +374,9 @@ class GlobPtr { */ GlobRef operator[](gptrdiff_t n) DASH_NOEXCEPT { - return GlobRef(self_t((*this) + n)); + auto ptr = *this; + ptr += n; + return GlobRef(std::move(ptr)); } /** @@ -383,7 +392,9 @@ class GlobPtr { */ constexpr GlobRef operator*() const DASH_NOEXCEPT { - return GlobRef(*this); + auto const_ptr = const_type{*this}; + return GlobRef::type>( + std::move(const_ptr)); } /** @@ -409,7 +420,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); @@ -443,7 +455,6 @@ class GlobPtr { return !DART_GPTR_ISNULL(m_dart_pointer); } -private: void increment(size_type offs) DASH_NOEXCEPT { if (offs == 0) { @@ -457,8 +468,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, @@ -544,14 +556,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 a87d95465..fe9edbb18 100644 --- a/dash/include/dash/GlobRef.h +++ b/dash/include/dash/GlobRef.h @@ -1,141 +1,52 @@ #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; - - - 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()) - { } - -public: - /** - * Reference semantics forbid declaration without definition. - */ - GlobRef() = delete; + template + friend class GlobRef; //required for .member() - GlobRef(const GlobRef & other) = delete; - /** - * Constructor, creates an GlobRef object referencing an element in global - * memory. - */ - explicit constexpr GlobRef(dart_gptr_t dart_gptr) noexcept - : _gptr(dart_gptr) - { - } - - /** - * 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 - * volatile qualifiers - * 2) value_type and _T are the same types after removing const and - * volatile qualifiers and value_type itself is const. - */ - template < - typename _T, - long = internal::enable_implicit_copy_ctor::value> - constexpr GlobRef(const GlobRef<_T>& gref) noexcept - : 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 - * volatile qualifiers - * 2) value_type is const and _T is non-const - */ - template < - typename _T, - int = internal::enable_explicit_copy_ctor::value> - explicit constexpr GlobRef(const GlobRef<_T>& gref) noexcept - : GlobRef(gref.dart_gptr()) - { - } + template + friend std::ostream & operator<<( + std::ostream & os, + const GlobRef & gref); +public: + //inherit all constructors from parent class + using detail::GlobRefBase::GlobRefBase; /** - * Constructor to convert \c GlobAsyncRef to GlobRef. Set to explicit to - * avoid unintendet conversion + * COPY Construction */ - template < - typename _T, - long = internal::enable_implicit_copy_ctor::value> - constexpr GlobRef(const GlobAsyncRef<_T>& gref) noexcept - : _gptr(gref.dart_gptr()) - { - } - - template < - typename _T, - int = internal::enable_explicit_copy_ctor::value> - explicit constexpr GlobRef(const GlobAsyncRef<_T>& gref) noexcept - : GlobRef(gref.dart_gptr()) - { - } + GlobRef(const GlobRef & other) = default; /** - * Move Constructor + * MOVE Construction */ - GlobRef(self_t&& other) noexcept - :_gptr(std::move(other._gptr)) - { - DASH_LOG_TRACE("GlobRef.GlobRef(GlobRef &&)", _gptr); - } + GlobRef(GlobRef && other) = default; /** - * Copy Assignment + * Copy Assignment: We copy the value behind this address, NOT the reference */ - const self_t & operator=(const self_t & other) const + const GlobRef & operator=(const GlobRef & 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)); @@ -145,8 +56,9 @@ class GlobRef /** * Move Assignment: Redirects to Copy Assignment */ - self_t& operator=(self_t&& other) noexcept { - 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; } @@ -154,7 +66,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; } @@ -162,67 +75,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 @@ -230,8 +120,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 @@ -239,35 +130,22 @@ 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!"); -#if 0 - // TODO: Alternative implementation, possibly more efficient: - T add_val = ref; - T old_val; - dart_ret_t result = dart_fetch_and_op( - _gptr, - reinterpret_cast(&add_val), - reinterpret_cast(&old_val), - dash::dart_datatype::value, - dash::plus().dart_operation(), - dash::Team::All().dart_id()); - dart_flush(_gptr); - #else nonconst_value_type val = operator nonconst_value_type(); val += ref; operator=(val); - #endif 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!"); @@ -277,7 +155,7 @@ class GlobRef return *this; } - const self_t & + const GlobRef & operator++() const { static_assert(std::is_same::value, "Cannot modify value referenced by GlobRef!"); @@ -296,7 +174,7 @@ class GlobRef return res; } - const self_t & + const GlobRef & operator--() const { static_assert(std::is_same::value, "Cannot modify value referenced by GlobRef!"); @@ -315,7 +193,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!"); @@ -325,7 +203,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!"); @@ -335,7 +213,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!"); @@ -345,44 +223,42 @@ 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; } /** * Get a global ref to a member of a certain type at the * specified offset */ - template - GlobRef::type> - member(size_t offs) const { - dart_gptr_t dartptr = _gptr; - DASH_ASSERT_RETURNS( - dart_gptr_incaddr(&dartptr, offs), - DART_OK); - return GlobRef::type>(dartptr); + 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 = this->dart_gptr(); + 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)); } /** @@ -396,8 +272,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 @@ -406,13 +303,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 3d2f99459..2ed71bc22 100644 --- a/dash/include/dash/Shared.h +++ b/dash/include/dash/Shared.h @@ -242,7 +242,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); } /** @@ -254,7 +254,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/TypeTraits.h b/dash/include/dash/TypeTraits.h new file mode 100644 index 000000000..7b412986a --- /dev/null +++ b/dash/include/dash/TypeTraits.h @@ -0,0 +1,103 @@ +#ifndef DASH__TYPE_TRAITS_H_ +#define DASH__TYPE_TRAITS_H_ + +#include + +/////////////////////////////////////////////////////////////////////////////// +// 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 +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>; +}; + +} // 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 6062565f7..c5494c446 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 /** @@ -228,31 +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 -#ifdef DASH_HAVE_STD_TRIVIALLY_COPYABLE - && std::is_trivially_copyable::value -#elif defined DASH_HAVE_TRIVIAL_COPY_INTRINSIC - && __has_trivial_copy(T) -#endif - > -{ }; - -/** - * 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. @@ -264,28 +225,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/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/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/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..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 @@ -15,12 +13,17 @@ 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. */ template -class GlobRef> { +class GlobRef>: public detail::GlobRefBase> +{ /* Notes on type compatibility: * * - The general support of atomic operations on values of type T is @@ -34,6 +37,8 @@ class GlobRef> { template friend std::ostream& operator<<(std::ostream& os, const GlobRef& gref); + using base_t = detail::GlobRefBase>; + public: using value_type = T; using const_value_type = typename std::add_const::type; @@ -45,119 +50,38 @@ class GlobRef> { using const_type = GlobRef; using nonconst_type = GlobRef>; -private: - dart_gptr_t _gptr{}; - - public: - /** - * Reference semantics forbid declaration without definition. - */ - GlobRef() = delete; - //TODO rkowalewski: Clarify constructors by passing various pointer types - /** - * Constructor: Create an atomic reference to a element in global memory - */ - explicit GlobRef(dart_gptr_t dart_gptr) - : _gptr(dart_gptr) - { - DASH_LOG_TRACE_VAR("GlobRef(dart_gptr_t)", dart_gptr); - } + //inherit all constructors from parent class + using detail::GlobRefBase>::GlobRefBase; - /** - * Constructor, creates an GlobRef object referencing an element in global - * memory. - */ - template - explicit GlobRef( - /// Pointer to referenced object in global memory - const GlobPtr& gptr) - : GlobRef(gptr.dart_gptr()) + template + GlobRef(dash::GlobPtr const& gptr) + : base_t(gptr.dart_gptr()) { - static_assert( - std::is_same::value, - "Cannot create GlobRef> from GlobPtr>!"); } - template - explicit GlobRef( - /// Pointer to referenced object in global memory - const GlobPtr& gptr) - : GlobRef(gptr.dart_gptr()) + template + GlobRef(dash::GlobPtr&& gptr) + : base_t(std::move(gptr.dart_gptr())) { } /** - * 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 - * volatile qualifiers - * 2) value_type and _T are the same types after removing const and - * volatile qualifiers and value_type itself is const. + * COPY Construction */ - template < - typename _T, - int = internal::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 - * volatile qualifiers - * 2) value_type is const and _T is non-const - */ - template < - typename _T, - long = internal::enable_explicit_copy_ctor::value> - explicit GlobRef(const GlobRef>& gref) - : GlobRef(gref.dart_gptr()) - { - } - - /** - * 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 - * volatile qualifiers - * 2) value_type and _T 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) - : 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 - * volatile qualifiers - * 2) value_type is const and _T is non-const - */ - template < - typename _T, - long = internal::enable_explicit_copy_ctor::value> - explicit GlobRef(const GlobAsyncRef>& gref) - : GlobRef(gref.dart_gptr()) - { - } + GlobRef(const GlobRef & other) = default; /** * Move Constructor. */ - GlobRef(self_t&& other) = default; + GlobRef(GlobRef&& other) = default; /** * Copy Assignment: Copies atomically the value from other */ - self_t& operator=(const self_t& other) const + GlobRef& operator=(const GlobRef& other) const { store(static_cast(other)); return *this; @@ -166,7 +90,7 @@ class GlobRef> { /** * Move Assignment: Redirects to Copy Assignment */ - self_t& operator=(self_t&& other) { + GlobRef& operator=(GlobRef&& other) { operator=(other); return *this; } @@ -176,18 +100,13 @@ class GlobRef> { return load(); } - dart_gptr_t dart_gptr() const - { - return _gptr; - } - /** * Checks whether the globally referenced element is in * the calling unit's local memory. */ bool is_local() const { - return dash::internal::is_local(_gptr); + return dash::internal::is_local(this->dart_gptr()); } /** @@ -218,15 +137,16 @@ class GlobRef> { static_assert( std::is_same::value, "Cannot modify value referenced by GlobRef>!"); + auto gptr = this->dart_gptr(); DASH_LOG_DEBUG_VAR("GlobRef.store()", value); - DASH_LOG_TRACE_VAR("GlobRef.store", _gptr); + DASH_LOG_TRACE_VAR("GlobRef.store", gptr); dart_ret_t ret = dart_accumulate( - _gptr, + this->dart_gptr(), &value, 1, dash::dart_punned_datatype::value, DART_OP_REPLACE); - dart_flush(_gptr); + dart_flush(gptr); DASH_ASSERT_EQ(DART_OK, ret, "dart_accumulate failed"); DASH_LOG_DEBUG("GlobRef.store >"); } @@ -247,16 +167,17 @@ class GlobRef> { "Basic type or type smaller than 64bit required for " "atomic get!"); DASH_LOG_DEBUG("GlobRef.load()"); - DASH_LOG_TRACE_VAR("GlobRef.load", _gptr); + auto gptr = this->dart_gptr(); + DASH_LOG_TRACE_VAR("GlobRef.load", gptr); nonconst_value_type nothing; nonconst_value_type result; dart_ret_t ret = dart_fetch_and_op( - _gptr, + gptr, ¬hing, &result, dash::dart_punned_datatype::value, DART_OP_NO_OP); - dart_flush_local(_gptr); + dart_flush_local(gptr); DASH_ASSERT_EQ(DART_OK, ret, "dart_accumulate failed"); DASH_LOG_DEBUG_VAR("GlobRef.get >", result); return result; @@ -292,16 +213,17 @@ class GlobRef> { std::is_same::value, "Cannot modify value referenced by GlobRef>!"); DASH_LOG_DEBUG_VAR("GlobRef.op()", value); - DASH_LOG_TRACE_VAR("GlobRef.op", _gptr); + auto gptr = this->dart_gptr(); + DASH_LOG_TRACE_VAR("GlobRef.op", gptr); nonconst_value_type acc = value; DASH_LOG_TRACE("GlobRef.op", "dart_accumulate"); dart_ret_t ret = dart_accumulate( - _gptr, + gptr, &acc, 1, dash::dart_punned_datatype::value, binary_op.dart_operation()); - dart_flush(_gptr); + dart_flush(gptr); DASH_ASSERT_EQ(DART_OK, ret, "dart_accumulate failed"); DASH_LOG_DEBUG_VAR("GlobRef.op >", acc); } @@ -330,16 +252,17 @@ class GlobRef> { std::is_same::value, "Cannot modify value referenced by GlobRef>!"); DASH_LOG_DEBUG_VAR("GlobRef.fetch_op()", value); - DASH_LOG_TRACE_VAR("GlobRef.fetch_op", _gptr); + auto gptr = this->dart_gptr(); + DASH_LOG_TRACE_VAR("GlobRef.fetch_op", gptr); DASH_LOG_TRACE_VAR("GlobRef.fetch_op", typeid(value).name()); nonconst_value_type res; dart_ret_t ret = dart_fetch_and_op( - _gptr, + gptr, &value, &res, dash::dart_punned_datatype::value, binary_op.dart_operation()); - dart_flush(_gptr); + dart_flush(gptr); DASH_ASSERT_EQ(DART_OK, ret, "dart_fetch_op failed"); DASH_LOG_DEBUG_VAR("GlobRef.fetch_op >", res); return res; @@ -374,18 +297,19 @@ class GlobRef> { std::is_same::value, "Cannot modify value referenced by GlobRef!"); DASH_LOG_DEBUG_VAR("GlobRef.compare_exchange()", desired); - DASH_LOG_TRACE_VAR("GlobRef.compare_exchange", _gptr); + auto gptr = this->dart_gptr(); + DASH_LOG_TRACE_VAR("GlobRef.compare_exchange", gptr); DASH_LOG_TRACE_VAR("GlobRef.compare_exchange", expected); DASH_LOG_TRACE_VAR( "GlobRef.compare_exchange", typeid(desired).name()); nonconst_value_type result; dart_ret_t ret = dart_compare_and_swap( - _gptr, + gptr, &desired, &expected, &result, dash::dart_punned_datatype::value); - dart_flush(_gptr); + dart_flush(gptr); DASH_ASSERT_EQ(DART_OK, ret, "dart_compare_and_swap failed"); DASH_LOG_DEBUG_VAR( "GlobRef.compare_exchange >", (expected == result)); 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 - 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/GlobIter.h b/dash/include/dash/iterator/GlobIter.h index f4509f405..be6db3b04 100644 --- a/dash/include/dash/iterator/GlobIter.h +++ b/dash/include/dash/iterator/GlobIter.h @@ -224,7 +224,7 @@ class GlobIter { */ DASH_CONSTEXPR reference operator*() noexcept { - return reference{this->dart_gptr()}; + return reference{static_cast(*this)}; } /** @@ -247,7 +247,7 @@ class GlobIter { { auto p = *this; p += g_index; - return reference(p.dart_gptr()); + return reference(static_cast(p)); } /** @@ -260,7 +260,7 @@ class GlobIter { { auto p = *this; p += g_index; - return const_reference(p.dart_gptr()); + return const_reference(static_cast(p)); } /** @@ -469,8 +469,7 @@ class GlobIter { return _pattern->team(); } - private: - DASH_CONSTEXPR dart_gptr_t + DASH_CONSTEXPR auto _get_pointer_at(typename pattern_type::local_index_t pos) const { auto dart_pointer = static_cast(_globmem->begin()); 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 cd3e66f3c..68d3c9eb7 100644 --- a/dash/include/dash/iterator/internal/GlobRefBase.h +++ b/dash/include/dash/iterator/internal/GlobRefBase.h @@ -1,10 +1,20 @@ #ifndef DASH__ITERATOR__INTERNAL__GLOBREF_BASE_H__INCLUDED #define DASH__ITERATOR__INTERNAL__GLOBREF_BASE_H__INCLUDED +#include +#include #include +#include +#include + namespace dash { -namespace internal { + +/// Forward declarations +template +class GlobPtr; + +namespace detail { template struct add_const_from_type { @@ -22,29 +32,228 @@ struct null_v : std::integral_constant { // clang-format off +template +using is_implicitly_convertible = std::is_convertible< + typename std::add_lvalue_reference::type, + typename std::add_lvalue_reference::type>; + +#if 0 template -using common_condition = std::is_same< - typename std::remove_cv::type, - typename std::remove_cv::type>; +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::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_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, + 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), + !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))}; +} + +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 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; + + 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()) + { + } + + /** + * 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 + * 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< + typename dash::remove_atomic<_From>::type, + typename dash::remove_atomic::type>::value> + constexpr GlobRefBase(const GlobRefBase<_From>& gref) noexcept + : GlobRefBase(gref.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< + typename dash::remove_atomic<_From>::type, + typename dash::remove_atomic::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. + * 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< + typename dash::remove_atomic<_From>::type, + typename dash::remove_atomic::type>::value> + explicit 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< + typename dash::remove_atomic<_From>::type, + typename dash::remove_atomic::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}; +}; + +} // namespace detail } // namespace dash #endif diff --git a/dash/include/dash/map/UnorderedMap.h b/dash/include/dash/map/UnorderedMap.h index 77618c52e..d719470c1 100644 --- a/dash/include/dash/map/UnorderedMap.h +++ b/dash/include/dash/map/UnorderedMap.h @@ -163,7 +163,7 @@ class UnorderedMap { /// to remote unit in next commit. std::vector _move_elements; /// Global pointer to local element in _local_sizes. - dart_gptr_t _local_size_gptr = DART_GPTR_NULL; + typename local_sizes_map::pointer _local_size_gptr{}; /// Hash type for mapping of key to unit and local offset. hasher _key_hash; /// Predicate for key comparison. @@ -315,7 +315,9 @@ class UnorderedMap { // Initialize local sizes with 0: _local_sizes.allocate(_team->size(), dash::BLOCKED, *_team); _local_sizes.local[0] = 0; - _local_size_gptr = _local_sizes[_myid].dart_gptr(); + + _local_size_gptr = static_cast( + _local_sizes.begin() + _myid); // Global iterators: _begin = iterator(this, 0); diff --git a/dash/include/dash/memory/GlobStaticMem.h b/dash/include/dash/memory/GlobStaticMem.h index d89793296..1559c0c8c 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(); diff --git a/dash/test/iterator/GlobAsyncRefTest.cc b/dash/test/iterator/GlobAsyncRefTest.cc index 6a671cc72..5066358e7 100644 --- a/dash/test/iterator/GlobAsyncRefTest.cc +++ b/dash/test/iterator/GlobAsyncRefTest.cc @@ -86,23 +86,6 @@ TEST_F(GlobAsyncRefTest, GetSet) { ASSERT_EQ_U(left_neighbor, array.local[0]); } -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 = static_cast>( - array.async[dash::myid().id]); - ASSERT_EQ_U(gref_async.is_local(), true); - ASSERT_EQ_U(gref_sync.is_local(), true); -} - struct mytype {int a; double b; }; std::ostream& @@ -169,7 +152,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 +169,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..82043e5f8 100644 --- a/dash/test/types/AtomicTest.cc +++ b/dash/test/types/AtomicTest.cc @@ -289,13 +289,13 @@ TEST_F(AtomicTest, ArrayElements) "prev: array @ unit(", remote_prev, ") +=", my_val); // in fact, this is a hack dash::GlobRef>( - array[remote_prev].dart_gptr() + dash::addressof(array[remote_prev]) ).add(my_val); DASH_LOG_TRACE("AtomicTest.ArrayElements", "next: array @ unit(", remote_next, ") +=", my_val); dash::GlobRef>( - array[remote_next].dart_gptr() + dash::addressof(array[remote_next]) ).fetch_add(my_val); DASH_LOG_TRACE("AtomicTest.ArrayElements", "barrier #2"); @@ -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); diff --git a/dash/test/types/GlobRefTest.cc b/dash/test/types/GlobRefTest.cc index f19db47a6..f5481fb83 100644 --- a/dash/test/types/GlobRefTest.cc +++ b/dash/test/types/GlobRefTest.cc @@ -1,19 +1,20 @@ - #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]; auto address_of_ref = dash::addressof(gref); @@ -58,3 +59,178 @@ 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; +}; + +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}; + // + // + + 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 + // int& ref2 = cref; + // dash::GlobRef gref2 = cgref; +} + +TEST_F(GlobRefTest, InheritanceConversionTest) +{ + dash::Array dArray{100}; + std::array stdArray{}; + + Child child; + child.x = 12; + child.y = 34; + + dash::fill(dArray.begin(), dArray.end(), child); + std::fill(stdArray.begin(), stdArray.end(), child); + + dArray.barrier(); + + auto lpos = dArray.pattern().local(10); + + child.x = 56; + child.y = 123; + if (lpos.unit == dash::team_unit_t{dash::myid()}) { + dArray.local[lpos.index] = child; + } + + stdArray[lpos.index] = child; + + dArray.barrier(); + + 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]; + dash::GlobRef upcastParent_dArray = dArray[10]; + + auto const val = child; + auto const &cref = val; + + // Why can we assign a const val to + auto &r_auto = val; + // The reason this works is the following + 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); + + // 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); + 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(upcastParent_stdArray.x, 56); + EXPECT_EQ_U(downcastChild_stdArray.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(upcastParent_dArray).x, 56); + EXPECT_EQ_U(static_cast(downcastChild_dArray).y, 123); +} + +template +using dash_ref = dash::GlobRef; + +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, + ""); + } +}; + +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, + ""); + } +}; + +TEST_F(GlobRefTest, ConversionRules) +{ + constexpr bool ignore = true; + + // Rule 1.1: T &-> const T & + StandardConformabilityTester::test(); + // Rule 1.2: const T & -> int & + // Conversion Fails due to const correctness + StandardConformabilityTester::test(); + + // Rule 2: T & -> U & if T and U are not related (FAILS) + StandardConformabilityTester::test(); + + // Rule 3: Child & -> Parent & (Upcast) + StandardConformabilityTester::test(); + + // Rule 4.1: Child & -> const Parent & (Upcast to const) + // Rule 4.2: const Child & -> Parent & (FAILS, const correctness) + StandardConformabilityTester::test(); + StandardConformabilityTester::test(); + + // 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(); +}