29#ifndef ETL_ATOMIC_GCC_SYNC_INCLUDED
30#define ETL_ATOMIC_GCC_SYNC_INCLUDED
36#include "../static_assert.h"
43#if defined(ETL_COMPILER_ARM5)
44 #define ETL_USE_SYNC_BUILTINS
48#if defined(ETL_COMPILER_ARM6)
49 #if ETL_COMPILER_FULL_VERSION >= 40700
50 #define ETL_USE_ATOMIC_BUILTINS
52 #define ETL_USE_SYNC_BUILTINS
57#if defined(ETL_COMPILER_GCC)
58 #if ETL_COMPILER_FULL_VERSION >= 40700
59 #define ETL_USE_ATOMIC_BUILTINS
61 #define ETL_USE_SYNC_BUILTINS
66#if defined(ETL_COMPILER_CLANG)
67 #if ETL_COMPILER_FULL_VERSION >= 50000
68 #define ETL_USE_ATOMIC_BUILTINS
70 #define ETL_USE_SYNC_BUILTINS
76#if defined(ETL_USE_ATOMIC_BUILTINS)
78 #define ETL_BUILTIN_LOCK \
80 while (__atomic_test_and_set(&flag, etl::memory_order_seq_cst)) \
84 #define ETL_BUILTIN_UNLOCK \
86 __atomic_clear(&flag, etl::memory_order_seq_cst); \
94 typedef enum memory_order
96 memory_order_relaxed = __ATOMIC_RELAXED,
97 memory_order_consume = __ATOMIC_CONSUME,
98 memory_order_acquire = __ATOMIC_ACQUIRE,
99 memory_order_release = __ATOMIC_RELEASE,
100 memory_order_acq_rel = __ATOMIC_ACQ_REL,
101 memory_order_seq_cst = __ATOMIC_SEQ_CST
104 template <
bool Is_Always_Lock_Free>
107 static ETL_CONSTANT
bool is_always_lock_free = Is_Always_Lock_Free;
110 template <
bool Is_Always_Lock_Free>
111 ETL_CONSTANT
bool atomic_traits<Is_Always_Lock_Free>::is_always_lock_free;
116 template <typename T, bool integral_type = etl::is_integral<T>::value>
117 class atomic :
public atomic_traits<integral_type>
121 ETL_CONSTEXPR atomic()
126 ETL_CONSTEXPR atomic(T v)
139 T operator=(T v)
volatile
149 return __atomic_add_fetch(&value, 1, etl::memory_order_seq_cst);
152 T operator++()
volatile
154 return __atomic_add_fetch(&value, 1, etl::memory_order_seq_cst);
160 return __atomic_fetch_add(&value, 1, etl::memory_order_seq_cst);
163 T operator++(
int)
volatile
165 return __atomic_fetch_add(&value, 1, etl::memory_order_seq_cst);
171 return __atomic_sub_fetch(&value, 1, etl::memory_order_seq_cst);
174 T operator--()
volatile
176 return __atomic_sub_fetch(&value, 1, etl::memory_order_seq_cst);
182 return __atomic_fetch_sub(&value, 1, etl::memory_order_seq_cst);
185 T operator--(
int)
volatile
187 return __atomic_fetch_sub(&value, 1, etl::memory_order_seq_cst);
193 return __atomic_fetch_add(&value, v, etl::memory_order_seq_cst);
196 T operator+=(T v)
volatile
198 return __atomic_fetch_add(&value, v, etl::memory_order_seq_cst);
204 return __atomic_fetch_sub(&value, v, etl::memory_order_seq_cst);
207 T operator-=(T v)
volatile
209 return __atomic_fetch_sub(&value, v, etl::memory_order_seq_cst);
215 return __atomic_fetch_and(&value, v, etl::memory_order_seq_cst);
220 return __atomic_fetch_and(&value, v, etl::memory_order_seq_cst);
226 return __atomic_fetch_or(&value, v, etl::memory_order_seq_cst);
231 return __atomic_fetch_or(&value, v, etl::memory_order_seq_cst);
237 return __atomic_fetch_xor(&value, v, etl::memory_order_seq_cst);
242 return __atomic_fetch_xor(&value, v, etl::memory_order_seq_cst);
248 return __atomic_fetch_add(&value, 0, etl::memory_order_seq_cst);
251 operator T()
volatile const
253 return __atomic_fetch_add(&value, 0, etl::memory_order_seq_cst);
257 bool is_lock_free()
const
262 bool is_lock_free()
const volatile
268 void store(T v, etl::memory_order order = etl::memory_order_seq_cst)
270 __atomic_store_n(&value, v, order);
273 void store(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
275 __atomic_store_n(&value, v, order);
279 T load(etl::memory_order order = etl::memory_order_seq_cst)
const
281 return __atomic_load_n(&value, order);
284 T load(etl::memory_order order = etl::memory_order_seq_cst)
const volatile
286 return __atomic_load_n(&value, order);
290 T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst)
292 return __atomic_fetch_add(&value, v, order);
295 T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
297 return __atomic_fetch_add(&value, v, order);
301 T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst)
303 return __atomic_fetch_sub(&value, v, order);
306 T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
308 return __atomic_fetch_sub(&value, v, order);
312 T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst)
314 return __atomic_fetch_or(&value, v, order);
317 T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
319 return __atomic_fetch_or(&value, v, order);
323 T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst)
325 return __atomic_fetch_and(&value, v, order);
328 T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
330 return __atomic_fetch_and(&value, v, order);
334 T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst)
336 return __atomic_fetch_xor(&value, v, order);
339 T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
341 return __atomic_fetch_xor(&value, v, order);
345 T fetch_max(T v, etl::memory_order order = etl::memory_order_seq_cst)
351 if (compare_exchange_weak(old, v, order))
360 T fetch_max(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
366 if (compare_exchange_weak(old, v, order))
376 T fetch_min(T v, etl::memory_order order = etl::memory_order_seq_cst)
382 if (compare_exchange_weak(old, v, order))
391 T fetch_min(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
397 if (compare_exchange_weak(old, v, order))
407 T
exchange(T v, etl::memory_order order = etl::memory_order_seq_cst)
409 return __atomic_exchange_n(&value, v, order);
412 T
exchange(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
414 return __atomic_exchange_n(&value, v, order);
418 bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
420 return __atomic_compare_exchange_n(&value, &expected, desired,
true, order, order);
423 bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
volatile
425 return __atomic_compare_exchange_n(&value, &expected, desired,
true, order, order);
428 bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
430 return __atomic_compare_exchange_n(&value, &expected, desired,
true, success, failure);
433 bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
volatile
435 return __atomic_compare_exchange_n(&value, &expected, desired,
true, success, failure);
439 bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
441 return __atomic_compare_exchange_n(&value, &expected, desired,
false, order, order);
444 bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
volatile
446 return __atomic_compare_exchange_n(&value, &expected, desired,
false, order, order);
449 bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
451 return __atomic_compare_exchange_n(&value, &expected, desired,
false, success, failure);
454 bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
volatile
456 return __atomic_compare_exchange_n(&value, &expected, desired,
false, success, failure);
461 atomic& operator=(
const atomic&) ETL_DELETE;
462 atomic& operator=(
const atomic&)
volatile ETL_DELETE;
470 template <
typename T>
471 class atomic<T*,
false> :
public atomic_traits<true>
481 : value(uintptr_t(v))
493 T* operator=(T* v)
volatile
503 return reinterpret_cast<T*
>(__atomic_add_fetch(&value,
sizeof(T), etl::memory_order_seq_cst));
506 T* operator++()
volatile
508 return reinterpret_cast<T*
>(__atomic_add_fetch(&value,
sizeof(T), etl::memory_order_seq_cst));
514 return reinterpret_cast<T*
>(__atomic_fetch_add(&value,
sizeof(T), etl::memory_order_seq_cst));
517 T* operator++(
int)
volatile
519 return reinterpret_cast<T*
>(__atomic_fetch_add(&value,
sizeof(T), etl::memory_order_seq_cst));
525 return reinterpret_cast<T*
>(__atomic_sub_fetch(&value,
sizeof(T), etl::memory_order_seq_cst));
528 T* operator--()
volatile
530 return reinterpret_cast<T*
>(__atomic_sub_fetch(&value,
sizeof(T), etl::memory_order_seq_cst));
536 return reinterpret_cast<T*
>(__atomic_fetch_sub(&value,
sizeof(T), etl::memory_order_seq_cst));
539 T* operator--(
int)
volatile
541 return reinterpret_cast<T*
>(__atomic_fetch_sub(&value,
sizeof(T), etl::memory_order_seq_cst));
545 T* operator+=(ptrdiff_t v)
547 return reinterpret_cast<T*
>(
548 __atomic_fetch_add(&value,
static_cast<uintptr_t
>(v *
static_cast<ptrdiff_t
>(
sizeof(T))), etl::memory_order_seq_cst));
551 T* operator+=(ptrdiff_t v)
volatile
553 return reinterpret_cast<T*
>(
554 __atomic_fetch_add(&value,
static_cast<uintptr_t
>(v *
static_cast<ptrdiff_t
>(
sizeof(T))), etl::memory_order_seq_cst));
558 T* operator-=(ptrdiff_t v)
560 return reinterpret_cast<T*
>(
561 __atomic_fetch_sub(&value,
static_cast<uintptr_t
>(v *
static_cast<ptrdiff_t
>(
sizeof(T))), etl::memory_order_seq_cst));
564 T* operator-=(ptrdiff_t v)
volatile
566 return reinterpret_cast<T*
>(
567 __atomic_fetch_sub(&value,
static_cast<uintptr_t
>(v *
static_cast<ptrdiff_t
>(
sizeof(T))), etl::memory_order_seq_cst));
573 return reinterpret_cast<T*
>(__atomic_fetch_add(&value, 0, etl::memory_order_seq_cst));
576 operator T*()
volatile const
578 return reinterpret_cast<T*
>(__atomic_fetch_add(&value, 0, etl::memory_order_seq_cst));
582 bool is_lock_free()
const
587 bool is_lock_free()
const volatile
593 void store(T* v, etl::memory_order order = etl::memory_order_seq_cst)
595 __atomic_store_n(&value, uintptr_t(v), order);
598 void store(T* v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
600 __atomic_store_n(&value, uintptr_t(v), order);
604 T* load(etl::memory_order order = etl::memory_order_seq_cst)
const
606 return reinterpret_cast<T*
>(__atomic_load_n(&value, order));
609 T* load(etl::memory_order order = etl::memory_order_seq_cst)
const volatile
611 return reinterpret_cast<T*
>(__atomic_load_n(&value, order));
615 T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst)
617 return reinterpret_cast<T*
>(__atomic_fetch_add(&value,
static_cast<uintptr_t
>(v *
static_cast<ptrdiff_t
>(
sizeof(T))), order));
620 T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
622 return reinterpret_cast<T*
>(__atomic_fetch_add(&value,
static_cast<uintptr_t
>(v *
static_cast<ptrdiff_t
>(
sizeof(T))), order));
626 T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst)
628 return reinterpret_cast<T*
>(__atomic_fetch_sub(&value,
static_cast<uintptr_t
>(v *
static_cast<ptrdiff_t
>(
sizeof(T))), order));
631 T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
633 return reinterpret_cast<T*
>(__atomic_fetch_sub(&value,
static_cast<uintptr_t
>(v *
static_cast<ptrdiff_t
>(
sizeof(T))), order));
637 T*
exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst)
639 return reinterpret_cast<T*
>(__atomic_exchange_n(&value, uintptr_t(v), order));
642 T*
exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
644 return reinterpret_cast<T*
>(__atomic_exchange_n(&value, uintptr_t(v), order));
648 bool compare_exchange_weak(T*&
expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst)
650 uintptr_t expected_v = uintptr_t(
expected);
652 return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired),
true, order, order);
655 bool compare_exchange_weak(T*&
expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst)
volatile
657 uintptr_t expected_v = uintptr_t(
expected);
659 return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired),
true, order, order);
662 bool compare_exchange_weak(T*&
expected, T* desired, etl::memory_order success, etl::memory_order failure)
664 uintptr_t expected_v = uintptr_t(
expected);
666 return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired),
true, success, failure);
669 bool compare_exchange_weak(T*&
expected, T* desired, etl::memory_order success, etl::memory_order failure)
volatile
671 uintptr_t expected_v = uintptr_t(
expected);
673 return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired),
true, success, failure);
677 bool compare_exchange_strong(T*&
expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst)
679 uintptr_t expected_v = uintptr_t(
expected);
681 return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired),
false, order, order);
684 bool compare_exchange_strong(T*&
expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst)
volatile
686 uintptr_t expected_v = uintptr_t(
expected);
688 return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired),
false, order, order);
691 bool compare_exchange_strong(T*&
expected, T* desired, etl::memory_order success, etl::memory_order failure)
693 uintptr_t expected_v = uintptr_t(
expected);
695 return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired),
false, success, failure);
698 bool compare_exchange_strong(T*&
expected, T* desired, etl::memory_order success, etl::memory_order failure)
volatile
700 uintptr_t expected_v = uintptr_t(
expected);
702 return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired),
false, success, failure);
710 mutable uintptr_t value;
717 class atomic<bool, true> :
public atomic_traits<true>
721 ETL_CONSTEXPR atomic()
726 ETL_CONSTEXPR atomic(
bool v)
732 bool operator=(
bool v)
739 bool operator=(
bool v)
volatile
747 operator bool()
const
749 return static_cast<bool>(__atomic_fetch_add(&value, 0, etl::memory_order_seq_cst));
752 operator bool()
volatile const
754 return static_cast<bool>(__atomic_fetch_add(&value, 0, etl::memory_order_seq_cst));
758 bool is_lock_free()
const
763 bool is_lock_free()
const volatile
769 void store(
bool v, etl::memory_order order = etl::memory_order_seq_cst)
771 __atomic_store_n(&value,
char(v), order);
774 void store(
bool v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
776 __atomic_store_n(&value,
char(v), order);
780 bool load(etl::memory_order order = etl::memory_order_seq_cst)
const
782 return static_cast<bool>(__atomic_load_n(&value, order));
785 bool load(etl::memory_order order = etl::memory_order_seq_cst)
const volatile
787 return static_cast<bool>(__atomic_load_n(&value, order));
791 bool exchange(
bool v, etl::memory_order order = etl::memory_order_seq_cst)
793 return static_cast<bool>(__atomic_exchange_n(&value,
char(v), order));
796 bool exchange(
bool v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
798 return static_cast<bool>(__atomic_exchange_n(&value,
char(v), order));
802 bool compare_exchange_weak(
bool& expected,
bool desired, etl::memory_order order = etl::memory_order_seq_cst)
804 char expected_v = char(expected);
805 char desired_v = char(desired);
807 return __atomic_compare_exchange_n(&value, &expected_v, desired_v,
true, order, order);
810 bool compare_exchange_weak(
bool& expected,
bool desired, etl::memory_order order = etl::memory_order_seq_cst)
volatile
812 char expected_v = char(expected);
813 char desired_v = char(desired);
815 return __atomic_compare_exchange_n(&value, &expected_v, desired_v,
true, order, order);
818 bool compare_exchange_weak(
bool& expected,
bool desired, etl::memory_order success, etl::memory_order failure)
820 char expected_v = char(expected);
821 char desired_v = char(desired);
823 return __atomic_compare_exchange_n(&value, &expected_v, desired_v,
true, success, failure);
826 bool compare_exchange_weak(
bool& expected,
bool desired, etl::memory_order success, etl::memory_order failure)
volatile
828 char expected_v = char(expected);
829 char desired_v = char(desired);
831 return __atomic_compare_exchange_n(&value, &expected_v, desired_v,
true, success, failure);
835 bool compare_exchange_strong(
bool& expected,
bool desired, etl::memory_order order = etl::memory_order_seq_cst)
837 char expected_v = char(expected);
838 char desired_v = char(desired);
840 return __atomic_compare_exchange_n(&value, &expected_v, desired_v,
false, order, order);
843 bool compare_exchange_strong(
bool& expected,
bool desired, etl::memory_order order = etl::memory_order_seq_cst)
volatile
845 char expected_v = char(expected);
846 char desired_v = char(desired);
848 return __atomic_compare_exchange_n(&value, &expected_v, desired_v,
false, order, order);
851 bool compare_exchange_strong(
bool& expected,
bool desired, etl::memory_order success, etl::memory_order failure)
853 char expected_v = char(expected);
854 char desired_v = char(desired);
856 return __atomic_compare_exchange_n(&value, &expected_v, desired_v,
false, success, failure);
859 bool compare_exchange_strong(
bool& expected,
bool desired, etl::memory_order success, etl::memory_order failure)
volatile
861 char expected_v = char(expected);
862 char desired_v = char(desired);
864 return __atomic_compare_exchange_n(&value, &expected_v, desired_v,
false, success, failure);
869 atomic& operator=(
const atomic&) ETL_DELETE;
870 atomic& operator=(
const atomic&)
volatile ETL_DELETE;
879 template <
typename T>
880 class atomic<T, false> :
public atomic_traits<false>
884 ETL_STATIC_ASSERT((etl::is_trivially_copyable<T>::value),
"atomic<T> requires that T is trivially copyable");
885 ETL_STATIC_ASSERT((etl::is_copy_constructible<T>::value),
"atomic<T> requires that T is copy constructible");
886 ETL_STATIC_ASSERT((etl::is_copy_assignable<T>::value),
"atomic<T> requires that T is copy assignable");
887 ETL_STATIC_ASSERT((etl::is_move_constructible<T>::value),
"atomic<T> requires that T is move constructible");
888 ETL_STATIC_ASSERT((etl::is_move_assignable<T>::value),
"atomic<T> requires that T is move assignable");
889 ETL_STATIC_ASSERT((etl::is_same<T,
typename etl::remove_cv<T>::type>::value),
"atomic<T> requires that T is not const or volatile");
922 bool is_lock_free()
const
928 void store(T v, etl::memory_order order = etl::memory_order_seq_cst)
937 T load(etl::memory_order order = etl::memory_order_seq_cst)
const
948 T
exchange(T v, etl::memory_order order = etl::memory_order_seq_cst)
960 bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
966 if (memcmp(&value, &expected,
sizeof(T)) == 0)
980 bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
984 return compare_exchange_weak(expected, desired);
988 bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
991 return compare_exchange_weak(expected, desired);
994 bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
998 return compare_exchange_weak(expected, desired);
1003 atomic& operator=(
const atomic&) ETL_DELETE;
1004 atomic& operator=(
const atomic&)
volatile ETL_DELETE;
1010 #undef ETL_BUILTIN_LOCK
1011 #undef ETL_BUILTIN_UNLOCK
1015#if defined(ETL_USE_SYNC_BUILTINS)
1017 #define ETL_BUILTIN_LOCK \
1019 while (__sync_lock_test_and_set(&flag, 1U)) \
1023 #define ETL_BUILTIN_UNLOCK \
1025 __sync_lock_release(&flag); \
1033 typedef enum memory_order
1035 memory_order_relaxed,
1036 memory_order_consume,
1037 memory_order_acquire,
1038 memory_order_release,
1039 memory_order_acq_rel,
1040 memory_order_seq_cst
1043 template <
bool Is_Always_Lock_Free>
1044 struct atomic_traits
1046 static ETL_CONSTANT
bool is_always_lock_free = Is_Always_Lock_Free;
1049 template <
bool Is_Always_Lock_Free>
1050 ETL_CONSTANT
bool atomic_traits<Is_Always_Lock_Free>::is_always_lock_free;
1055 template <typename T, bool integral_type = etl::is_integral<T>::value>
1056 class atomic :
public atomic_traits<integral_type>
1060 ETL_STATIC_ASSERT(etl::is_integral<T>::value,
"Only integral types are supported");
1062 ETL_CONSTEXPR atomic()
1067 ETL_CONSTEXPR atomic(T v)
1080 T operator=(T v)
volatile
1090 return __sync_add_and_fetch(&value, 1);
1093 T operator++()
volatile
1095 return __sync_add_and_fetch(&value, 1);
1101 return __sync_fetch_and_add(&value, 1);
1104 T operator++(
int)
volatile
1106 return __sync_fetch_and_add(&value, 1);
1112 return __sync_sub_and_fetch(&value, 1);
1115 T operator--()
volatile
1117 return __sync_sub_and_fetch(&value, 1);
1123 return __sync_fetch_and_sub(&value, 1);
1126 T operator--(
int)
volatile
1128 return __sync_fetch_and_sub(&value, 1);
1134 return __sync_fetch_and_add(&value, v);
1137 T operator+=(T v)
volatile
1139 return __sync_fetch_and_add(&value, v);
1145 return __sync_fetch_and_sub(&value, v);
1148 T operator-=(T v)
volatile
1150 return __sync_fetch_and_sub(&value, v);
1156 return __sync_fetch_and_and(&value, v);
1161 return __sync_fetch_and_and(&value, v);
1167 return __sync_fetch_and_or(&value, v);
1172 return __sync_fetch_and_or(&value, v);
1178 return __sync_fetch_and_xor(&value, v);
1183 return __sync_fetch_and_xor(&value, v);
1189 return __sync_fetch_and_add(&value, 0);
1192 operator T()
volatile const
1194 return __sync_fetch_and_add(&value, 0);
1198 bool is_lock_free()
const
1203 bool is_lock_free()
const volatile
1209 void store(T v, etl::memory_order order = etl::memory_order_seq_cst)
1212 (void)__sync_lock_test_and_set(&value, v);
1215 void store(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1218 (void)__sync_lock_test_and_set(&value, v);
1222 T load(etl::memory_order order = etl::memory_order_seq_cst)
const
1225 return __sync_fetch_and_add(&value, 0);
1228 T load(etl::memory_order order = etl::memory_order_seq_cst)
const volatile
1231 return __sync_fetch_and_add(&value, 0);
1235 T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst)
1238 return __sync_fetch_and_add(&value, v);
1241 T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1244 return __sync_fetch_and_add(&value, v);
1248 T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst)
1251 return __sync_fetch_and_sub(&value, v);
1254 T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1257 return __sync_fetch_and_sub(&value, v);
1261 T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst)
1264 return __sync_fetch_and_or(&value, v);
1267 T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1270 return __sync_fetch_and_or(&value, v);
1274 T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst)
1277 return __sync_fetch_and_and(&value, v);
1280 T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1283 return __sync_fetch_and_and(&value, v);
1287 T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst)
1290 return __sync_fetch_and_xor(&value, v);
1293 T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1296 return __sync_fetch_and_xor(&value, v);
1300 T fetch_max(T v, etl::memory_order order = etl::memory_order_seq_cst)
1303 T old = load(order);
1307 if (compare_exchange_weak(old, v, order))
1316 T fetch_max(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1319 T old = load(order);
1323 if (compare_exchange_weak(old, v, order))
1333 T fetch_min(T v, etl::memory_order order = etl::memory_order_seq_cst)
1336 T old = load(order);
1340 if (compare_exchange_weak(old, v, order))
1349 T fetch_min(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1352 T old = load(order);
1356 if (compare_exchange_weak(old, v, order))
1366 T
exchange(T v, etl::memory_order order = etl::memory_order_seq_cst)
1369 return __sync_lock_test_and_set(&value, v);
1372 T
exchange(T v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1375 return __sync_lock_test_and_set(&value, v);
1379 bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
1382 T old = __sync_val_compare_and_swap(&value, expected, desired);
1384 if (old == expected)
1395 bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1398 T old = __sync_val_compare_and_swap(&value, expected, desired);
1400 if (old == expected)
1411 bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
1415 T old = __sync_val_compare_and_swap(&value, expected, desired);
1417 if (old == expected)
1428 bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
volatile
1432 T old = __sync_val_compare_and_swap(&value, expected, desired);
1434 if (old == expected)
1446 bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
1451 while (!compare_exchange_weak(old, desired))
1453 if (memcmp(&old, &expected,
sizeof(T)))
1463 bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1468 while (!compare_exchange_weak(old, desired))
1470 if (memcmp(&old, &expected,
sizeof(T)))
1480 bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
1486 while (!compare_exchange_weak(old, desired))
1488 if (memcmp(&old, &expected,
sizeof(T)))
1498 bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
volatile
1504 while (!compare_exchange_weak(old, desired))
1506 if (memcmp(&old, &expected,
sizeof(T)))
1518 atomic& operator=(
const atomic&) ETL_DELETE;
1519 atomic& operator=(
const atomic&)
volatile ETL_DELETE;
1521 mutable volatile T value;
1527 template <
typename T>
1528 class atomic<T*,
false> :
public atomic_traits<true>
1538 : value(uintptr_t(v))
1550 T* operator=(T* v)
volatile
1560 return reinterpret_cast<T*
>(__sync_add_and_fetch(&value,
sizeof(T)));
1563 T* operator++()
volatile
1565 return reinterpret_cast<T*
>(__sync_add_and_fetch(&value,
sizeof(T)));
1571 return reinterpret_cast<T*
>(__sync_fetch_and_add(&value,
sizeof(T)));
1574 T* operator++(
int)
volatile
1576 return reinterpret_cast<T*
>(__sync_fetch_and_add(&value,
sizeof(T)));
1582 return reinterpret_cast<T*
>(__sync_sub_and_fetch(&value,
sizeof(T)));
1585 T* operator--()
volatile
1587 return reinterpret_cast<T*
>(__sync_sub_and_fetch(&value,
sizeof(T)));
1593 return reinterpret_cast<T*
>(__sync_fetch_and_sub(&value,
sizeof(T)));
1596 T* operator--(
int)
volatile
1598 return reinterpret_cast<T*
>(__sync_fetch_and_sub(&value,
sizeof(T)));
1602 T* operator+=(ptrdiff_t v)
1604 return reinterpret_cast<T*
>(__sync_fetch_and_add(&value, v *
sizeof(T)));
1607 T* operator+=(ptrdiff_t v)
volatile
1609 return reinterpret_cast<T*
>(__sync_fetch_and_add(&value, v *
sizeof(T)));
1613 T* operator-=(ptrdiff_t v)
1615 return reinterpret_cast<T*
>(__sync_fetch_and_sub(&value, v *
sizeof(T)));
1618 T* operator-=(ptrdiff_t v)
volatile
1620 return reinterpret_cast<T*
>(__sync_fetch_and_sub(&value, v *
sizeof(T)));
1626 return reinterpret_cast<T*
>(__sync_fetch_and_add(&value, 0));
1629 operator T*()
volatile const
1631 return reinterpret_cast<T*
>(__sync_fetch_and_add(&value, 0));
1635 bool is_lock_free()
const
1640 bool is_lock_free()
const volatile
1646 void store(T* v, etl::memory_order order = etl::memory_order_seq_cst)
1648 __sync_lock_test_and_set(&value, uintptr_t(v));
1651 void store(T* v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1653 __sync_lock_test_and_set(&value, uintptr_t(v));
1657 T* load(etl::memory_order order = etl::memory_order_seq_cst)
const
1659 return reinterpret_cast<T*
>(__sync_fetch_and_add(&value, 0));
1662 T* load(etl::memory_order order = etl::memory_order_seq_cst)
const volatile
1664 return reinterpret_cast<T*
>(__sync_fetch_and_add(&value, 0));
1668 T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst)
1670 return reinterpret_cast<T*
>(__sync_fetch_and_add(&value, v));
1673 T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1675 return reinterpret_cast<T*
>(__sync_fetch_and_add(&value, v));
1679 T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst)
1681 return reinterpret_cast<T*
>(__sync_fetch_and_sub(&value, v));
1684 T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1686 return reinterpret_cast<T*
>(__sync_fetch_and_sub(&value, v));
1690 T*
exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst)
1692 return reinterpret_cast<T*
>(__sync_lock_test_and_set(&value, uintptr_t(v)));
1695 T*
exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1697 return reinterpret_cast<T*
>(__sync_lock_test_and_set(&value, uintptr_t(v)));
1701 bool compare_exchange_weak(T*&
expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst)
1703 T* old =
reinterpret_cast<T*
>(__sync_val_compare_and_swap(&value, uintptr_t(
expected), uintptr_t(desired)));
1716 bool compare_exchange_weak(T*&
expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1718 T* old =
reinterpret_cast<T*
>(__sync_val_compare_and_swap(&value, uintptr_t(
expected), uintptr_t(desired)));
1731 bool compare_exchange_weak(T*&
expected, T* desired, etl::memory_order success, etl::memory_order failure)
1733 T* old =
reinterpret_cast<T*
>(__sync_val_compare_and_swap(&value, uintptr_t(
expected), uintptr_t(desired)));
1746 bool compare_exchange_weak(T*&
expected, T* desired, etl::memory_order success, etl::memory_order failure)
volatile
1748 T* old =
reinterpret_cast<T*
>(__sync_val_compare_and_swap(&value, uintptr_t(
expected), uintptr_t(desired)));
1762 bool compare_exchange_strong(T*&
expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst)
1766 while (!compare_exchange_weak(old, desired))
1768 if (memcmp(&old, &
expected,
sizeof(T*)))
1778 bool compare_exchange_strong(T*&
expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1782 while (!compare_exchange_weak(old, desired))
1784 if (memcmp(&old, &
expected,
sizeof(T*)))
1794 bool compare_exchange_strong(T*&
expected, T* desired, etl::memory_order success, etl::memory_order failure)
1798 while (!compare_exchange_weak(old, desired))
1800 if (memcmp(&old, &
expected,
sizeof(T*)))
1810 bool compare_exchange_strong(T*&
expected, T* desired, etl::memory_order success, etl::memory_order failure)
volatile
1814 while (!compare_exchange_weak(old, desired))
1816 if (memcmp(&old, &
expected,
sizeof(T*)))
1831 mutable uintptr_t value;
1838 class atomic<bool, true> :
public atomic_traits<true>
1842 ETL_CONSTEXPR atomic()
1847 ETL_CONSTEXPR atomic(
bool v)
1853 bool operator=(
bool v)
1860 bool operator=(
bool v)
volatile
1868 operator bool()
const
1870 return static_cast<bool>(__sync_fetch_and_add(&value, 0));
1873 operator bool()
volatile const
1875 return static_cast<bool>(__sync_fetch_and_add(&value, 0));
1879 bool is_lock_free()
const
1884 bool is_lock_free()
const volatile
1890 void store(
bool v, etl::memory_order order = etl::memory_order_seq_cst)
1892 __sync_lock_test_and_set(&value,
char(v));
1895 void store(
bool v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1897 __sync_lock_test_and_set(&value,
char(v));
1901 bool load(etl::memory_order order = etl::memory_order_seq_cst)
const
1903 return static_cast<bool>(__sync_fetch_and_add(&value, 0));
1906 bool load(etl::memory_order order = etl::memory_order_seq_cst)
const volatile
1908 return static_cast<bool>(__sync_fetch_and_add(&value, 0));
1912 bool exchange(
bool v, etl::memory_order order = etl::memory_order_seq_cst)
1914 return static_cast<bool>(__sync_lock_test_and_set(&value,
char(v)));
1917 bool exchange(
bool v, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1919 return static_cast<bool>(__sync_lock_test_and_set(&value,
char(v)));
1923 bool compare_exchange_weak(
bool& expected,
bool desired, etl::memory_order order = etl::memory_order_seq_cst)
1925 bool old =
static_cast<bool>(__sync_val_compare_and_swap(&value,
char(expected),
char(desired)));
1927 if (old == expected)
1938 bool compare_exchange_weak(
bool& expected,
bool desired, etl::memory_order order = etl::memory_order_seq_cst)
volatile
1940 bool old =
static_cast<bool>(__sync_val_compare_and_swap(&value,
char(expected),
char(desired)));
1942 if (old == expected)
1953 bool compare_exchange_weak(
bool& expected,
bool desired, etl::memory_order success, etl::memory_order failure)
1955 bool old =
static_cast<bool>(__sync_val_compare_and_swap(&value,
char(expected),
char(desired)));
1957 if (old == expected)
1968 bool compare_exchange_weak(
bool& expected,
bool desired, etl::memory_order success, etl::memory_order failure)
volatile
1970 bool old =
static_cast<bool>(__sync_val_compare_and_swap(&value,
char(expected),
char(desired)));
1972 if (old == expected)
1984 bool compare_exchange_strong(
bool& expected,
bool desired, etl::memory_order order = etl::memory_order_seq_cst)
1986 bool old = expected;
1988 while (!compare_exchange_weak(old, desired))
1990 if (memcmp(&old, &expected,
sizeof(
bool)))
2000 bool compare_exchange_strong(
bool& expected,
bool desired, etl::memory_order order = etl::memory_order_seq_cst)
volatile
2002 bool old = expected;
2004 while (!compare_exchange_weak(old, desired))
2006 if (memcmp(&old, &expected,
sizeof(
bool)))
2016 bool compare_exchange_strong(
bool& expected,
bool desired, etl::memory_order success, etl::memory_order failure)
2018 bool old = expected;
2020 while (!compare_exchange_weak(old, desired))
2022 if (memcmp(&old, &expected,
sizeof(
bool)))
2032 bool compare_exchange_strong(
bool& expected,
bool desired, etl::memory_order success, etl::memory_order failure)
volatile
2034 bool old = expected;
2036 while (!compare_exchange_weak(old, desired))
2038 if (memcmp(&old, &expected,
sizeof(
bool)))
2050 atomic& operator=(
const atomic&) ETL_DELETE;
2051 atomic& operator=(
const atomic&)
volatile ETL_DELETE;
2060 template <
typename T>
2061 class atomic<T, false> :
public atomic_traits<false>
2065 ETL_STATIC_ASSERT((etl::is_trivially_copyable<T>::value),
"atomic<T> requires that T is trivially copyable");
2066 ETL_STATIC_ASSERT((etl::is_copy_constructible<T>::value),
"atomic<T> requires that T is copy constructible");
2067 ETL_STATIC_ASSERT((etl::is_copy_assignable<T>::value),
"atomic<T> requires that T is copy assignable");
2068 ETL_STATIC_ASSERT((etl::is_move_constructible<T>::value),
"atomic<T> requires that T is move constructible");
2069 ETL_STATIC_ASSERT((etl::is_move_assignable<T>::value),
"atomic<T> requires that T is move assignable");
2070 ETL_STATIC_ASSERT((etl::is_same<T,
typename etl::remove_cv<T>::type>::value),
"atomic<T> requires that T is not const or volatile");
2103 bool is_lock_free()
const
2109 void store(T v, etl::memory_order order = etl::memory_order_seq_cst)
2117 T load(etl::memory_order order = etl::memory_order_seq_cst)
const
2127 T
exchange(T v, etl::memory_order order = etl::memory_order_seq_cst)
2138 bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
2143 if (memcmp(&value, &expected,
sizeof(T)) == 0)
2157 bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
2159 return compare_exchange_weak(expected, desired);
2163 bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
2165 return compare_exchange_weak(expected, desired);
2168 bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
2170 return compare_exchange_weak(expected, desired);
2175 atomic& operator=(
const atomic&) ETL_DELETE;
2176 atomic& operator=(
const atomic&)
volatile ETL_DELETE;
2182 #undef ETL_SYNC_BUILTIN_LOCK
2183 #undef ETL_SYNC_BUILTIN_UNLOCK
2187 typedef etl::atomic<bool> atomic_bool;
2188 typedef etl::atomic<char> atomic_char;
2189 typedef etl::atomic<signed char> atomic_schar;
2190 typedef etl::atomic<unsigned char> atomic_uchar;
2191 typedef etl::atomic<short> atomic_short;
2192 typedef etl::atomic<unsigned short> atomic_ushort;
2193 typedef etl::atomic<int> atomic_int;
2194 typedef etl::atomic<unsigned int> atomic_uint;
2195 typedef etl::atomic<long> atomic_long;
2196 typedef etl::atomic<unsigned long> atomic_ulong;
2197 typedef etl::atomic<long long> atomic_llong;
2198 typedef etl::atomic<unsigned long long> atomic_ullong;
2199 typedef etl::atomic<wchar_t> atomic_wchar_t;
2200#if ETL_HAS_NATIVE_CHAR8_T
2201 typedef etl::atomic<char8_t> atomic_char8_t;
2203#if ETL_HAS_NATIVE_CHAR16_T
2204 typedef etl::atomic<char16_t> atomic_char16_t;
2206#if ETL_HAS_NATIVE_CHAR32_T
2207 typedef etl::atomic<char32_t> atomic_char32_t;
2209#if ETL_USING_8BIT_TYPES
2210 typedef etl::atomic<uint8_t> atomic_uint8_t;
2211 typedef etl::atomic<int8_t> atomic_int8_t;
2213 typedef etl::atomic<uint16_t> atomic_uint16_t;
2214 typedef etl::atomic<int16_t> atomic_int16_t;
2215 typedef etl::atomic<uint32_t> atomic_uint32_t;
2216 typedef etl::atomic<int32_t> atomic_int32_t;
2217#if ETL_USING_64BIT_TYPES
2218 typedef etl::atomic<uint64_t> atomic_uint64_t;
2219 typedef etl::atomic<int64_t> atomic_int64_t;
2221 typedef etl::atomic<int_least8_t> atomic_int_least8_t;
2222 typedef etl::atomic<uint_least8_t> atomic_uint_least8_t;
2223 typedef etl::atomic<int_least16_t> atomic_int_least16_t;
2224 typedef etl::atomic<uint_least16_t> atomic_uint_least16_t;
2225 typedef etl::atomic<int_least32_t> atomic_int_least32_t;
2226 typedef etl::atomic<uint_least32_t> atomic_uint_least32_t;
2227#if ETL_USING_64BIT_TYPES
2228 typedef etl::atomic<int_least64_t> atomic_int_least64_t;
2229 typedef etl::atomic<uint_least64_t> atomic_uint_least64_t;
2231 typedef etl::atomic<int_fast8_t> atomic_int_fast8_t;
2232 typedef etl::atomic<uint_fast8_t> atomic_uint_fast8_t;
2233 typedef etl::atomic<int_fast16_t> atomic_int_fast16_t;
2234 typedef etl::atomic<uint_fast16_t> atomic_uint_fast16_t;
2235 typedef etl::atomic<int_fast32_t> atomic_int_fast32_t;
2236 typedef etl::atomic<uint_fast32_t> atomic_uint_fast32_t;
2237#if ETL_USING_64BIT_TYPES
2238 typedef etl::atomic<int_fast64_t> atomic_int_fast64_t;
2239 typedef etl::atomic<uint_fast64_t> atomic_uint_fast64_t;
2241 typedef etl::atomic<intptr_t> atomic_intptr_t;
2242 typedef etl::atomic<uintptr_t> atomic_uintptr_t;
2243 typedef etl::atomic<size_t> atomic_size_t;
2244 typedef etl::atomic<ptrdiff_t> atomic_ptrdiff_t;
2245 typedef etl::atomic<intmax_t> atomic_intmax_t;
2246 typedef etl::atomic<uintmax_t> atomic_uintmax_t;
Definition atomic_std.h:54
Expected type.
Definition expected.h:257
T exchange(T &object, const T &new_value)
exchange (const)
Definition utility.h:498
etl::byte & operator^=(etl::byte &lhs, etl::byte rhs)
Exclusive or equals.
Definition byte.h:290
etl::byte & operator|=(etl::byte &lhs, etl::byte rhs)
Or equals.
Definition byte.h:274
etl::byte & operator&=(etl::byte &lhs, etl::byte rhs)
And equals.
Definition byte.h:282