8 #ifndef INCL_evo_atomic_h 9 #define INCL_evo_atomic_h 14 #if defined(EVO_CPP11) || (defined(EVO_MSVC_YEAR) && EVO_MSVC_YEAR >= 2012) || defined(EVO_INTEL_VER) 16 #define EVO_INTRINSIC_ATOMICS 1 // 1 when compiler supports atomic operations 17 #define EVO_STD_ATOMIC 1 // 1 when compiler supports std::atomic and std::atomic_flag 18 #define EVO_ATOMIC_PTRMATH 1 // 1 when pointer math works correctly with AtomicPtr, i.e. increment uses sizeof() 21 #define EVO_ATOMIC_RELAXED std::memory_order_relaxed 24 #define EVO_ATOMIC_CONSUME std::memory_order_consume 27 #define EVO_ATOMIC_ACQUIRE std::memory_order_acquire 30 #define EVO_ATOMIC_RELEASE std::memory_order_release 33 #define EVO_ATOMIC_ACQ_REL std::memory_order_acq_rel 36 #define EVO_ATOMIC_SYNC std::memory_order_seq_cst 52 #define EVO_ATOMIC_FENCE(MEM_ORDER) std::atomic_thread_fence(MEM_ORDER) 53 #elif defined(EVO_GCC_VER) && EVO_GCC_VER >= 407 55 #define EVO_INTRINSIC_ATOMICS 1 56 #define EVO_GCC_ATOMICS 1 58 #define EVO_ATOMIC_RELAXED __ATOMIC_RELAXED 59 #define EVO_ATOMIC_CONSUME __ATOMIC_CONSUME 60 #define EVO_ATOMIC_ACQUIRE __ATOMIC_ACQUIRE 61 #define EVO_ATOMIC_RELEASE __ATOMIC_RELEASE 62 #define EVO_ATOMIC_ACQ_REL __ATOMIC_ACQ_REL 63 #define EVO_ATOMIC_SYNC __ATOMIC_SEQ_CST 65 #define EVO_ATOMIC_FENCE(MEM_ORDER) __atomic_thread_fence(MEM_ORDER) 67 #define EVO_ATOMIC_FETCH_OP(OP, PTR, VAL, MEM_ORDER) __atomic_fetch_ ## OP (PTR, VAL, MEM_ORDER) 68 #define EVO_ATOMIC_OP_FETCH(OP, PTR, VAL, MEM_ORDER) __atomic_ ## OP ## _fetch(PTR, VAL, MEM_ORDER) 71 #define EVO_ATOMIC_RELAXED 0 72 #define EVO_ATOMIC_CONSUME 0 73 #define EVO_ATOMIC_ACQUIRE 0 74 #define EVO_ATOMIC_RELEASE 0 75 #define EVO_ATOMIC_ACQ_REL 0 76 #define EVO_ATOMIC_SYNC 0 78 #if defined(EVO_MSVC_YEAR) || (defined(EVO_GCC_VER) && EVO_GCC_VER < 401) 81 #define EVO_INTRINSIC_ATOMICS 0 84 #define EVO_INTRINSIC_ATOMICS 1 85 #define EVO_ATOMIC_FENCE(MEM_ORDER) __sync_synchronize() 87 #define EVO_ATOMIC_FETCH_OP(OP, PTR, VAL, MEM_ORDER) __sync_fetch_and_ ## OP (PTR, VAL) 88 #define EVO_ATOMIC_OP_FETCH(OP, PTR, VAL, MEM_ORDER) __sync_ ## OP ## _and_fetch(PTR, VAL) 91 #if !EVO_INTRINSIC_ATOMICS 94 #define EVO_ATOMIC_PTRMATH 1 98 #if defined(EVO_ATOMIC_SAFE_STATICS) 101 #if defined(EVO_MSVC_YEAR) 102 #if EVO_MSVC_YEAR >= 2015 // No thread-safe static init until MSVC 2015 103 #define EVO_ATOMIC_SAFE_STATICS 1 105 #elif defined(EVO_CPP11) // C++11 requires thread-safe static init 106 #define EVO_ATOMIC_SAFE_STATICS 1 107 #elif defined(EVO_CLANG_VER) // clang 2.9+ 108 #if EVO_CLANG_VER >= 209 109 #define EVO_ATOMIC_SAFE_STATICS 1 111 #elif defined(EVO_GCC_VER) // gcc 4.3+ 112 #if EVO_GCC_VER >= 403 113 #define EVO_ATOMIC_SAFE_STATICS 1 117 #if !defined(EVO_ATOMIC_SAFE_STATICS) 122 #define EVO_ATOMIC_SAFE_STATICS 0 127 #if defined(EVO_MSVC_YEAR) && !EVO_INTRINSIC_ATOMICS 128 #pragma warning(push) 129 #pragma warning(disable:4800 4100) 139 #if defined(EVO_STD_ATOMIC) 159 #if !EVO_INTRINSIC_ATOMICS 160 #define EVO_TMP_ATOMIC_OP(CODE) { T val; mutex_.lock(); CODE; mutex_.unlock(); return val; } 171 #if defined(EVO_STD_ATOMIC) 173 #if defined(EVO_CLANG_VER) || defined(EVO_MSVC_YEAR) 197 #if !EVO_INTRINSIC_ATOMICS 201 #elif defined(EVO_GCC_ATOMICS) 202 __atomic_clear(&val_, mem_order);
210 #if !EVO_INTRINSIC_ATOMICS 212 EVO_TMP_ATOMIC_OP(val = val_; val_ = 1)
213 #elif defined(EVO_GCC_ATOMICS)
214 return __atomic_test_and_set(&val_, mem_order);
216 return !__sync_bool_compare_and_swap(&val_, 0, 1);
221 #if defined(EVO_GCC_ATOMICS) 260 #if !EVO_INTRINSIC_ATOMICS 309 #if defined(EVO_STD_ATOMIC) 333 { T oldval = cmpval;
return this->compare_exchange_strong(oldval, newval, mem_order_success, mem_order_failure); }
441 #if !EVO_INTRINSIC_ATOMICS 442 EVO_TMP_ATOMIC_OP(val = val_)
443 #elif defined(EVO_GCC_ATOMICS) 444 return __atomic_load_n(&val_, mem_order);
447 __sync_synchronize();
449 __sync_synchronize();
455 #if !EVO_INTRINSIC_ATOMICS 456 EVO_TMP_ATOMIC_OP(val = val_; val_ = num)
457 #elif defined(EVO_GCC_ATOMICS)
458 return __atomic_exchange_n(&val_, num, mem_order);
462 __sync_synchronize();
464 }
while (!__sync_bool_compare_and_swap(&val_, prev_val, num));
470 #if !EVO_INTRINSIC_ATOMICS 474 #elif defined(EVO_GCC_ATOMICS) 475 __atomic_store_n(&val_, num, mem_order);
478 __sync_synchronize();
482 This& operator=(T num) {
488 #if !EVO_INTRINSIC_ATOMICS 489 bool replaced =
false;
491 if (val_ == cmpval) {
497 #elif defined(EVO_GCC_ATOMICS) 498 return __atomic_compare_exchange_n(&val_, &cmpval, newval,
false, mem_order_success, mem_order_failure);
500 return __sync_bool_compare_and_swap(&val_, cmpval, newval);
504 #if EVO_INTRINSIC_ATOMICS 506 {
return EVO_ATOMIC_FETCH_OP(add, &val_, num, mem_order); }
509 {
return EVO_ATOMIC_FETCH_OP(sub, &val_, num, mem_order); }
512 {
return EVO_ATOMIC_FETCH_OP(and, &val_, num, mem_order); }
515 {
return EVO_ATOMIC_FETCH_OP(or, &val_, num, mem_order); }
518 {
return EVO_ATOMIC_FETCH_OP(xor, &val_, num, mem_order); }
552 { EVO_TMP_ATOMIC_OP(val = val_; val_ += (NumType)num) }
555 { EVO_TMP_ATOMIC_OP(val = val_; val_ -= (NumType)num) }
558 { EVO_TMP_ATOMIC_OP(val = val_; val_ &= (NumType)num) }
561 { EVO_TMP_ATOMIC_OP(val = val_; val_ |= (NumType)num) }
564 { EVO_TMP_ATOMIC_OP(val = val_; val_ ^= (NumType)num) }
567 { EVO_TMP_ATOMIC_OP(val = ++val_) }
570 { EVO_TMP_ATOMIC_OP(val = val_; ++val_) }
573 { EVO_TMP_ATOMIC_OP(val = --val_) }
576 { EVO_TMP_ATOMIC_OP(val = val_; --val_) }
579 { EVO_TMP_ATOMIC_OP(val = val_ += (NumType)num) }
582 { EVO_TMP_ATOMIC_OP(val = val_ -= (NumType)num) }
585 { EVO_TMP_ATOMIC_OP(val = val_ &= (NumType)num) }
588 { EVO_TMP_ATOMIC_OP(val = val_ |= (NumType)num) }
591 { EVO_TMP_ATOMIC_OP(val = val_ ^= (NumType)num) }
607 { this->store(num); }
614 {
return this->load(); }
623 {
return this->load(); }
632 {
return this->load(); }
638 {
return !this->load(); }
645 {
return (
this == &num || this->load() == num.
load()); }
652 {
return this->load() == num; }
659 {
return (
this != &num && this->load() != num.
load()); }
666 {
return this->load() != num; }
673 {
return this->load() < num; }
680 {
return this->load() <= num; }
687 {
return this->load() > num; }
694 {
return this->load() >= num; }
697 #if !EVO_INTRINSIC_ATOMICS 703 This& operator=(
const This&);
723 #if defined(EVO_TMP_ATOMIC_OP) 724 #undef EVO_TMP_ATOMIC_OP 727 #if defined(_MSC_VER) && !EVO_INTRINSIC_ATOMICS 766 { ptr_.store((T*)ptr); }
778 { ptr_.store(src.
ptr_); }
784 { ptr_.store(src.
ptr_); }
791 { ptr_.store(src.
ptr_.
load());
return *
this; }
798 { ptr_.store(src.
ptr_);
return *
this; }
805 { ptr_.store(src.
ptr_);
return *
this; }
812 { ptr_.store(ptr);
return *
this; }
819 { ptr_.store((T*)ptr);
return *
this; }
825 { ptr_.store(NULL);
return *
this; }
833 {
return ptr_.exchange(NULL); }
839 #if defined(EVO_ATOMIC_PTRMATH) 842 return ptr_ += (T*)
sizeof(T);
850 #if defined(EVO_ATOMIC_PTRMATH) 853 return ptr_.fetch_add((T*)
sizeof(T));
862 #if defined(EVO_STD_ATOMIC) 864 #elif defined(EVO_ATOMIC_PTRMATH) 867 ptr_ += (T*)(count *
sizeof(T));
876 #if defined(EVO_ATOMIC_PTRMATH) 879 return ptr_ -= (T*)
sizeof(T);
887 #if defined(EVO_ATOMIC_PTRMATH) 890 return ptr_.fetch_sub((T*)
sizeof(T));
899 #if defined(EVO_STD_ATOMIC) 901 #elif defined(EVO_ATOMIC_PTRMATH) 904 ptr_ -= (T*)(count *
sizeof(T));
909 using Base::operator==;
910 using Base::operator!=;
911 using Base::operator<;
912 using Base::operator<=;
913 using Base::operator>;
914 using Base::operator>=;
921 {
return ptr_.load() == ptr.
ptr_; }
928 {
return ptr_.load() != ptr.
ptr_; }
935 {
return ptr_.load() < ptr.
ptr_; }
942 {
return ptr_.load() <= ptr.
ptr_; }
949 {
return ptr_.load() > ptr.
ptr_; }
956 {
return ptr_.load() >= ptr.
ptr_; }
992 { ptr_.store((T*)ptr); }
1004 { ptr_.store(src.
ptr_); }
1010 { ptr_.store(src.
ptr_); }
1017 { ptr_.store(src.
ptr_.
load());
return *
this; }
1024 { ptr_.store(src.
ptr_);
return *
this; }
1031 { ptr_.store(src.
ptr_);
return *
this; }
1038 { ptr_.store(ptr);
return *
this; }
1045 { ptr_.store((T*)ptr);
return *
this; }
1051 { ptr_.store(NULL);
return *
this; }
1059 {
return ptr_.exchange(NULL); }
1065 #if defined(EVO_ATOMIC_PTRMATH) 1068 return ptr_ += (T*)
sizeof(T);
1076 #if defined(EVO_ATOMIC_PTRMATH) 1079 return ptr_.fetch_add((T*)
sizeof(T));
1088 #if defined(EVO_STD_ATOMIC) 1090 #elif defined(EVO_ATOMIC_PTRMATH) 1093 ptr_ += (T*)(count *
sizeof(T));
1102 #if defined(EVO_ATOMIC_PTRMATH) 1105 return ptr_ -= (T*)
sizeof(T);
1113 #if defined(EVO_ATOMIC_PTRMATH) 1116 return ptr_.fetch_sub((T*)
sizeof(T));
1125 #if defined(EVO_STD_ATOMIC) 1127 #elif defined(EVO_ATOMIC_PTRMATH) 1130 ptr_ -= (T*)(count *
sizeof(T));
1135 using Base::operator==;
1136 using Base::operator!=;
1137 using Base::operator<;
1138 using Base::operator<=;
1139 using Base::operator>;
1140 using Base::operator>=;
1147 {
return ptr_.load() == ptr.
ptr_; }
1154 {
return ptr_.load() != ptr.
ptr_; }
1161 {
return ptr_.load() < ptr.
ptr_; }
1168 {
return ptr_.load() <= ptr.
ptr_; }
1175 {
return ptr_.load() > ptr.
ptr_; }
1182 {
return ptr_.load() >= ptr.
ptr_; }
1194 {
return ptr1.
ptr_ == ptr2.ptr_.load(); }
1203 {
return ptr1.
ptr_ != ptr2.ptr_.load(); }
1212 {
return ptr1.
ptr_ < ptr2.ptr_.load(); }
1221 {
return ptr1.
ptr_ <= ptr2.ptr_.load(); }
1230 {
return ptr1.
ptr_ > ptr2.ptr_.load(); }
1239 {
return ptr1.
ptr_ >= ptr2.ptr_.load(); }
bool operator>=(T num) const
Compare whether current value is greater than or equal to number.
Definition: atomic.h:693
bool operator<(T num) const
Compare whether current value is less than number.
Definition: atomic.h:672
AtomicPtr(const Base &src)
Copy constructor to reference pointer.
Definition: atomic.h:777
AtomicPtr(T *ptr)
Constructor.
Definition: atomic.h:759
AtomicPtr< T > This
This type.
Definition: atomic.h:748
Atomic< long > AtomicLong
Atomic signed long.
Definition: atomic.h:710
T * operator--(int)
Postfix decrement operator.
Definition: atomic.h:886
AtomicPtr(const T *ptr)
Constructor.
Definition: atomic.h:765
Atomic()
Constructor, initializes with 0.
Definition: atomic.h:600
This & operator=(T num)
Store new value.
Definition: atomic.h:319
Atomic signalling flag.
Definition: atomic.h:172
Atomic integer type.
Definition: atomic.h:311
#define EVO_ATOMIC_SYNC
Full sync (sequentially consistent) memory barrier.
Definition: atomic.h:36
This & operator=(const This &src)
Copy/Assignment operator.
Definition: atomic.h:790
bool test_and_set(MemOrder mem_order=std::memory_order_seq_cst)
Atomically set flag (to true) and return the previous value.
PtrBase< T, Atomic< T * > > Base
Base type.
Definition: atomic.h:749
Static conditional type.
Definition: meta.h:134
T * operator++(int)
Prefix increment operator.
Definition: atomic.h:849
Atomic< ulongl > AtomicULongL
Atomic unsigned long long.
Definition: atomic.h:713
This & operator=(const T *ptr)
Assignment operator for raw pointer.
Definition: atomic.h:818
Definition: systhread.h:165
T * operator--()
Prefix decrement operator.
Definition: atomic.h:875
Atomic< int32 > AtomicInt32
Atomic 32-bit signed int.
Definition: atomic.h:715
This & operator-=(int count)
Decrement by count operator.
Definition: atomic.h:898
Evo implementation detail for system portability – this is included by most Evo headers, include this via: include <evo/type.h>.
bool operator!() const
Negation operator checks if NULL/false (0).
Definition: atomic.h:637
Atomic dumb pointer to single object.
Definition: atomic.h:743
PtrBase< T > PtrBaseT
Managed pointer base type.
Definition: atomic.h:750
bool operator!=(T num) const
Compare whether current value is not equal to number.
Definition: atomic.h:665
bool operator==(const PtrBaseT &ptr) const
Equality operator.
Definition: atomic.h:920
bool operator>=(const PtrBase< T > &ptr1, const PtrBase< T, Atomic< T *> > &ptr2)
Greater-than-or-equals operator for managed pointer base and atomic pointer base. ...
Definition: atomic.h:1238
AtomicFlag()
Definition: atomic.h:174
#define EVO_ATOMIC_FENCE(MEM_ORDER)
Sets a memory fence/barrier.
Definition: atomic.h:52
Evo system threads implementation.
const T operator->() const
Member access operator (const).
Definition: atomic.h:622
Atomic< int64 > AtomicInt64
Atomic 64-bit signed int.
Definition: atomic.h:717
bool operator>=(const PtrBaseT &ptr) const
Greater-than-or-equals operator.
Definition: atomic.h:955
bool operator>(T num) const
Compare whether current value is greater than number.
Definition: atomic.h:686
This & operator=(T *ptr)
Assignment operator for raw pointer.
Definition: atomic.h:811
AtomicPtr< T[]> This
This type.
Definition: atomic.h:974
void clear(MemOrder mem_order=std::memory_order_seq_cst)
Clear flag (set to false).
bool operator!=(const This &num) const
Compare whether current value is not equal to number.
Definition: atomic.h:658
bool compare_set(T cmpval, T newval, MemOrder mem_order_success=std::memory_order_seq_cst, MemOrder mem_order_failure=std::memory_order_acquire)
Compare and set, storing new value if comparison matches.
Definition: atomic.h:332
Safe bool base class.
Definition: type.h:73
bool operator==(const PtrBase< T > &ptr1, const PtrBase< T, Atomic< T *> > &ptr2)
Equality operator for managed pointer base and atomic pointer base.
Definition: atomic.h:1193
This & clear()
Clear pointer, setting as null.
Definition: atomic.h:824
void sleeplock(ulong ms=1)
Spin-lock flag with a sleep.
Definition: atomic.h:247
Atomic dumb pointer to array.
Definition: atomic.h:969
AtomicPtr(const PtrBaseT &src)
Copy constructor to reference pointer.
Definition: atomic.h:783
bool operator!=(const PtrBaseT &ptr) const
Inequality operator.
Definition: atomic.h:927
#define EVO_ATOMIC_ACQUIRE
Start "acquire" memory ordering barrier, usually followed by a matching "release" barrier...
Definition: atomic.h:27
bool operator<=(const PtrBaseT &ptr) const
Less-than-or-equals operator.
Definition: atomic.h:941
bool operator==(T num) const
Compare whether current value is equal to number.
Definition: atomic.h:651
T * detach()
Detach and return pointer.
Definition: atomic.h:832
bool operator!=(const PtrBase< T > &ptr1, const PtrBase< T, Atomic< T *> > &ptr2)
Inequality operator for managed pointer base and atomic pointer base.
Definition: atomic.h:1202
bool operator>(const PtrBaseT &ptr) const
Greater-than operator.
Definition: atomic.h:948
Atomic< T > This
This type.
Definition: atomic.h:313
Atomic< int > AtomicInt
Atomic signed int.
Definition: atomic.h:708
AtomicPtr()
Default constructor sets as NULL.
Definition: atomic.h:753
void lock()
Spin-lock flag.
Definition: atomic.h:234
Evo C++ Library namespace.
Definition: alg.h:11
#define EVO_ATOMIC_RELEASE
Release (end) memory ordering barrier started with "consume" or "acquire" barrier.
Definition: atomic.h:30
std::memory_order MemOrder
Atomic memory order (fence) type.
Definition: atomic.h:153
Atomic< ulong > AtomicULong
Atomic unsigned long.
Definition: atomic.h:711
Atomic(T num)
Constructor.
Definition: atomic.h:606
Atomic< uint32 > AtomicUInt32
Atomic 32-bit unsigned int.
Definition: atomic.h:716
void unlock()
Spin-unlock flag.
Definition: atomic.h:256
bool sleepms(ulong msec)
Sleep for number of milliseconds.
Definition: sys.h:654
P ptr_
Pointer.
Definition: type.h:1566
T operator->()
Member access operator.
Definition: atomic.h:631
Atomic< longl > AtomicLongL
Atomic signed long long.
Definition: atomic.h:712
This & operator=(const Base &src)
Assignment operator to reference pointer.
Definition: atomic.h:797
T * operator++()
Prefix increment operator.
Definition: atomic.h:838
bool operator>(const PtrBase< T > &ptr1, const PtrBase< T, Atomic< T *> > &ptr2)
Greater-than operator for managed pointer base and atomic pointer base.
Definition: atomic.h:1229
Base managed pointer.
Definition: type.h:1562
bool operator==(const This &num) const
Compare whether current value is equal to number.
Definition: atomic.h:644
bool operator<(const PtrBaseT &ptr) const
Less-than operator.
Definition: atomic.h:934
T load(MemOrder mem_order=std::memory_order_seq_cst) const
Load and return current value.
Atomic< uint > AtomicUInt
Atomic unsigned int.
Definition: atomic.h:709
This & operator+=(int count)
Increment by count operator.
Definition: atomic.h:861
bool operator<=(T num) const
Compare whether current value is less than or equal to number.
Definition: atomic.h:679
AtomicPtr(const This &src)
Copy constructor.
Definition: atomic.h:771
Evo basic types and traits.
This & operator=(const PtrBaseT &src)
Assignment operator to reference pointer.
Definition: atomic.h:804
Atomic< uint64 > AtomicUInt64
Atomic 64-bit unsigned int.
Definition: atomic.h:718