-
Notifications
You must be signed in to change notification settings - Fork 191
Expand file tree
/
Copy pathis_atomic.hpp
More file actions
131 lines (106 loc) · 3.76 KB
/
Copy pathis_atomic.hpp
File metadata and controls
131 lines (106 loc) · 3.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#ifndef RFL_ATOMIC_ISATOMIC_HPP_
#define RFL_ATOMIC_ISATOMIC_HPP_
#include <array>
#include <atomic>
#include <type_traits>
#include "../NamedTuple.hpp"
#include "../Tuple.hpp"
#include "../named_tuple_t.hpp"
#include "../to_view.hpp"
namespace rfl::atomic {
template <class T>
struct is_atomic;
template <class T>
struct is_atomic {
static constexpr bool value = false;
using RemoveAtomicT = T;
static void set(RemoveAtomicT&& val, T* _t) { *_t = std::forward<T>(val); };
};
template <class T>
struct is_atomic<std::atomic<T>> {
static constexpr bool value = true;
using RemoveAtomicT = T;
static void set(RemoveAtomicT&& val, std::atomic<T>* _t) {
_t->store(std::forward<RemoveAtomicT>(val), std::memory_order_relaxed);
};
};
template <>
struct is_atomic<std::atomic_flag> {
static constexpr bool value = true;
using RemoveAtomicT = bool;
static void set(RemoveAtomicT&& val, std::atomic_flag* _t) {
if (val) {
_t->test_and_set(std::memory_order_relaxed);
} else {
_t->clear(std::memory_order_relaxed);
}
}
};
template <class T, size_t N>
struct is_atomic<std::array<T, N>> {
using Type = std::remove_cvref_t<T>;
static constexpr bool value = is_atomic<Type>::value;
using RemoveAtomicT = std::array<typename is_atomic<Type>::RemoveAtomicT, N>;
static void set(RemoveAtomicT&& val, std::array<T, N>* _t) {
for (size_t i = 0; i < N; ++i) {
is_atomic<T>::set(
std::forward<typename is_atomic<Type>::RemoveAtomicT>(val[i]),
&((*_t)[i]));
}
}
};
template <class T, size_t N>
struct is_atomic<T[N]> {
using Type = std::remove_cvref_t<T>;
static constexpr bool value = is_atomic<Type>::value;
using RemoveAtomicT = std::array<typename is_atomic<Type>::RemoveAtomicT, N>;
static void set(RemoveAtomicT&& val, T (*_t)[N]) {
for (size_t i = 0; i < N; ++i) {
is_atomic<T>::set(
std::forward<typename is_atomic<Type>::RemoveAtomicT>(val[i]),
&((*_t)[i]));
}
}
};
template <class... Fields>
struct is_atomic<NamedTuple<Fields...>> {
static constexpr bool value =
(is_atomic<typename Fields::Type>::value || ...);
using RemoveAtomicT = NamedTuple<
rfl::Field<Fields::name_,
typename is_atomic<typename Fields::Type>::RemoveAtomicT>...>;
static void set(RemoveAtomicT&& val, NamedTuple<Fields...>* _t) {
(is_atomic<typename Fields::Type>::set(
std::forward<typename is_atomic<
std::remove_cvref_t<typename Fields::Type>>::RemoveAtomicT>(
val.template get<Fields::name_>()),
&(_t->template get<Fields::name_>())),
...);
}
};
template <class T>
requires(std::is_class_v<T> && std::is_aggregate_v<T>)
struct is_atomic<T> {
static constexpr bool value = is_atomic<named_tuple_t<T>>::value;
using RemoveAtomicT = typename is_atomic<named_tuple_t<T>>::RemoveAtomicT;
static void set(RemoveAtomicT&& val, T* _t) {
using Fields = typename named_tuple_t<T>::Fields;
const auto view = to_view(*_t);
const auto set_field = [&]<size_t _i>(std::integral_constant<size_t, _i>) {
using FieldType = typename rfl::tuple_element_t<_i, Fields>::Type;
using FieldRemoveAtomicT =
typename is_atomic<std::remove_cvref_t<FieldType>>::RemoveAtomicT;
is_atomic<std::remove_cvref_t<FieldType>>::set(
std::forward<FieldRemoveAtomicT>(val.template get<_i>()),
view.template get<_i>());
};
constexpr size_t num_fields = std::remove_cvref_t<decltype(view)>::size();
[&]<size_t... _is>(std::index_sequence<_is...>) {
(set_field(std::integral_constant<size_t, _is>{}), ...);
}(std::make_index_sequence<num_fields>{});
}
};
template <class T>
constexpr bool is_atomic_v = is_atomic<std::remove_cvref_t<T>>::value;
} // namespace rfl::atomic
#endif