7#include <initializer_list>
10USERVER_NAMESPACE_BEGIN
14template <
typename Enum>
20template <
typename Enum>
23 using ValueType = std::underlying_type_t<Enum>;
25 constexpr Flags()
noexcept : Flags(Enum::kNone) {}
26 constexpr Flags(Enum)
noexcept;
27 constexpr Flags(std::initializer_list<Enum>)
noexcept;
29 constexpr explicit operator
bool()
const;
31 constexpr Flags& operator|=(Flags);
32 constexpr Flags& operator&=(Flags);
33 constexpr Flags& Clear(Flags);
35 constexpr Flags operator|(Flags)
const;
36 constexpr Flags operator&(Flags)
const;
38 constexpr bool operator==(Flags)
const;
39 constexpr bool operator!=(Flags)
const;
41 constexpr ValueType GetValue()
const;
42 constexpr void SetValue(ValueType value);
45 friend class AtomicFlags<Enum>;
50template <
typename Enum>
51constexpr Flags<Enum> operator|(Enum, Flags<Enum>);
53template <
typename Enum>
54constexpr Flags<Enum> operator&(Enum, Flags<Enum>);
56template <
typename Enum>
57constexpr bool operator==(Enum, Flags<Enum>);
59template <
typename Enum>
60constexpr bool operator!=(Enum, Flags<Enum>);
65template <
typename Enum>
66class AtomicFlags final {
68 using ValueType = std::underlying_type_t<Enum>;
70 constexpr AtomicFlags() : AtomicFlags(Enum::kNone) {}
71 constexpr explicit AtomicFlags(Enum);
72 constexpr AtomicFlags(std::initializer_list<Enum>);
74 explicit operator
bool()
const;
75 operator Flags<Enum>()
const;
76 Flags<Enum> Load(std::memory_order = std::memory_order_seq_cst)
const;
78 AtomicFlags& operator=(Flags<Enum>);
79 AtomicFlags& Store(Flags<Enum>, std::memory_order = std::memory_order_seq_cst);
80 Flags<Enum> Exchange(Flags<Enum>);
82 AtomicFlags& operator|=(Flags<Enum>);
83 AtomicFlags& operator&=(Flags<Enum>);
84 AtomicFlags& Clear(Flags<Enum>);
85 Flags<Enum> FetchOr(Flags<Enum>, std::memory_order = std::memory_order_seq_cst);
86 Flags<Enum> FetchAnd(Flags<Enum>, std::memory_order = std::memory_order_seq_cst);
87 Flags<Enum> FetchClear(Flags<Enum>, std::memory_order = std::memory_order_seq_cst);
88 bool CompareExchangeWeak(
89 Flags<Enum>& expected,
91 std::memory_order order = std::memory_order_seq_cst
93 bool CompareExchangeStrong(
94 Flags<Enum>& expected,
96 std::memory_order order = std::memory_order_seq_cst
98 bool CompareExchangeWeak(
99 Flags<Enum>& expected,
101 std::memory_order success,
102 std::memory_order failure
104 bool CompareExchangeStrong(
105 Flags<Enum>& expected,
107 std::memory_order success,
108 std::memory_order failure
111 Flags<Enum> operator|(Flags<Enum>)
const;
112 Flags<Enum> operator&(Flags<Enum>)
const;
114 bool operator==(Flags<Enum>)
const;
115 bool operator!=(Flags<Enum>)
const;
117 ValueType GetValue();
120 std::atomic<ValueType> value_;
123template <
typename Enum>
124Flags<Enum> operator|(Enum,
const AtomicFlags<Enum>&);
126template <
typename Enum>
127Flags<Enum> operator&(Enum,
const AtomicFlags<Enum>&);
129template <
typename Enum>
130bool operator==(Enum,
const AtomicFlags<Enum>&);
132template <
typename Enum>
133bool operator!=(Enum,
const AtomicFlags<Enum>&);
135template <
typename Enum>
136constexpr Flags<Enum>::Flags(Enum value)
noexcept : value_(
static_cast<ValueType>(value)) {}
138template <
typename Enum>
139constexpr Flags<Enum>::Flags(std::initializer_list<Enum> values)
noexcept : Flags() {
140 for (Enum value : values) {
145template <
typename Enum>
146constexpr Flags<Enum>::operator
bool()
const {
150template <
typename Enum>
151constexpr Flags<Enum>& Flags<Enum>::operator|=(Flags rhs) {
152 value_ |= rhs.value_;
156template <
typename Enum>
157constexpr Flags<Enum>& Flags<Enum>::operator&=(Flags rhs) {
158 value_ &= rhs.value_;
162template <
typename Enum>
163constexpr Flags<Enum>& Flags<Enum>::Clear(Flags flags) {
164 value_ &= ~flags.value_;
168template <
typename Enum>
169constexpr Flags<Enum> Flags<Enum>::operator|(Flags rhs)
const {
170 return Flags(*
this) |= rhs;
173template <
typename Enum>
174constexpr Flags<Enum> Flags<Enum>::operator&(Flags rhs)
const {
175 return Flags(*
this) &= rhs;
178template <
typename Enum>
179constexpr bool Flags<Enum>::operator==(Flags rhs)
const {
180 return value_ == rhs.value_;
183template <
typename Enum>
184constexpr bool Flags<Enum>::operator!=(Flags rhs)
const {
185 return !(*
this == rhs);
188template <
typename Enum>
189constexpr typename Flags<Enum>::ValueType Flags<Enum>::GetValue()
const {
193template <
typename Enum>
194constexpr void Flags<Enum>::SetValue(
typename Flags<Enum>::ValueType value) {
195 this->value_ = value;
198template <
typename Enum>
199constexpr Flags<Enum> operator|(Enum lhs, Flags<Enum> rhs) {
203template <
typename Enum>
204constexpr Flags<Enum> operator&(Enum lhs, Flags<Enum> rhs) {
208template <
typename Enum>
209constexpr bool operator==(Enum lhs, Flags<Enum> rhs) {
210 return rhs == Flags<Enum>{lhs};
213template <
typename Enum>
214constexpr bool operator!=(Enum lhs, Flags<Enum> rhs) {
215 return rhs != Flags<Enum>{lhs};
218template <
typename Enum>
219constexpr AtomicFlags<Enum>::AtomicFlags(Enum value) : value_(
static_cast<ValueType>(value)) {}
221template <
typename Enum>
222constexpr AtomicFlags<Enum>::AtomicFlags(std::initializer_list<Enum> values) : AtomicFlags(Enum(values)) {}
224template <
typename Enum>
225AtomicFlags<Enum>::operator
bool()
const {
229template <
typename Enum>
230AtomicFlags<Enum>::operator Flags<Enum>()
const {
234template <
typename Enum>
235Flags<Enum> AtomicFlags<Enum>::Load(std::memory_order order)
const {
236 return static_cast<Enum>(value_.load(order));
239template <
typename Enum>
240AtomicFlags<Enum>& AtomicFlags<Enum>::operator=(Flags<Enum> rhs) {
245template <
typename Enum>
246AtomicFlags<Enum>& AtomicFlags<Enum>::Store(Flags<Enum> rhs, std::memory_order order) {
247 value_.store(rhs.value_, order);
251template <
typename Enum>
252Flags<Enum> AtomicFlags<Enum>::Exchange(Flags<Enum> flags) {
253 return static_cast<Enum>(value_.exchange(flags.value_));
256template <
typename Enum>
257AtomicFlags<Enum>& AtomicFlags<Enum>::operator|=(Flags<Enum> rhs) {
262template <
typename Enum>
263AtomicFlags<Enum>& AtomicFlags<Enum>::operator&=(Flags<Enum> rhs) {
268template <
typename Enum>
269AtomicFlags<Enum>& AtomicFlags<Enum>::Clear(Flags<Enum> flags) {
274template <
typename Enum>
275Flags<Enum> AtomicFlags<Enum>::FetchOr(Flags<Enum> rhs, std::memory_order memory_order) {
276 return static_cast<Enum>(value_.fetch_or(rhs.value_, memory_order));
279template <
typename Enum>
280Flags<Enum> AtomicFlags<Enum>::FetchAnd(Flags<Enum> rhs, std::memory_order memory_order) {
281 return static_cast<Enum>(value_.fetch_and(rhs.value_, memory_order));
284template <
typename Enum>
285Flags<Enum> AtomicFlags<Enum>::FetchClear(Flags<Enum> flags, std::memory_order memory_order) {
286 return static_cast<Enum>(value_.fetch_and(~flags.value_, memory_order));
289template <
typename Enum>
290bool AtomicFlags<Enum>::CompareExchangeWeak(Flags<Enum>& expected, Flags<Enum> desired, std::memory_order order) {
291 auto expected_int = expected.GetValue();
292 const bool result = value_.compare_exchange_weak(expected_int, desired.GetValue(), order);
293 expected = Enum{expected_int};
297template <
typename Enum>
298bool AtomicFlags<Enum>::CompareExchangeStrong(Flags<Enum>& expected, Flags<Enum> desired, std::memory_order order) {
299 auto expected_int = expected.GetValue();
300 const bool result = value_.compare_exchange_strong(expected_int, desired.GetValue(), order);
301 expected = Enum{expected_int};
305template <
typename Enum>
306bool AtomicFlags<Enum>::CompareExchangeWeak(
307 Flags<Enum>& expected,
309 std::memory_order success,
310 std::memory_order failure
312 auto expected_int = expected.GetValue();
313 const bool result = value_.compare_exchange_weak(expected_int, desired.GetValue(), success, failure);
314 expected = Enum{expected_int};
318template <
typename Enum>
319bool AtomicFlags<Enum>::CompareExchangeStrong(
320 Flags<Enum>& expected,
322 std::memory_order success,
323 std::memory_order failure
325 auto expected_int = expected.GetValue();
326 const bool result = value_.compare_exchange_strong(expected_int, desired.GetValue(), success, failure);
327 expected = Enum{expected_int};
331template <
typename Enum>
332Flags<Enum> AtomicFlags<Enum>::operator|(Flags<Enum> rhs)
const {
333 return Flags<Enum>{*
this} |= rhs;
336template <
typename Enum>
337Flags<Enum> AtomicFlags<Enum>::operator&(Flags<Enum> rhs)
const {
338 return Flags<Enum>{*
this} &= rhs;
341template <
typename Enum>
342bool AtomicFlags<Enum>::operator==(Flags<Enum> rhs)
const {
343 return value_ == rhs.value_;
346template <
typename Enum>
347bool AtomicFlags<Enum>::operator!=(Flags<Enum> rhs)
const {
348 return !(*
this == rhs);
351template <
typename Enum>
352typename AtomicFlags<Enum>::ValueType AtomicFlags<Enum>::GetValue() {
353 return this->value_.load();
356template <
typename Enum>
357Flags<Enum> operator|(Enum lhs,
const AtomicFlags<Enum>& rhs) {
361template <
typename Enum>
362Flags<Enum> operator&(Enum lhs,
const AtomicFlags<Enum>& rhs) {
366template <
typename Enum>
367bool operator==(Enum lhs,
const AtomicFlags<Enum>& rhs) {
368 return rhs == Flags<Enum>{lhs};
371template <
typename Enum>
372bool operator!=(Enum lhs,
const AtomicFlags<Enum>& rhs) {
373 return rhs != Flags<Enum>{lhs};