diff --git a/libcxx/include/atomic b/libcxx/include/atomic index 0d3e6afd203c..89970cfa888f 100644 --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -11380,6 +11380,476 @@ atomic_fetch_xor_explicit(atomic_wchar_t* __obj, wchar_t __v, __v, __o); } +// atomic_address + +struct atomic_address; + +bool atomic_is_lock_free(const volatile atomic_address*); +bool atomic_is_lock_free(const atomic_address*); +void atomic_init(volatile atomic_address*, void*); +void atomic_init(atomic_address*, void*); +void atomic_store(volatile atomic_address*, void*); +void atomic_store(atomic_address*, void*); +void atomic_store_explicit(volatile atomic_address*, void*, memory_order); +void atomic_store_explicit(atomic_address*, void*, memory_order); +void* atomic_load(const volatile atomic_address*); +void* atomic_load(const atomic_address*); +void* atomic_load_explicit(const volatile atomic_address*, memory_order); +void* atomic_load_explicit(const atomic_address*, memory_order); +void* atomic_exchange(volatile atomic_address*, void*); +void* atomic_exchange(atomic_address*, void*); +void* atomic_exchange_explicit(volatile atomic_address*, void*, memory_order); +void* atomic_exchange_explicit(atomic_address*, void*, memory_order); +bool atomic_compare_exchange_weak(volatile atomic_address*, void**, void*); +bool atomic_compare_exchange_weak(atomic_address*, void**, void*); +bool atomic_compare_exchange_strong(volatile atomic_address*, void**, void*); +bool atomic_compare_exchange_strong(atomic_address*, void**, void*); +bool atomic_compare_exchange_weak_explicit(volatile atomic_address*, void**, + void*, memory_order, memory_order); +bool atomic_compare_exchange_weak_explicit(atomic_address*, void**, + void*, memory_order, memory_order); +bool atomic_compare_exchange_strong_explicit(volatile atomic_address*, void**, + void*, memory_order, memory_order); +bool atomic_compare_exchange_strong_explicit(atomic_address*, void**, + void*, memory_order, memory_order); +void* atomic_fetch_add(volatile atomic_address*, ptrdiff_t); +void* atomic_fetch_add(atomic_address*, ptrdiff_t); +void* atomic_fetch_add_explicit(volatile atomic_address*, ptrdiff_t, + memory_order); +void* atomic_fetch_add_explicit(atomic_address*, ptrdiff_t, memory_order); +void* atomic_fetch_sub(volatile atomic_address*, ptrdiff_t); +void* atomic_fetch_sub(atomic_address*, ptrdiff_t); +void* atomic_fetch_sub_explicit(volatile atomic_address*, ptrdiff_t, + memory_order); +void* atomic_fetch_sub_explicit(atomic_address*, ptrdiff_t, memory_order); + +typedef struct atomic_address +{ + void* __v_; + + _LIBCPP_INLINE_VISIBILITY + bool is_lock_free() const volatile + {return atomic_is_lock_free(this);} + _LIBCPP_INLINE_VISIBILITY + bool is_lock_free() const + {return atomic_is_lock_free(this);} + _LIBCPP_INLINE_VISIBILITY + void store(void* __v, memory_order __o = memory_order_seq_cst) volatile + {atomic_store_explicit(this, __v, __o);} + _LIBCPP_INLINE_VISIBILITY + void store(void* __v, memory_order __o = memory_order_seq_cst) + {atomic_store_explicit(this, __v, __o);} + _LIBCPP_INLINE_VISIBILITY + void* load(memory_order __o = memory_order_seq_cst) const volatile + {return atomic_load_explicit(this, __o);} + _LIBCPP_INLINE_VISIBILITY + void* load(memory_order __o = memory_order_seq_cst) const + {return atomic_load_explicit(this, __o);} + _LIBCPP_INLINE_VISIBILITY + operator void*() const volatile + {return load();} + _LIBCPP_INLINE_VISIBILITY + operator void*() const + {return load();} + _LIBCPP_INLINE_VISIBILITY + void* exchange(void* __v, memory_order __o = memory_order_seq_cst) volatile + {return atomic_exchange_explicit(this, __v, __o);} + _LIBCPP_INLINE_VISIBILITY + void* exchange(void* __v, memory_order __o = memory_order_seq_cst) + {return atomic_exchange_explicit(this, __v, __o);} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_weak(void*& __v, void* __e, memory_order __s, + memory_order __f) volatile + {return atomic_compare_exchange_weak_explicit(this, &__v, __e, __s, + __f);} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_weak(void*& __v, void* __e, memory_order __s, + memory_order __f) + {return atomic_compare_exchange_weak_explicit(this, &__v, __e, __s, + __f);} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_strong(void*& __v, void* __e, memory_order __s, + memory_order __f) volatile + {return atomic_compare_exchange_strong_explicit(this, &__v, __e, __s, + __f);} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_strong(void*& __v, void* __e, memory_order __s, + memory_order __f) + {return atomic_compare_exchange_strong_explicit(this, &__v, __e, __s, + __f);} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_weak(void*& __v, void* __e, + memory_order __s = memory_order_seq_cst) volatile + {return atomic_compare_exchange_weak_explicit(this, &__v, __e, __s, + __translate_memory_order(__s));} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_weak(void*& __v, void* __e, + memory_order __s = memory_order_seq_cst) + {return atomic_compare_exchange_weak_explicit(this, &__v, __e, __s, + __translate_memory_order(__s));} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_strong(void*& __v, void* __e, + memory_order __s = memory_order_seq_cst) volatile + {return atomic_compare_exchange_strong_explicit(this, &__v, __e, __s, + __translate_memory_order(__s));} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_strong(void*& __v, void* __e, + memory_order __s = memory_order_seq_cst) + {return atomic_compare_exchange_strong_explicit(this, &__v, __e, __s, + __translate_memory_order(__s));} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_weak(const void*& __v, const void* __e, + memory_order __s, memory_order __f) volatile + {return atomic_compare_exchange_weak_explicit(this, + &const_cast(__v), const_cast(__e), __s, __f);} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_weak(const void*& __v, const void* __e, + memory_order __s, memory_order __f) + {return atomic_compare_exchange_weak_explicit(this, + &const_cast(__v), const_cast(__e), __s, __f);} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_strong(const void*& __v, const void* __e, + memory_order __s, memory_order __f) volatile + {return atomic_compare_exchange_strong_explicit(this, + &const_cast(__v), const_cast(__e), __s, __f);} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_strong(const void*& __v, const void* __e, + memory_order __s, memory_order __f) + {return atomic_compare_exchange_strong_explicit(this, + &const_cast(__v), const_cast(__e), __s, __f);} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_weak(const void*& __v, const void* __e, + memory_order __s = memory_order_seq_cst) volatile + {return atomic_compare_exchange_weak_explicit(this, + &const_cast(__v), const_cast(__e), + __s, __translate_memory_order(__s));} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_weak(const void*& __v, const void* __e, + memory_order __s = memory_order_seq_cst) + {return atomic_compare_exchange_weak_explicit(this, + &const_cast(__v), const_cast(__e), + __s, __translate_memory_order(__s));} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_strong(const void*& __v, const void* __e, + memory_order __s = memory_order_seq_cst) volatile + {return atomic_compare_exchange_strong_explicit(this, + &const_cast(__v), const_cast(__e), + __s, __translate_memory_order(__s));} + _LIBCPP_INLINE_VISIBILITY + bool compare_exchange_strong(const void*& __v, const void* __e, + memory_order __s = memory_order_seq_cst) + {return atomic_compare_exchange_strong_explicit(this, + &const_cast(__v), const_cast(__e), + __s, __translate_memory_order(__s));} + _LIBCPP_INLINE_VISIBILITY + void* fetch_add(ptrdiff_t __v, + memory_order __o = memory_order_seq_cst) volatile + {return atomic_fetch_add_explicit(this, __v, __o);} + _LIBCPP_INLINE_VISIBILITY + void* fetch_add(ptrdiff_t __v, memory_order __o = memory_order_seq_cst) + {return atomic_fetch_add_explicit(this, __v, __o);} + _LIBCPP_INLINE_VISIBILITY + void* fetch_sub(ptrdiff_t __v, + memory_order __o = memory_order_seq_cst) volatile + {return atomic_fetch_sub_explicit(this, __v, __o);} + _LIBCPP_INLINE_VISIBILITY + void* fetch_sub(ptrdiff_t __v, memory_order __o = memory_order_seq_cst) + {return atomic_fetch_sub_explicit(this, __v, __o);} +#ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS + atomic_address() = default; +#else + _LIBCPP_INLINE_VISIBILITY + atomic_address() {} +#endif + _LIBCPP_INLINE_VISIBILITY + /*constexpr*/ atomic_address(void* __v) + : __v_(__v) {} +#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS + atomic_address(const atomic_address&) = delete; + atomic_address& operator=(const atomic_address&) = delete; + atomic_address& operator=(const atomic_address&) volatile = delete; +#else +private: + atomic_address(const atomic_address&); + atomic_address& operator=(const atomic_address&); + atomic_address& operator=(const atomic_address&) volatile; +public: +#endif + _LIBCPP_INLINE_VISIBILITY + void* operator=(const void* __v) volatile + {store(const_cast(__v)); return const_cast(__v);} + _LIBCPP_INLINE_VISIBILITY + void* operator=(const void* __v) + {store(const_cast(__v)); return const_cast(__v);} + _LIBCPP_INLINE_VISIBILITY + void* operator+=(ptrdiff_t __v) volatile + {return static_cast(fetch_add(__v)) + __v;} + _LIBCPP_INLINE_VISIBILITY + void* operator+=(ptrdiff_t __v) + {return static_cast(fetch_add(__v)) + __v;} + _LIBCPP_INLINE_VISIBILITY + void* operator-=(ptrdiff_t __v) volatile + {return static_cast(fetch_sub(__v)) - __v;} + _LIBCPP_INLINE_VISIBILITY + void* operator-=(ptrdiff_t __v) + {return static_cast(fetch_sub(__v)) - __v;} +} atomic_address; + +inline _LIBCPP_INLINE_VISIBILITY +bool +atomic_is_lock_free(const volatile atomic_address*) +{ + typedef void* type; + return __atomic_is_lock_free(type); +} + +inline _LIBCPP_INLINE_VISIBILITY +bool +atomic_is_lock_free(const atomic_address* __obj) +{ + return atomic_is_lock_free(const_cast(__obj)); +} + +inline _LIBCPP_INLINE_VISIBILITY +void +atomic_init(volatile atomic_address* __obj, void* __desr) +{ + __obj->__v_ = __desr; +} + +inline _LIBCPP_INLINE_VISIBILITY +void +atomic_init(atomic_address* __obj, void* __desr) +{ + __obj->__v_ = __desr; +} + +inline _LIBCPP_INLINE_VISIBILITY +void +atomic_store(volatile atomic_address* __obj, void* __desr) +{ + __atomic_store(&__obj->__v_, __desr, memory_order_seq_cst); +} + +inline _LIBCPP_INLINE_VISIBILITY +void +atomic_store(atomic_address* __obj, void* __desr) +{ + atomic_store(const_cast(__obj), __desr); +} + +inline _LIBCPP_INLINE_VISIBILITY +void +atomic_store_explicit(volatile atomic_address* __obj, void* __desr, + memory_order __o) +{ + __atomic_store(&__obj->__v_, __desr, __o); +} + +inline _LIBCPP_INLINE_VISIBILITY +void +atomic_store_explicit(atomic_address* __obj, void* __desr, memory_order __o) +{ + atomic_store_explicit(const_cast(__obj), __desr, + __o); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_load(const volatile atomic_address* __obj) +{ + return __atomic_load(&__obj->__v_, memory_order_seq_cst); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_load(const atomic_address* __obj) +{ + return atomic_load(const_cast(__obj)); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_load_explicit(const volatile atomic_address* __obj, memory_order __o) +{ + return __atomic_load(&__obj->__v_, __o); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_load_explicit(const atomic_address* __obj, memory_order __o) +{ + return atomic_load_explicit(const_cast + (__obj), __o); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_exchange(volatile atomic_address* __obj, void* __desr) +{ + return __atomic_exchange(&__obj->__v_, __desr, memory_order_seq_cst); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_exchange(atomic_address* __obj, void* __desr) +{ + return atomic_exchange(const_cast(__obj), __desr); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_exchange_explicit(volatile atomic_address* __obj, void* __desr, + memory_order __o) +{ + return __atomic_exchange(&__obj->__v_, __desr, __o); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_exchange_explicit(atomic_address* __obj, void* __desr, memory_order __o) +{ + return atomic_exchange_explicit(const_cast + (__obj), __desr, __o); +} + +inline _LIBCPP_INLINE_VISIBILITY +bool +atomic_compare_exchange_weak(volatile atomic_address* __obj, void** __exp, + void* __desr) +{ + return __atomic_compare_exchange_weak(&__obj->__v_, __exp, __desr, + memory_order_seq_cst, memory_order_seq_cst); +} + +inline _LIBCPP_INLINE_VISIBILITY +bool +atomic_compare_exchange_weak(atomic_address* __obj, void** __exp, void* __desr) +{ + return atomic_compare_exchange_weak(const_cast + (__obj), __exp, __desr); +} + +inline _LIBCPP_INLINE_VISIBILITY +bool +atomic_compare_exchange_strong(volatile atomic_address* __obj, void** __exp, + void* __desr) +{ + return __atomic_compare_exchange_strong(&__obj->__v_, __exp, __desr, + memory_order_seq_cst, memory_order_seq_cst); +} + +inline _LIBCPP_INLINE_VISIBILITY +bool +atomic_compare_exchange_strong(atomic_address* __obj, void** __exp, + void* __desr) +{ + return atomic_compare_exchange_strong(const_cast + (__obj), __exp, __desr); +} + +inline _LIBCPP_INLINE_VISIBILITY +bool +atomic_compare_exchange_weak_explicit(volatile atomic_address* __obj, + void** __exp, void* __desr, + memory_order __s, memory_order __f) +{ + return __atomic_compare_exchange_weak(&__obj->__v_, __exp, __desr, __s, + __f); +} + +inline _LIBCPP_INLINE_VISIBILITY +bool +atomic_compare_exchange_weak_explicit(atomic_address* __obj, void** __exp, + void* __desr, memory_order __s, + memory_order __f) +{ + return atomic_compare_exchange_weak_explicit( + const_cast(__obj), __exp, __desr, __s, __f); +} + +inline _LIBCPP_INLINE_VISIBILITY +bool +atomic_compare_exchange_strong_explicit(volatile atomic_address* __obj, + void** __exp, void* __desr, + memory_order __s, memory_order __f) +{ + return __atomic_compare_exchange_strong(&__obj->__v_, __exp, __desr, __s, + __f); +} + +inline _LIBCPP_INLINE_VISIBILITY +bool +atomic_compare_exchange_strong_explicit(atomic_address* __obj, void** __exp, + void* __desr, memory_order __s, + memory_order __f) +{ + return atomic_compare_exchange_strong_explicit( + const_cast(__obj), __exp, __desr, __s, __f); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_fetch_add(volatile atomic_address* __obj, ptrdiff_t __v) +{ + return __atomic_fetch_add(&__obj->__v_, __v, memory_order_seq_cst); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_fetch_add(atomic_address* __obj, ptrdiff_t __v) +{ + return atomic_fetch_add(const_cast(__obj), __v); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_fetch_add_explicit(volatile atomic_address* __obj, ptrdiff_t __v, + memory_order __o) +{ + return __atomic_fetch_add(&__obj->__v_, __v, __o); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_fetch_add_explicit(atomic_address* __obj, ptrdiff_t __v, + memory_order __o) +{ + return atomic_fetch_add_explicit(const_cast(__obj), + __v, __o); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_fetch_sub(volatile atomic_address* __obj, ptrdiff_t __v) +{ + return __atomic_fetch_sub(&__obj->__v_, __v, memory_order_seq_cst); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_fetch_sub(atomic_address* __obj, ptrdiff_t __v) +{ + return atomic_fetch_sub(const_cast(__obj), __v); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_fetch_sub_explicit(volatile atomic_address* __obj, ptrdiff_t __v, + memory_order __o) +{ + return __atomic_fetch_sub(&__obj->__v_, __v, __o); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* +atomic_fetch_sub_explicit(atomic_address* __obj, ptrdiff_t __v, + memory_order __o) +{ + return atomic_fetch_sub_explicit(const_cast(__obj), + __v, __o); +} + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_ATOMIC diff --git a/libcxx/test/atomics/atomics.types/atomics.types.address/address.pass.cpp b/libcxx/test/atomics/atomics.types/atomics.types.address/address.pass.cpp new file mode 100644 index 000000000000..e3eb77991aa6 --- /dev/null +++ b/libcxx/test/atomics/atomics.types/atomics.types.address/address.pass.cpp @@ -0,0 +1,220 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// typedef struct atomic_address +// { +// bool is_lock_free() const volatile; +// bool is_lock_free() const; +// void store(void*, memory_order = memory_order_seq_cst) volatile; +// void store(void*, memory_order = memory_order_seq_cst); +// void* load(memory_order = memory_order_seq_cst) const volatile; +// void* load(memory_order = memory_order_seq_cst) const; +// operator void*() const volatile; +// operator void*() const; +// void* exchange(void*, memory_order = memory_order_seq_cst) volatile; +// void* exchange(void*, memory_order = memory_order_seq_cst); +// bool compare_exchange_weak(void*&, void*, memory_order, +// memory_order) volatile; +// bool compare_exchange_weak(void*&, void*, memory_order, memory_order); +// bool compare_exchange_strong(void*&, void*, memory_order, +// memory_order) volatile; +// bool compare_exchange_strong(void*&, void*, memory_order, memory_order); +// bool compare_exchange_weak(void*&, void*, +// memory_order = memory_order_seq_cst) volatile; +// bool compare_exchange_weak(void*&, void*, +// memory_order = memory_order_seq_cst); +// bool compare_exchange_strong(void*&, void*, +// memory_order = memory_order_seq_cst) volatile; +// bool compare_exchange_strong(void*&, void*, +// memory_order = memory_order_seq_cst); +// bool compare_exchange_weak(const void*&, const void*, +// memory_order, memory_order) volatile; +// bool compare_exchange_weak(const void*&, const void*, memory_order, +// memory_order); +// bool compare_exchange_strong(const void*&, const void*, memory_order, +// memory_order) volatile; +// bool compare_exchange_strong(const void*&, const void*, memory_order, +// memory_order); +// bool compare_exchange_weak(const void*&, const void*, +// memory_order = memory_order_seq_cst) volatile; +// bool compare_exchange_weak(const void*&, const void*, +// memory_order = memory_order_seq_cst); +// bool compare_exchange_strong(const void*&, const void*, +// memory_order = memory_order_seq_cst) volatile; +// bool compare_exchange_strong(const void*&, const void*, +// memory_order = memory_order_seq_cst); +// void* fetch_add(ptrdiff_t, memory_order = memory_order_seq_cst) volatile; +// void* fetch_add(ptrdiff_t, memory_order = memory_order_seq_cst); +// void* fetch_sub(ptrdiff_t, memory_order = memory_order_seq_cst) volatile; +// void* fetch_sub(ptrdiff_t, memory_order = memory_order_seq_cst); +// atomic_address() = default; +// constexpr atomic_address(void*); +// atomic_address(const atomic_address&) = delete; +// atomic_address& operator=(const atomic_address&) = delete; +// atomic_address& operator=(const atomic_address&) volatile = delete; +// void* operator=(const void*) volatile; +// void* operator=(const void*); +// void* operator+=(ptrdiff_t) volatile; +// void* operator+=(ptrdiff_t); +// void* operator-=(ptrdiff_t) volatile; +// void* operator-=(ptrdiff_t); +// } atomic_address; +// +// bool atomic_is_lock_free(const volatile atomic_address*); +// bool atomic_is_lock_free(const atomic_address*); +// void atomic_init(volatile atomic_address*, void*); +// void atomic_init(atomic_address*, void*); +// void atomic_store(volatile atomic_address*, void*); +// void atomic_store(atomic_address*, void*); +// void atomic_store_explicit(volatile atomic_address*, void*, memory_order); +// void atomic_store_explicit(atomic_address*, void*, memory_order); +// void* atomic_load(const volatile atomic_address*); +// void* atomic_load(const atomic_address*); +// void* atomic_load_explicit(const volatile atomic_address*, memory_order); +// void* atomic_load_explicit(const atomic_address*, memory_order); +// void* atomic_exchange(volatile atomic_address*, void*); +// void* atomic_exchange(atomic_address*, void*); +// void* atomic_exchange_explicit(volatile atomic_address*, void*, memory_order); +// void* atomic_exchange_explicit(atomic_address*, void*, memory_order); +// bool atomic_compare_exchange_weak(volatile atomic_address*, void**, void*); +// bool atomic_compare_exchange_weak(atomic_address*, void**, void*); +// bool atomic_compare_exchange_strong(volatile atomic_address*, void**, void*); +// bool atomic_compare_exchange_strong(atomic_address*, void**, void*); +// bool atomic_compare_exchange_weak_explicit(volatile atomic_address*, void**, +// void*, memory_order, memory_order); +// bool atomic_compare_exchange_weak_explicit(atomic_address*, void**, void*, +// memory_order, memory_order); +// bool atomic_compare_exchange_strong_explicit(volatile atomic_address*, void**, +// void*, memory_order, memory_order); +// bool atomic_compare_exchange_strong_explicit(atomic_address*, void**, void*, +// memory_order, memory_order); +// void* atomic_fetch_add(volatile atomic_address*, ptrdiff_t); +// void* atomic_fetch_add(atomic_address*, ptrdiff_t); +// void* atomic_fetch_add_explicit(volatile atomic_address*, ptrdiff_t, +// memory_order); +// void* atomic_fetch_add_explicit(atomic_address*, ptrdiff_t, memory_order); +// void* atomic_fetch_sub(volatile atomic_address*, ptrdiff_t); +// void* atomic_fetch_sub(atomic_address*, ptrdiff_t); +// void* atomic_fetch_sub_explicit(volatile atomic_address*, ptrdiff_t, +// memory_order); +// void* atomic_fetch_sub_explicit(atomic_address*, ptrdiff_t, memory_order); + +#include +#include + +template +void +do_test() +{ + A obj(T(0)); + assert(obj == T(0)); + std::atomic_init(&obj, T(1)); + assert(obj == T(1)); + std::atomic_init(&obj, T(2)); + assert(obj == T(2)); + bool b0 = obj.is_lock_free(); + obj.store(T(0)); + assert(obj == T(0)); + obj.store(T(1), std::memory_order_release); + assert(obj == T(1)); + assert(obj.load() == T(1)); + assert(obj.load(std::memory_order_acquire) == T(1)); + assert(obj.exchange(T(2)) == T(1)); + assert(obj == T(2)); + assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2)); + assert(obj == T(3)); + T x = obj; + assert(obj.compare_exchange_weak(x, T(2)) == true); + assert(obj == T(2)); + assert(x == T(3)); + assert(obj.compare_exchange_weak(x, T(1)) == false); + assert(obj == T(2)); + assert(x == T(2)); + assert(obj.compare_exchange_strong(x, T(1)) == true); + assert(obj == T(1)); + assert(x == T(2)); + assert(obj.compare_exchange_strong(x, T(0)) == false); + assert(obj == T(1)); + assert(x == T(1)); + assert((obj = T(0)) == T(0)); + assert(obj == T(0)); + obj = T(2); + assert((obj += std::ptrdiff_t(3)) == T(5)); + assert(obj == T(5)); + assert((obj -= std::ptrdiff_t(3)) == T(2)); + assert(obj == T(2)); + + std::atomic_init(&obj, T(1)); + assert(obj == T(1)); + bool b1 = std::atomic_is_lock_free(&obj); + std::atomic_store(&obj, T(0)); + assert(obj == T(0)); + std::atomic_store_explicit(&obj, T(1), std::memory_order_release); + assert(obj == T(1)); + assert(std::atomic_load(&obj) == T(1)); + assert(std::atomic_load_explicit(&obj, std::memory_order_acquire) == T(1)); + assert(std::atomic_exchange(&obj, T(2)) == T(1)); + assert(obj == T(2)); + assert(std::atomic_exchange_explicit(&obj, T(3), std::memory_order_relaxed) == T(2)); + assert(obj == T(3)); + x = obj; + assert(std::atomic_compare_exchange_weak(&obj, &x, T(2)) == true); + assert(obj == T(2)); + assert(x == T(3)); + assert(std::atomic_compare_exchange_weak(&obj, &x, T(1)) == false); + assert(obj == T(2)); + assert(x == T(2)); + assert(std::atomic_compare_exchange_strong(&obj, &x, T(1)) == true); + assert(obj == T(1)); + assert(x == T(2)); + assert(std::atomic_compare_exchange_strong(&obj, &x, T(0)) == false); + assert(obj == T(1)); + assert(x == T(1)); + assert(std::atomic_compare_exchange_weak_explicit(&obj, &x, T(2), + std::memory_order_relaxed, std::memory_order_relaxed) == true); + assert(obj == T(2)); + assert(x == T(1)); + assert(std::atomic_compare_exchange_weak_explicit(&obj, &x, T(3), + std::memory_order_relaxed, std::memory_order_relaxed) == false); + assert(obj == T(2)); + assert(x == T(2)); + assert(std::atomic_compare_exchange_strong_explicit(&obj, &x, T(3), + std::memory_order_relaxed, std::memory_order_relaxed) == true); + assert(obj == T(3)); + assert(x == T(2)); + assert(std::atomic_compare_exchange_strong_explicit(&obj, &x, T(0), + std::memory_order_relaxed, std::memory_order_relaxed) == false); + assert(obj == T(3)); + assert(x == T(3)); + assert((obj = T(1)) == T(1)); + assert(obj == T(1)); + obj = T(2); + assert(std::atomic_fetch_add(&obj, std::ptrdiff_t(3)) == T(2)); + assert(obj == T(5)); + assert(std::atomic_fetch_add_explicit(&obj, std::ptrdiff_t(3), std::memory_order_seq_cst) == T(5)); + assert(obj == T(8)); + assert(std::atomic_fetch_sub(&obj, std::ptrdiff_t(3)) == T(8)); + assert(obj == T(5)); + assert(std::atomic_fetch_sub_explicit(&obj, std::ptrdiff_t(3), std::memory_order_seq_cst) == T(5)); + assert(obj == T(2)); +} + +template +void test() +{ + do_test(); + do_test(); +} + +int main() +{ + test(); +}