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>,
80 std::memory_order = std::memory_order_seq_cst);
81 Flags<Enum> Exchange(Flags<Enum>);
83 AtomicFlags& operator|=(Flags<Enum>);
84 AtomicFlags& operator&=(Flags<Enum>);
85 AtomicFlags& Clear(Flags<Enum>);
86 Flags<Enum> FetchOr(Flags<Enum>,
87 std::memory_order = std::memory_order_seq_cst);
88 Flags<Enum> FetchAnd(Flags<Enum>,
89 std::memory_order = std::memory_order_seq_cst);
90 Flags<Enum> FetchClear(Flags<Enum>,
91 std::memory_order = std::memory_order_seq_cst);
92 bool CompareExchangeWeak(Flags<Enum>& expected, Flags<Enum> desired,
93 std::memory_order order = std::memory_order_seq_cst);
94 bool CompareExchangeStrong(
95 Flags<Enum>& expected, Flags<Enum> desired,
96 std::memory_order order = std::memory_order_seq_cst);
97 bool CompareExchangeWeak(Flags<Enum>& expected, Flags<Enum> desired,
98 std::memory_order success,
99 std::memory_order failure);
100 bool CompareExchangeStrong(Flags<Enum>& expected, Flags<Enum> desired,
101 std::memory_order success,
102 std::memory_order failure);
104 Flags<Enum> operator|(Flags<Enum>)
const;
105 Flags<Enum> operator&(Flags<Enum>)
const;
107 bool operator==(Flags<Enum>)
const;
108 bool operator!=(Flags<Enum>)
const;
110 ValueType GetValue();
113 std::atomic<ValueType> value_;
116template <
typename Enum>
117Flags<Enum> operator|(Enum,
const AtomicFlags<Enum>&);
119template <
typename Enum>
120Flags<Enum> operator&(Enum,
const AtomicFlags<Enum>&);
122template <
typename Enum>
123bool operator==(Enum,
const AtomicFlags<Enum>&);
125template <
typename Enum>
126bool operator!=(Enum,
const AtomicFlags<Enum>&);
128template <
typename Enum>
129constexpr Flags<Enum>::Flags(Enum value)
noexcept
130 : value_(
static_cast<ValueType>(value)) {}
132template <
typename Enum>
133constexpr Flags<Enum>::Flags(std::initializer_list<Enum> values)
noexcept
135 for (Enum value : values) {
140template <
typename Enum>
141constexpr Flags<Enum>::operator
bool()
const {
145template <
typename Enum>
146constexpr Flags<Enum>& Flags<Enum>::operator|=(Flags rhs) {
147 value_ |= rhs.value_;
151template <
typename Enum>
152constexpr Flags<Enum>& Flags<Enum>::operator&=(Flags rhs) {
153 value_ &= rhs.value_;
157template <
typename Enum>
158constexpr Flags<Enum>& Flags<Enum>::Clear(Flags flags) {
159 value_ &= ~flags.value_;
163template <
typename Enum>
164constexpr Flags<Enum> Flags<Enum>::operator|(Flags rhs)
const {
165 return Flags(*
this) |= rhs;
168template <
typename Enum>
169constexpr Flags<Enum> Flags<Enum>::operator&(Flags rhs)
const {
170 return Flags(*
this) &= rhs;
173template <
typename Enum>
174constexpr bool Flags<Enum>::operator==(Flags rhs)
const {
175 return value_ == rhs.value_;
178template <
typename Enum>
179constexpr bool Flags<Enum>::operator!=(Flags rhs)
const {
180 return !(*
this == rhs);
183template <
typename Enum>
184constexpr typename Flags<Enum>::ValueType Flags<Enum>::GetValue()
const {
188template <
typename Enum>
189constexpr void Flags<Enum>::SetValue(
typename Flags<Enum>::ValueType value) {
190 this->value_ = value;
193template <
typename Enum>
194constexpr Flags<Enum> operator|(Enum lhs, Flags<Enum> rhs) {
198template <
typename Enum>
199constexpr Flags<Enum> operator&(Enum lhs, Flags<Enum> rhs) {
203template <
typename Enum>
204constexpr bool operator==(Enum lhs, Flags<Enum> rhs) {
205 return rhs == Flags<Enum>{lhs};
208template <
typename Enum>
209constexpr bool operator!=(Enum lhs, Flags<Enum> rhs) {
210 return rhs != Flags<Enum>{lhs};
213template <
typename Enum>
214constexpr AtomicFlags<Enum>::AtomicFlags(Enum value)
215 : value_(
static_cast<ValueType>(value)) {}
217template <
typename Enum>
218constexpr AtomicFlags<Enum>::AtomicFlags(std::initializer_list<Enum> values)
219 : AtomicFlags(Enum(values)) {}
221template <
typename Enum>
222AtomicFlags<Enum>::operator
bool()
const {
226template <
typename Enum>
227AtomicFlags<Enum>::operator Flags<Enum>()
const {
231template <
typename Enum>
232Flags<Enum> AtomicFlags<Enum>::Load(std::memory_order order)
const {
233 return static_cast<Enum>(value_.load(order));
236template <
typename Enum>
237AtomicFlags<Enum>& AtomicFlags<Enum>::operator=(Flags<Enum> rhs) {
242template <
typename Enum>
243AtomicFlags<Enum>& AtomicFlags<Enum>::Store(Flags<Enum> rhs,
244 std::memory_order order) {
245 value_.store(rhs.value_, order);
249template <
typename Enum>
250Flags<Enum> AtomicFlags<Enum>::Exchange(Flags<Enum> flags) {
251 return static_cast<Enum>(value_.exchange(flags.value_));
254template <
typename Enum>
255AtomicFlags<Enum>& AtomicFlags<Enum>::operator|=(Flags<Enum> rhs) {
260template <
typename Enum>
261AtomicFlags<Enum>& AtomicFlags<Enum>::operator&=(Flags<Enum> rhs) {
266template <
typename Enum>
267AtomicFlags<Enum>& AtomicFlags<Enum>::Clear(Flags<Enum> flags) {
272template <
typename Enum>
273Flags<Enum> AtomicFlags<Enum>::FetchOr(Flags<Enum> rhs,
274 std::memory_order memory_order) {
275 return static_cast<Enum>(value_.fetch_or(rhs.value_, memory_order));
278template <
typename Enum>
279Flags<Enum> AtomicFlags<Enum>::FetchAnd(Flags<Enum> rhs,
280 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,
286 std::memory_order memory_order) {
287 return static_cast<Enum>(value_.fetch_and(~flags.value_, memory_order));
290template <
typename Enum>
291bool AtomicFlags<Enum>::CompareExchangeWeak(Flags<Enum>& expected,
293 std::memory_order order) {
294 auto expected_int = expected.GetValue();
296 value_.compare_exchange_weak(expected_int, desired.GetValue(), order);
297 expected = Enum{expected_int};
301template <
typename Enum>
302bool AtomicFlags<Enum>::CompareExchangeStrong(Flags<Enum>& expected,
304 std::memory_order order) {
305 auto expected_int = expected.GetValue();
307 value_.compare_exchange_strong(expected_int, desired.GetValue(), order);
308 expected = Enum{expected_int};
312template <
typename Enum>
313bool AtomicFlags<Enum>::CompareExchangeWeak(Flags<Enum>& expected,
315 std::memory_order success,
316 std::memory_order failure) {
317 auto expected_int = expected.GetValue();
318 const bool result = value_.compare_exchange_weak(
319 expected_int, desired.GetValue(), success, failure);
320 expected = Enum{expected_int};
324template <
typename Enum>
325bool AtomicFlags<Enum>::CompareExchangeStrong(Flags<Enum>& expected,
327 std::memory_order success,
328 std::memory_order failure) {
329 auto expected_int = expected.GetValue();
330 const bool result = value_.compare_exchange_strong(
331 expected_int, desired.GetValue(), success, failure);
332 expected = Enum{expected_int};
336template <
typename Enum>
337Flags<Enum> AtomicFlags<Enum>::operator|(Flags<Enum> rhs)
const {
338 return Flags<Enum>{*
this} |= rhs;
341template <
typename Enum>
342Flags<Enum> AtomicFlags<Enum>::operator&(Flags<Enum> rhs)
const {
343 return Flags<Enum>{*
this} &= rhs;
346template <
typename Enum>
347bool AtomicFlags<Enum>::operator==(Flags<Enum> rhs)
const {
348 return value_ == rhs.value_;
351template <
typename Enum>
352bool AtomicFlags<Enum>::operator!=(Flags<Enum> rhs)
const {
353 return !(*
this == rhs);
356template <
typename Enum>
357typename AtomicFlags<Enum>::ValueType AtomicFlags<Enum>::GetValue() {
358 return this->value_.load();
361template <
typename Enum>
362Flags<Enum> operator|(Enum lhs,
const AtomicFlags<Enum>& rhs) {
366template <
typename Enum>
367Flags<Enum> operator&(Enum lhs,
const AtomicFlags<Enum>& rhs) {
371template <
typename Enum>
372bool operator==(Enum lhs,
const AtomicFlags<Enum>& rhs) {
373 return rhs == Flags<Enum>{lhs};
376template <
typename Enum>
377bool operator!=(Enum lhs,
const AtomicFlags<Enum>& rhs) {
378 return rhs != Flags<Enum>{lhs};