diff --git a/dash/include/dash/GlobAsyncRef.h b/dash/include/dash/GlobAsyncRef.h index e56325750..1a03a45e7 100644 --- a/dash/include/dash/GlobAsyncRef.h +++ b/dash/include/dash/GlobAsyncRef.h @@ -45,10 +45,12 @@ class GlobAsyncRef typename ElementT > friend class GlobAsyncRef; -private: +public: typedef GlobAsyncRef self_t; + typedef T value_type; + typedef typename std::remove_const::type nonconst_value_type; @@ -279,6 +281,15 @@ class GlobAsyncRef return this->_gptr; } + /** + * Disallow implicit comparison with other global references. + */ + template + bool operator==(const GlobAsyncRef & other) = delete; + + template + bool operator!=(const GlobAsyncRef & other) = delete; + /** * Flush all pending asynchronous operations on this asynchronous reference. */ diff --git a/dash/include/dash/GlobRef.h b/dash/include/dash/GlobRef.h index 44d5959ad..44b67b76b 100644 --- a/dash/include/dash/GlobRef.h +++ b/dash/include/dash/GlobRef.h @@ -177,12 +177,25 @@ class GlobRef return t; } - constexpr bool operator==(const_value_type & value) const + 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; } - constexpr bool operator!=(const_value_type & value) const + template + constexpr bool operator!=(const ValueT& value) const { return !(*this == value); } diff --git a/dash/include/dash/atomic/GlobAtomicRef.h b/dash/include/dash/atomic/GlobAtomicRef.h index 70c8eb3fb..1312d69d3 100644 --- a/dash/include/dash/atomic/GlobAtomicRef.h +++ b/dash/include/dash/atomic/GlobAtomicRef.h @@ -16,7 +16,7 @@ template class Shared; /** - * Specialization for atomic values. All atomic operations are + * Specialization for atomic values. All atomic operations are * \c const as the \c GlobRef does not own the atomic values. */ template @@ -102,19 +102,6 @@ class GlobRef> self_t & operator=(const self_t & other) = delete; - inline bool operator==(const self_t & other) const noexcept - { - return _gptr == other._gptr; - } - - inline bool operator!=(const self_t & other) const noexcept - { - return !(*this == other); - } - - inline bool operator==(const T & value) const = delete; - inline bool operator!=(const T & value) const = delete; - operator T() const { return load(); } @@ -256,9 +243,9 @@ class GlobRef> /** * Atomically compares the value with the value of expected and if thosei * are bitwise-equal, replaces the former with desired. - * + * * \return True if value is exchanged - * + * * \see \c dash::atomic::compare_exchange */ bool compare_exchange(const T & expected, const T & desired) const { diff --git a/dash/test/container/ArrayTest.cc b/dash/test/container/ArrayTest.cc index fdc6f3b66..825d52103 100644 --- a/dash/test/container/ArrayTest.cc +++ b/dash/test/container/ArrayTest.cc @@ -273,7 +273,6 @@ TEST_F(ArrayTest, MoveSemantics){ } } - TEST_F(ArrayTest, ElementCompare){ using value_t = int; using array_t = dash::Array; @@ -285,6 +284,19 @@ TEST_F(ArrayTest, ElementCompare){ array_t arr(dash::size()); dash::fill(arr.begin(), arr.end(), 0); + arr.barrier(); ASSERT_EQ_U(arr[0], arr[1]); + + ASSERT_EQ_U(0, arr[dash::myid()]); + ASSERT_EQ_U(arr[dash::myid()], 0); + ASSERT_EQ_U(arr[dash::myid()], 0UL); + + dash::barrier(); + arr[dash::myid()] = dash::myid(); + ASSERT_EQ_U(dash::myid(), arr[dash::myid()]); + dash::barrier(); + if (dash::myid() > 0) { + ASSERT_NE_U(arr[0], arr[dash::myid()]); + } } diff --git a/dash/test/types/AtomicTest.cc b/dash/test/types/AtomicTest.cc index f8db77b37..f6f3dbbb9 100644 --- a/dash/test/types/AtomicTest.cc +++ b/dash/test/types/AtomicTest.cc @@ -327,7 +327,7 @@ TEST_F(AtomicTest, AlgorithmVariant){ for(int i=0; i(dash::myid().id); value_t id_right = (myid + 1) % dash::size(); - + array[myid].store(myid); array.barrier(); ASSERT_EQ_U(id_right, array[id_right].load()); @@ -430,13 +430,13 @@ TEST_F(AtomicTest, AtomicInterface){ TEST_F(AtomicTest, MutexInterface){ dash::Mutex mx; - + dash::Shared shared(dash::team_unit_t{0}); - + if(dash::myid() == 0){ shared.set(0); } - + mx.lock(); int tmp = shared.get(); std::this_thread::sleep_for(std::chrono::microseconds(100)); @@ -444,34 +444,34 @@ TEST_F(AtomicTest, MutexInterface){ LOG_MESSAGE("Before %d, after %d", tmp, static_cast(shared.get())); // I guess here a flush is required, blocked by issue 322 mx.unlock(); - + dash::barrier(); - + while(!mx.try_lock()){ } // lock aquired tmp = shared.get(); std::this_thread::sleep_for(std::chrono::microseconds(100)); shared.set(tmp + 1); mx.unlock(); - + dash::barrier(); - + if(dash::myid() == 0){ int result = shared.get(); EXPECT_EQ_U(result, static_cast(dash::size()*2)); } - + dash::barrier(); - + // this even works with std::lock_guard { std::lock_guard lg(mx); int tmp = shared.get(); shared.set(tmp + 1); } - + dash::barrier(); - + if(dash::myid() == 0){ int result = shared.get(); EXPECT_EQ_U(result, static_cast(dash::size())*3); @@ -491,8 +491,6 @@ TEST_F(AtomicTest, AtomicSignal){ array_t array(dash::size()); dash::fill(array.begin(), array.end(), 0); - int neighbor = (dash::myid() + 1) % dash::size(); - if (dash::myid() != 0) { // send the signal array[0].add(1); @@ -507,3 +505,27 @@ TEST_F(AtomicTest, AtomicSignal){ ASSERT_GT_U(count, 0); } } + +TEST_F(AtomicTest, ElementCompare){ + using value_t = int; + using atom_t = dash::Atomic; + using array_t = dash::Array; + + if (dash::size() < 2) { + SKIP_TEST_MSG("At least 2 units required"); + } + + array_t array(dash::size()); + dash::fill(array.begin(), array.end(), 0); + dash::barrier(); + + ASSERT_EQ_U(0, array[dash::myid()]); + ASSERT_EQ_U(0UL, array[dash::myid()]); + ASSERT_EQ_U(array[dash::myid()], 0); + ASSERT_EQ_U(array[dash::myid()], 0UL); + // forbidden + //ASSERT_EQ_U(array[0], array[dash::myid()]); + + // OK + ASSERT_EQ_U(array[0].get(), array[dash::myid()]); +}