11#pragma once
22
3+ #include < conc/atomic.hpp>
4+
35#include < stdx/bit.hpp>
46#include < stdx/bitset.hpp>
57#include < stdx/compiler.hpp>
@@ -22,19 +24,22 @@ template <auto Size,
2224 typename StorageElem = decltype (smallest_uint<to_underlying(Size)>())>
2325class atomic_bitset {
2426 constexpr static std::size_t N = to_underlying(Size);
25- using elem_t = StorageElem;
27+
28+ using elem_t = atomic::atomic_type_t <StorageElem>;
29+ constexpr static auto alignment = atomic::alignment_of<StorageElem>;
30+
2631 static_assert (std::is_unsigned_v<elem_t >,
2732 " Storage element for atomic_bitset must be an unsigned type" );
2833
2934 constexpr static auto bit = elem_t {1U };
3035
3136 static_assert (N <= std::numeric_limits<elem_t >::digits,
3237 " atomic_bitset is limited to a single storage element" );
33- std::atomic< elem_t > storage{};
38+ alignas (alignment) elem_t storage{};
3439
3540 constexpr static auto mask = bit_mask<elem_t , N - 1 >();
36- elem_t salient_value (std::memory_order order) const {
37- return storage. load (order) & mask;
41+ auto salient_value (std::memory_order order) const -> elem_t {
42+ return atomic:: load (storage, order) & mask;
3843 }
3944
4045 [[nodiscard]] static constexpr auto value_from_string (std::string_view str,
@@ -88,46 +93,44 @@ class atomic_bitset {
8893 " Conversion must be to an unsigned integral type or enum!" );
8994 static_assert (N <= std::numeric_limits<U>::digits,
9095 " atomic_bitset must fit within T" );
91- return static_cast <T>(storage. load (order));
96+ return static_cast <T>(salient_value (order));
9297 }
9398
9499 [[nodiscard]] auto
95- to_natural (std::memory_order order = std::memory_order_seq_cst) const {
96- return storage.load (order);
100+ to_natural (std::memory_order order = std::memory_order_seq_cst) const
101+ -> StorageElem {
102+ return static_cast <StorageElem>(salient_value (order));
97103 }
98104
99- operator bitset_t () const { return bitset_t {storage.load ()}; }
105+ operator bitset_t () const {
106+ return bitset_t {salient_value (std::memory_order_seq_cst)};
107+ }
100108
101109 auto load (std::memory_order order = std::memory_order_seq_cst) const
102110 -> bitset_t {
103- return bitset_t {storage. load (order)};
111+ return bitset_t {salient_value (order)};
104112 }
105113 auto store (bitset_t b,
106114 std::memory_order order = std::memory_order_seq_cst) {
107- storage. store (b.template to <elem_t >(), order);
115+ atomic:: store (storage, b.template to <elem_t >(), order);
108116 }
109117
110118 constexpr static std::integral_constant<std::size_t , N> size{};
111119
112- constexpr static std::bool_constant<
113- std::atomic<elem_t >::is_always_lock_free>
114- is_always_lock_free{};
115-
116120 template <typename T> [[nodiscard]] auto operator [](T idx) const -> bool {
117- auto const pos = static_cast <std::size_t >(to_underlying (idx));
118- return (salient_value (std::memory_order_seq_cst) & (bit << pos)) != 0 ;
121+ return load ()[idx];
119122 }
120123
121124 template <typename T>
122125 auto set (T idx, bool value = true ,
123126 std::memory_order order = std::memory_order_seq_cst) -> bitset_t {
124127 auto const pos = static_cast <std::size_t >(to_underlying (idx));
125128 if (value) {
126- return bitset_t {
127- storage. fetch_or ( static_cast <elem_t >(bit << pos), order)};
129+ return bitset_t {atomic::fetch_or (
130+ storage, static_cast <elem_t >(bit << pos), order)};
128131 }
129- return bitset_t {
130- storage. fetch_and ( static_cast <elem_t >(~(bit << pos)), order)};
132+ return bitset_t {atomic::fetch_and (
133+ storage, static_cast <elem_t >(~(bit << pos)), order)};
131134 }
132135
133136 auto set (lsb_t lsb, msb_t msb, bool value = true ,
@@ -136,9 +139,9 @@ class atomic_bitset {
136139 auto const m = to_underlying (msb);
137140 auto const shifted_value = bit_mask<elem_t >(m, l);
138141 if (value) {
139- return bitset_t {storage. fetch_or (shifted_value, order)};
142+ return bitset_t {atomic:: fetch_or (storage, shifted_value, order)};
140143 }
141- return bitset_t {storage. fetch_and (~shifted_value, order)};
144+ return bitset_t {atomic:: fetch_and (storage, ~shifted_value, order)};
142145 }
143146
144147 auto set (lsb_t lsb, length_t len, bool value = true ,
@@ -150,18 +153,19 @@ class atomic_bitset {
150153
151154 auto set (std::memory_order order = std::memory_order_seq_cst)
152155 LIFETIMEBOUND -> atomic_bitset & {
153- storage. store (mask, order);
156+ atomic:: store (storage, mask, order);
154157 return *this ;
155158 }
156159
157160 template <typename T> auto reset (T idx) -> bitset_t {
158161 auto const pos = static_cast <std::size_t >(to_underlying (idx));
159- return bitset_t {storage.fetch_and (static_cast <elem_t >(~(bit << pos)))};
162+ return bitset_t {
163+ atomic::fetch_and (storage, static_cast <elem_t >(~(bit << pos)))};
160164 }
161165
162166 auto reset (std::memory_order order = std::memory_order_seq_cst)
163167 LIFETIMEBOUND -> atomic_bitset & {
164- storage. store (elem_t {}, order);
168+ atomic:: store (storage, elem_t {}, order);
165169 return *this ;
166170 }
167171
@@ -182,11 +186,11 @@ class atomic_bitset {
182186 std::memory_order order = std::memory_order_seq_cst) -> bitset_t {
183187 auto const pos = static_cast <std::size_t >(to_underlying (idx));
184188 return bitset_t {
185- storage. fetch_xor (static_cast <elem_t >(bit << pos), order)};
189+ atomic:: fetch_xor (storage, static_cast <elem_t >(bit << pos), order)};
186190 }
187191
188192 auto flip (std::memory_order order = std::memory_order_seq_cst) -> bitset_t {
189- return bitset_t {storage. fetch_xor (mask, order)};
193+ return bitset_t {atomic:: fetch_xor (storage, mask, order)};
190194 }
191195
192196 [[nodiscard]] auto
0 commit comments