summaryrefslogtreecommitdiff
path: root/src/mongo/platform/atomic_word_test.cpp
diff options
context:
space:
mode:
authorJason Carey <jcarey@argv.me>2017-08-17 16:22:13 -0400
committerJason Carey <jcarey@argv.me>2017-08-21 13:04:36 -0400
commit0fe978629f685f19e93ebc16ea2f311590850220 (patch)
tree16640bc19e20b2c6d52d33efa32c9521a7a71e5a /src/mongo/platform/atomic_word_test.cpp
parent3128427f77397916967e3eb684dfed845bb1638a (diff)
downloadmongo-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.cpp102
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