// Copyright 2014 The Emscripten Authors. All rights reserved. // Emscripten is available under two separate licenses, the MIT license and the // University of Illinois/NCSA Open Source License. Both these licenses can be // found in the LICENSE file. //------------------------------------------------------------------------------ // test C++11 atomics // compile native version with: // clang -std=c++11 -Wno-format test_atomic_cxx.cpp // compile emscripten version with: // emcc -std=c++11 -Wno-format test_atomic_cxx.cpp //------------------------------------------------------------------------------ #include #include template void test(TYPE mask0, TYPE mask1, TYPE mask2) { typedef TYPE dog; const TYPE numMemoryOrders = 6; std::memory_order memoryOrder[numMemoryOrders] = { std::memory_order_relaxed, std::memory_order_consume, std::memory_order_acquire, std::memory_order_release, std::memory_order_acq_rel, std::memory_order_seq_cst, }; // test atomic std::atomic atomicDog(5); printf("atomic.is_lock_free(): %s\n", atomicDog.is_lock_free() ? "true" : "false"); printf("atomic value: %lld\n", (long long)TYPE(atomicDog)); // test store/load for (TYPE i = 0; i < numMemoryOrders; i++) { atomicDog.store(i, memoryOrder[i]); printf("store/load %lld: %lld\n", (long long)i, (long long)atomicDog.load(memoryOrder[i])); } // test exchange for (TYPE i = 0; i < numMemoryOrders; i++) { TYPE old = atomicDog.exchange(i, memoryOrder[i]); printf("exchange %lld: old=%lld new=%lld\n", (long long)i, (long long)old, (long long)TYPE(atomicDog)); } // compare_exchange_weak for (TYPE i = 0; i < numMemoryOrders; i++) { bool success = atomicDog.compare_exchange_weak(i, i + 1, memoryOrder[i], memoryOrder[i]); printf("compare_exchange_weak %lld: success = %s\n", (long long)i, success ? "true" : "false"); } // compare_exchange_strong for (TYPE i = 0; i < numMemoryOrders; i++) { bool success = atomicDog.compare_exchange_strong(i, i + 1, memoryOrder[i], memoryOrder[i]); printf("compare_exchange_strong %lld: success = %s\n", (long long)i, success ? "true" : "false"); } // fetch_add atomicDog = mask2; for (TYPE i = 0; i < numMemoryOrders; i++) { TYPE old = atomicDog.fetch_add(1, memoryOrder[i]); printf("fetch_add %lld: old=%llx new=%llx\n", (long long)i, (long long)old, (long long)TYPE(atomicDog)); } // fetch_sub for (TYPE i = 0; i < numMemoryOrders; i++) { TYPE old = atomicDog.fetch_sub(1, memoryOrder[i]); printf("fetch_sub %lld: old=%llx new=%llx\n", (long long)i, (long long)old, (long long)TYPE(atomicDog)); } // fetch_and for (TYPE i = 0; i < numMemoryOrders; i++) { atomicDog.store(mask0, memoryOrder[i]); TYPE old = atomicDog.fetch_and((1<(0xFF, 0xF0, 0x0F); printf("\n16 bits\n\n"); test(0xFFFF, 0xF0F0, 0x0F0F); printf("\n32 bits\n\n"); test(0xFFFFFFFF, 0xF0F0F0F0, 0x0F0F0F0F); printf("\n64 bits\n\n"); test(0xFFFFFFFFFFFFFFFF, 0xF0F0F0F0F0F0F0F0, 0x0F0F0F0F0F0F0F0F); // test atomic_flag (should also have memory_orders, but probably doesn't matter // to find the missing atomic functions) std::atomic_flag af; af.clear(); bool b = af.test_and_set(); printf("atomic_flag: %s\n", b ? "true" : "false"); printf("done.\n"); return 0; }