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);
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>
68 using ValueType = std::underlying_type_t<Enum>;
70 constexpr AtomicFlags()
73 constexpr explicit AtomicFlags(Flags<Enum>);
74 constexpr explicit AtomicFlags(Enum);
75 constexpr AtomicFlags(std::initializer_list<Enum>);
77 explicit operator
bool()
const;
78 operator Flags<Enum>()
const;
79 Flags<Enum> Load(std::memory_order = std::memory_order_seq_cst)
const;
82 AtomicFlags& Store(Flags<Enum>, std::memory_order = std::memory_order_seq_cst);
83 Flags<Enum> Exchange(Flags<Enum>);
88 Flags<Enum> FetchOr(Flags<Enum>, std::memory_order = std::memory_order_seq_cst);
89 Flags<Enum> FetchAnd(Flags<Enum>, std::memory_order = std::memory_order_seq_cst);
90 Flags<Enum> FetchClear(Flags<Enum>, std::memory_order = std::memory_order_seq_cst);
91 bool CompareExchangeWeak(
92 Flags<Enum>& expected,
94 std::memory_order order = std::memory_order_seq_cst
96 bool CompareExchangeStrong(
97 Flags<Enum>& expected,
99 std::memory_order order = std::memory_order_seq_cst
101 bool CompareExchangeWeak(
102 Flags<Enum>& expected,
104 std::memory_order success,
105 std::memory_order failure
107 bool CompareExchangeStrong(
108 Flags<Enum>& expected,
110 std::memory_order success,
111 std::memory_order failure
114 Flags<Enum> operator|(Flags<Enum>)
const;
115 Flags<Enum> operator&(Flags<Enum>)
const;
117 bool operator==(Flags<Enum>)
const;
118 bool operator!=(Flags<Enum>)
const;
120 ValueType GetValue();
123 std::atomic<ValueType> value_;
126template <
typename Enum>
127Flags<Enum> operator|(Enum,
const AtomicFlags<Enum>&);
129template <
typename Enum>
130Flags<Enum> operator&(Enum,
const AtomicFlags<Enum>&);
132template <
typename Enum>
135template <
typename Enum>
138template <
typename Enum>
139constexpr Flags<Enum>::Flags(Enum value)
noexcept : value_(
static_cast<ValueType>(value)) {}
141template <
typename Enum>
142constexpr Flags<Enum>::Flags(std::initializer_list<Enum> values)
noexcept : Flags() {
143 for (Enum value : values) {
148template <
typename Enum>
149constexpr Flags<Enum>::operator
bool()
const {
153template <
typename Enum>
154constexpr Flags<Enum>& Flags<Enum>::operator|=(Flags rhs) {
155 value_ |= rhs.value_;
159template <
typename Enum>
160constexpr Flags<Enum>& Flags<Enum>::operator&=(Flags rhs) {
161 value_ &= rhs.value_;
165template <
typename Enum>
166constexpr Flags<Enum>& Flags<Enum>::Clear(Flags flags) {
167 value_ &= ~flags.value_;
171template <
typename Enum>
172constexpr Flags<Enum> Flags<Enum>::operator|(Flags rhs)
const {
173 return Flags(*
this) |= rhs;
176template <
typename Enum>
177constexpr Flags<Enum> Flags<Enum>::operator&(Flags rhs)
const {
178 return Flags(*
this) &= rhs;
181template <
typename Enum>
182constexpr bool Flags<Enum>::operator==(Flags rhs)
const {
183 return value_ == rhs.value_;
186template <
typename Enum>
187constexpr bool Flags<Enum>::operator!=(Flags rhs)
const {
188 return !(*
this == rhs);
191template <
typename Enum>
192constexpr typename Flags<Enum>::ValueType Flags<Enum>::GetValue()
const {
196template <
typename Enum>
197constexpr void Flags<Enum>::SetValue(
typename Flags<Enum>::ValueType value) {
198 this->value_ = value;
201template <
typename Enum>
202constexpr Flags<Enum> operator|(Enum lhs, Flags<Enum> rhs) {
206template <
typename Enum>
207constexpr Flags<Enum> operator&(Enum lhs, Flags<Enum> rhs) {
211template <
typename Enum>
212constexpr bool operator==(Enum lhs, Flags<Enum> rhs) {
213 return rhs == Flags<Enum>{lhs};
216template <
typename Enum>
217constexpr bool operator!=(Enum lhs, Flags<Enum> rhs) {
218 return rhs != Flags<Enum>{lhs};
221template <
typename Enum>
222constexpr AtomicFlags<Enum>::AtomicFlags(Flags<Enum> flags)
223 : value_(flags.GetValue())
226template <
typename Enum>
227constexpr AtomicFlags<Enum>::AtomicFlags(Enum value)
231template <
typename Enum>
232constexpr AtomicFlags<Enum>::AtomicFlags(std::initializer_list<Enum> values)
236template <
typename Enum>
241template <
typename Enum>
246template <
typename Enum>
247Flags<Enum>
AtomicFlags<Enum>::Load(std::memory_order order)
const {
248 return static_cast<Enum>(value_.load(order));
251template <
typename Enum>
257template <
typename Enum>
259 value_.store(rhs.value_, order);
263template <
typename Enum>
264Flags<Enum>
AtomicFlags<Enum>::Exchange(Flags<Enum> flags) {
265 return static_cast<Enum>(value_.exchange(flags.value_));
268template <
typename Enum>
274template <
typename Enum>
280template <
typename Enum>
286template <
typename Enum>
287Flags<Enum>
AtomicFlags<Enum>::FetchOr(Flags<Enum> rhs, std::memory_order memory_order) {
288 return static_cast<Enum>(value_.fetch_or(rhs.value_, memory_order));
291template <
typename Enum>
292Flags<Enum>
AtomicFlags<Enum>::FetchAnd(Flags<Enum> rhs, std::memory_order memory_order) {
293 return static_cast<Enum>(value_.fetch_and(rhs.value_, memory_order));
296template <
typename Enum>
297Flags<Enum>
AtomicFlags<Enum>::FetchClear(Flags<Enum> flags, std::memory_order memory_order) {
298 return static_cast<Enum>(value_.fetch_and(~flags.value_, memory_order));
301template <
typename Enum>
302bool AtomicFlags<Enum>::CompareExchangeWeak(Flags<Enum>& expected, Flags<Enum> desired, std::memory_order order) {
303 auto expected_int = expected.GetValue();
304 const bool result = value_.compare_exchange_weak(expected_int, desired.GetValue(), order);
305 expected = Enum{expected_int};
309template <
typename Enum>
310bool AtomicFlags<Enum>::CompareExchangeStrong(Flags<Enum>& expected, Flags<Enum> desired, std::memory_order order) {
311 auto expected_int = expected.GetValue();
312 const bool result = value_.compare_exchange_strong(expected_int, desired.GetValue(), order);
313 expected = Enum{expected_int};
317template <
typename Enum>
319 Flags<Enum>& expected,
321 std::memory_order success,
322 std::memory_order failure
324 auto expected_int = expected.GetValue();
325 const bool result = value_.compare_exchange_weak(expected_int, desired.GetValue(), success, failure);
326 expected = Enum{expected_int};
330template <
typename Enum>
332 Flags<Enum>& expected,
334 std::memory_order success,
335 std::memory_order failure
337 auto expected_int = expected.GetValue();
338 const bool result = value_.compare_exchange_strong(expected_int, desired.GetValue(), success, failure);
339 expected = Enum{expected_int};
343template <
typename Enum>
344Flags<Enum>
AtomicFlags<Enum>::operator|(Flags<Enum> rhs)
const {
345 return Flags<Enum>{*
this} |= rhs;
348template <
typename Enum>
349Flags<Enum>
AtomicFlags<Enum>::operator&(Flags<Enum> rhs)
const {
350 return Flags<Enum>{*
this} &= rhs;
353template <
typename Enum>
354bool AtomicFlags<Enum>::operator==(Flags<Enum> rhs)
const {
355 return value_ == rhs.value_;
358template <
typename Enum>
359bool AtomicFlags<Enum>::operator!=(Flags<Enum> rhs)
const {
360 return !(*
this == rhs);
363template <
typename Enum>
365 return this->value_.load();
368template <
typename Enum>
369Flags<Enum> operator|(Enum lhs,
const AtomicFlags<Enum>& rhs) {
373template <
typename Enum>
374Flags<Enum> operator&(Enum lhs,
const AtomicFlags<Enum>& rhs) {
378template <
typename Enum>
379bool operator==(Enum lhs,
const AtomicFlags<Enum>& rhs) {
380 return rhs == Flags<Enum>{lhs};
383template <
typename Enum>
384bool operator!=(Enum lhs,
const AtomicFlags<Enum>& rhs) {
385 return rhs != Flags<Enum>{lhs};