44#include < stdx/bitset.hpp>
55#include < stdx/compiler.hpp>
66#include < stdx/concepts.hpp>
7+ #include < stdx/ct_string.hpp>
78#include < stdx/detail/bitset_common.hpp>
89#include < stdx/type_traits.hpp>
910#include < stdx/udls.hpp>
1718
1819namespace stdx {
1920inline namespace v1 {
20- namespace detail {
21- template <std::size_t N, typename StorageElem> class atomic_bitset {
22- constexpr static auto bit = StorageElem{1U };
21+ template <auto Size,
22+ typename StorageElem = decltype (smallest_uint<to_underlying(Size)>())>
23+ class atomic_bitset {
24+ constexpr static std::size_t N = to_underlying(Size);
25+ using elem_t = StorageElem;
26+ static_assert (std::is_unsigned_v<elem_t >,
27+ " Storage element for atomic_bitset must be an unsigned type" );
2328
24- static_assert (N <= std::numeric_limits<StorageElem>::digits,
29+ constexpr static auto bit = elem_t {1U };
30+
31+ static_assert (N <= std::numeric_limits<elem_t >::digits,
2532 " atomic_bitset is limited to a single storage element" );
26- static_assert (std::atomic<StorageElem>::is_always_lock_free,
27- " atomic_bitset must always be lock free" );
28- std::atomic<StorageElem> storage{};
33+ std::atomic<elem_t > storage{};
2934
30- constexpr static auto mask = bit_mask<StorageElem , N - 1 >();
31- StorageElem salient_value (std::memory_order order) const {
35+ constexpr static auto mask = bit_mask<elem_t , N - 1 >();
36+ elem_t salient_value (std::memory_order order) const {
3237 return storage.load (order) & mask;
3338 }
3439
35- [[nodiscard]] static constexpr auto
36- value_from_string (std::string_view str, std::size_t pos, std::size_t n,
37- char one) -> StorageElem {
38- StorageElem ret{};
40+ [[nodiscard]] static constexpr auto value_from_string (std::string_view str,
41+ std::size_t pos,
42+ std::size_t n,
43+ char one) -> elem_t {
44+ elem_t ret{};
3945 auto const len = std::min (n, str.size () - pos);
4046 auto const s = str.substr (pos, std::min (len, N));
4147 auto i = bit;
4248 for (auto it = std::rbegin (s); it != std::rend (s); ++it) {
4349 if (*it == one) {
4450 ret |= i;
4551 }
46- i = static_cast <StorageElem >(i << 1u );
52+ i = static_cast <elem_t >(i << 1u );
4753 }
4854 return ret;
4955 }
5056
51- using bitset_t = bitset<N, StorageElem >;
57+ using bitset_t = bitset<Size, elem_t >;
5258
5359 public:
5460 constexpr atomic_bitset () = default;
5561 constexpr explicit atomic_bitset (std::uint64_t value)
56- : storage{static_cast <StorageElem >(value & mask)} {}
62+ : storage{static_cast <elem_t >(value & mask)} {}
5763
5864 template <typename ... Bs>
5965 constexpr explicit atomic_bitset (place_bits_t , Bs... bs)
60- : storage{static_cast <StorageElem >(
61- (StorageElem {} | ... |
62- static_cast <StorageElem >(bit << to_underlying (bs))))} {}
66+ : storage{static_cast <elem_t >(
67+ (elem_t {} | ... |
68+ static_cast <elem_t >(bit << to_underlying (bs))))} {}
6369
6470 constexpr explicit atomic_bitset (all_bits_t ) : storage{mask} {}
6571
@@ -68,6 +74,11 @@ template <std::size_t N, typename StorageElem> class atomic_bitset {
6874 char one = ' 1' )
6975 : storage{value_from_string (str, pos, n, one)} {}
7076
77+ #if __cplusplus >= 202002L
78+ constexpr explicit atomic_bitset (ct_string<N + 1 > s)
79+ : atomic_bitset{static_cast <std::string_view>(s)} {}
80+ #endif
81+
7182 template <typename T>
7283 [[nodiscard]] auto
7384 to (std::memory_order order = std::memory_order_seq_cst) const -> T {
@@ -93,13 +104,13 @@ template <std::size_t N, typename StorageElem> class atomic_bitset {
93104 }
94105 auto store (bitset_t b,
95106 std::memory_order order = std::memory_order_seq_cst) {
96- storage.store (b.template to <StorageElem >(), order);
107+ storage.store (b.template to <elem_t >(), order);
97108 }
98109
99110 constexpr static std::integral_constant<std::size_t , N> size{};
100111
101112 constexpr static std::bool_constant<
102- std::atomic<StorageElem >::is_always_lock_free>
113+ std::atomic<elem_t >::is_always_lock_free>
103114 is_always_lock_free{};
104115
105116 template <typename T> [[nodiscard]] auto operator [](T idx) const -> bool {
@@ -113,17 +124,17 @@ template <std::size_t N, typename StorageElem> class atomic_bitset {
113124 auto const pos = static_cast <std::size_t >(to_underlying (idx));
114125 if (value) {
115126 return bitset_t {
116- storage.fetch_or (static_cast <StorageElem >(bit << pos), order)};
127+ storage.fetch_or (static_cast <elem_t >(bit << pos), order)};
117128 }
118129 return bitset_t {
119- storage.fetch_and (static_cast <StorageElem >(~(bit << pos)), order)};
130+ storage.fetch_and (static_cast <elem_t >(~(bit << pos)), order)};
120131 }
121132
122133 auto set (lsb_t lsb, msb_t msb, bool value = true ,
123134 std::memory_order order = std::memory_order_seq_cst) -> bitset_t {
124135 auto const l = to_underlying (lsb);
125136 auto const m = to_underlying (msb);
126- auto const shifted_value = bit_mask<StorageElem >(m, l);
137+ auto const shifted_value = bit_mask<elem_t >(m, l);
127138 if (value) {
128139 return bitset_t {storage.fetch_or (shifted_value, order)};
129140 }
@@ -145,13 +156,12 @@ template <std::size_t N, typename StorageElem> class atomic_bitset {
145156
146157 template <typename T> auto reset (T idx) -> bitset_t {
147158 auto const pos = static_cast <std::size_t >(to_underlying (idx));
148- return bitset_t {
149- storage.fetch_and (static_cast <StorageElem>(~(bit << pos)))};
159+ return bitset_t {storage.fetch_and (static_cast <elem_t >(~(bit << pos)))};
150160 }
151161
152162 auto reset (std::memory_order order = std::memory_order_seq_cst)
153163 LIFETIMEBOUND -> atomic_bitset & {
154- storage.store (StorageElem {}, order);
164+ storage.store (elem_t {}, order);
155165 return *this ;
156166 }
157167
@@ -172,7 +182,7 @@ template <std::size_t N, typename StorageElem> class atomic_bitset {
172182 std::memory_order order = std::memory_order_seq_cst) -> bitset_t {
173183 auto const pos = static_cast <std::size_t >(to_underlying (idx));
174184 return bitset_t {
175- storage.fetch_xor (static_cast <StorageElem >(bit << pos), order)};
185+ storage.fetch_xor (static_cast <elem_t >(bit << pos), order)};
176186 }
177187
178188 auto flip (std::memory_order order = std::memory_order_seq_cst) -> bitset_t {
@@ -198,10 +208,9 @@ template <std::size_t N, typename StorageElem> class atomic_bitset {
198208 return static_cast <std::size_t >(popcount (salient_value (order)));
199209 }
200210};
201- } // namespace detail
202211
203- template < auto N, typename StorageElem = void >
204- using atomic_bitset = detail:: atomic_bitset<
205- to_underlying (N), decltype (smallest_uint<to_underlying(N), StorageElem>())>;
212+ # if __cplusplus >= 202002L
213+ template <std:: size_t N> atomic_bitset (ct_string<N>) -> atomic_bitset<N - 1>;
214+ # endif
206215} // namespace v1
207216} // namespace stdx
0 commit comments