diff options
author | Jason Carey <jcarey@argv.me> | 2017-08-17 16:22:13 -0400 |
---|---|---|
committer | Jason Carey <jcarey@argv.me> | 2017-08-21 13:04:36 -0400 |
commit | 0fe978629f685f19e93ebc16ea2f311590850220 (patch) | |
tree | 16640bc19e20b2c6d52d33efa32c9521a7a71e5a /src/mongo/platform/atomic_word_test.cpp | |
parent | 3128427f77397916967e3eb684dfed845bb1638a (diff) | |
download | mongo-0fe978629f685f19e93ebc16ea2f311590850220.tar.gz |
SERVER-30706 Support for non-int AtomicWord<T>
Restricts the base AtomicWord template to integral types and adds
another specialization which uses a std::atomic<uint64_t> for
non-integral types (by doing atomic 64 bit ops, then copying bytes in
and out of the user type assuming it's Trivially copyable).
Diffstat (limited to 'src/mongo/platform/atomic_word_test.cpp')
-rw-r--r-- | src/mongo/platform/atomic_word_test.cpp | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/mongo/platform/atomic_word_test.cpp b/src/mongo/platform/atomic_word_test.cpp index 8adb13722c5..f5539241b1f 100644 --- a/src/mongo/platform/atomic_word_test.cpp +++ b/src/mongo/platform/atomic_word_test.cpp @@ -112,5 +112,107 @@ TEST(AtomicWordTests, BasicOperationsSigned64Bit) { ASSERT_EQUALS(WordType(0), w.load()); } +TEST(AtomicWordTests, BasicOperationsFloat) { + typedef AtomicWord<float>::WordType WordType; + + AtomicWord<float> w; + + ASSERT_EQUALS(WordType(0), w.load()); + + w.store(1); + ASSERT_EQUALS(WordType(1), w.load()); + + ASSERT_EQUALS(WordType(1), w.swap(2)); + ASSERT_EQUALS(WordType(2), w.load()); + + ASSERT_EQUALS(WordType(2), w.compareAndSwap(0, 1)); + ASSERT_EQUALS(WordType(2), w.load()); + ASSERT_EQUALS(WordType(2), w.compareAndSwap(2, 1)); + ASSERT_EQUALS(WordType(1), w.load()); + + w.store(15); + ASSERT_EQUALS(WordType(15), w.compareAndSwap(15, 0)); + ASSERT_EQUALS(WordType(0), w.load()); +} + +struct Chars { + static constexpr size_t kLength = 6; + + Chars(const char* chars = "") { + invariant(std::strlen(chars) < kLength); + std::strncpy(_storage.data(), chars, sizeof(_storage)); + } + + std::array<char, 6> _storage = {}; + + friend bool operator==(const Chars& lhs, const Chars& rhs) { + return lhs._storage == rhs._storage; + } + + friend bool operator!=(const Chars& lhs, const Chars& rhs) { + return !(lhs == rhs); + } +}; + +std::ostream& operator<<(std::ostream& os, const Chars& chars) { + return (os << chars._storage.data()); +} + +TEST(AtomicWordTests, BasicOperationsComplex) { + using WordType = Chars; + + AtomicWord<WordType> checkZero(AtomicWord<WordType>::ZeroInitTag{}); + ASSERT_EQUALS(WordType(""), checkZero.load()); + + AtomicWord<WordType> w; + + ASSERT_EQUALS(WordType(), w.load()); + + w.store("b"); + ASSERT_EQUALS(WordType("b"), w.load()); + + ASSERT_EQUALS(WordType("b"), w.swap("c")); + ASSERT_EQUALS(WordType("c"), w.load()); + + ASSERT_EQUALS(WordType("c"), w.compareAndSwap("a", "b")); + ASSERT_EQUALS(WordType("c"), w.load()); + ASSERT_EQUALS(WordType("c"), w.compareAndSwap("c", "b")); + ASSERT_EQUALS(WordType("b"), w.load()); + + w.store("foo"); + ASSERT_EQUALS(WordType("foo"), w.compareAndSwap("foo", "bar")); + ASSERT_EQUALS(WordType("bar"), w.load()); +} + +template <typename T> +void verifyAtomicityHelper() { + ASSERT(std::atomic<T>{}.is_lock_free()); // NOLINT + ASSERT(std::atomic<typename std::make_signed<T>::type>{}.is_lock_free()); // NOLINT + ASSERT(std::atomic<typename std::make_unsigned<T>::type>{}.is_lock_free()); // NOLINT +} + +template <typename... Types> +void verifyAtomicity() { + using expander = int[]; + (void)expander{(verifyAtomicityHelper<Types>(), 0)...}; +} + +TEST(AtomicWordTests, StdAtomicOfIntegralIsLockFree) { + // 2 means that they're always atomic. Instead of 1, that means sometimes, and 0, which means + // never. + ASSERT_EQUALS(2, ATOMIC_CHAR_LOCK_FREE); + ASSERT_EQUALS(2, ATOMIC_CHAR16_T_LOCK_FREE); + ASSERT_EQUALS(2, ATOMIC_CHAR32_T_LOCK_FREE); + ASSERT_EQUALS(2, ATOMIC_WCHAR_T_LOCK_FREE); + ASSERT_EQUALS(2, ATOMIC_SHORT_LOCK_FREE); + ASSERT_EQUALS(2, ATOMIC_INT_LOCK_FREE); + ASSERT_EQUALS(2, ATOMIC_LONG_LOCK_FREE); + ASSERT_EQUALS(2, ATOMIC_LLONG_LOCK_FREE); + ASSERT_EQUALS(2, ATOMIC_POINTER_LOCK_FREE); + + verifyAtomicity<char, char16_t, char32_t, wchar_t, short, int, long, long long>(); + ASSERT(std::atomic<bool>{}.is_lock_free()); // NOLINT +} + } // namespace } // namespace mongo |