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()
71 : AtomicFlags(Enum::kNone)
73 constexpr explicit AtomicFlags(Enum);
74 constexpr AtomicFlags(std::initializer_list<Enum>);
76 explicit operator
bool()
const;
77 operator Flags<Enum>()
const;
78 Flags<Enum> Load(std::memory_order = std::memory_order_seq_cst)
const;
80 AtomicFlags& operator=(Flags<Enum>);
81 AtomicFlags& Store(Flags<Enum>, std::memory_order = std::memory_order_seq_cst);
82 Flags<Enum> Exchange(Flags<Enum>);
84 AtomicFlags& operator|=(Flags<Enum>);
85 AtomicFlags& operator&=(Flags<Enum>);
86 AtomicFlags& Clear(Flags<Enum>);
87 Flags<Enum> FetchOr(Flags<Enum>, std::memory_order = std::memory_order_seq_cst);
88 Flags<Enum> FetchAnd(Flags<Enum>, std::memory_order = std::memory_order_seq_cst);
89 Flags<Enum> FetchClear(Flags<Enum>, std::memory_order = std::memory_order_seq_cst);
90 bool CompareExchangeWeak(
91 Flags<Enum>& expected,
93 std::memory_order order = std::memory_order_seq_cst
95 bool CompareExchangeStrong(
96 Flags<Enum>& expected,
98 std::memory_order order = std::memory_order_seq_cst
100 bool CompareExchangeWeak(
101 Flags<Enum>& expected,
103 std::memory_order success,
104 std::memory_order failure
106 bool CompareExchangeStrong(
107 Flags<Enum>& expected,
109 std::memory_order success,
110 std::memory_order failure
113 Flags<Enum> operator|(Flags<Enum>)
const;
114 Flags<Enum> operator&(Flags<Enum>)
const;
116 bool operator==(Flags<Enum>)
const;
117 bool operator!=(Flags<Enum>)
const;
119 ValueType GetValue();
122 std::atomic<ValueType> value_;
125template <
typename Enum>
126Flags<Enum> operator|(Enum,
const AtomicFlags<Enum>&);
128template <
typename Enum>
129Flags<Enum> operator&(Enum,
const AtomicFlags<Enum>&);
131template <
typename Enum>
132bool operator==(Enum,
const AtomicFlags<Enum>&);
134template <
typename Enum>
135bool operator!=(Enum,
const AtomicFlags<Enum>&);
137template <
typename Enum>
138constexpr Flags<Enum>::Flags(Enum value)
noexcept : value_(
static_cast<ValueType>(value)) {}
140template <
typename Enum>
141constexpr Flags<Enum>::Flags(std::initializer_list<Enum> values)
noexcept : Flags() {
142 for (Enum value : values) {
147template <
typename Enum>
148constexpr Flags<Enum>::operator
bool()
const {
152template <
typename Enum>
153constexpr Flags<Enum>& Flags<Enum>::operator|=(Flags rhs) {
154 value_ |= rhs.value_;
158template <
typename Enum>
159constexpr Flags<Enum>& Flags<Enum>::operator&=(Flags rhs) {
160 value_ &= rhs.value_;
164template <
typename Enum>
165constexpr Flags<Enum>& Flags<Enum>::Clear(Flags flags) {
166 value_ &= ~flags.value_;
170template <
typename Enum>
171constexpr Flags<Enum> Flags<Enum>::operator|(Flags rhs)
const {
172 return Flags(*
this) |= rhs;
175template <
typename Enum>
176constexpr Flags<Enum> Flags<Enum>::operator&(Flags rhs)
const {
177 return Flags(*
this) &= rhs;
180template <
typename Enum>
181constexpr bool Flags<Enum>::operator==(Flags rhs)
const {
182 return value_ == rhs.value_;
185template <
typename Enum>
186constexpr bool Flags<Enum>::operator!=(Flags rhs)
const {
187 return !(*
this == rhs);
190template <
typename Enum>
191constexpr typename Flags<Enum>::ValueType Flags<Enum>::GetValue()
const {
195template <
typename Enum>
196constexpr void Flags<Enum>::SetValue(
typename Flags<Enum>::ValueType value) {
197 this->value_ = value;
200template <
typename Enum>
201constexpr Flags<Enum> operator|(Enum lhs, Flags<Enum> rhs) {
205template <
typename Enum>
206constexpr Flags<Enum> operator&(Enum lhs, Flags<Enum> rhs) {
210template <
typename Enum>
211constexpr bool operator==(Enum lhs, Flags<Enum> rhs) {
212 return rhs == Flags<Enum>{lhs};
215template <
typename Enum>
216constexpr bool operator!=(Enum lhs, Flags<Enum> rhs) {
217 return rhs != Flags<Enum>{lhs};
220template <
typename Enum>
221constexpr AtomicFlags<Enum>::AtomicFlags(Enum value)
222 : value_(
static_cast<ValueType>(value))
225template <
typename Enum>
226constexpr AtomicFlags<Enum>::AtomicFlags(std::initializer_list<Enum> values)
227 : AtomicFlags(Enum(values))
230template <
typename Enum>
231AtomicFlags<Enum>::operator
bool()
const {
235template <
typename Enum>
236AtomicFlags<Enum>::operator Flags<Enum>()
const {
240template <
typename Enum>
241Flags<Enum> AtomicFlags<Enum>::Load(std::memory_order order)
const {
242 return static_cast<Enum>(value_.load(order));
245template <
typename Enum>
246AtomicFlags<Enum>& AtomicFlags<Enum>::operator=(Flags<Enum> rhs) {
251template <
typename Enum>
252AtomicFlags<Enum>& AtomicFlags<Enum>::Store(Flags<Enum> rhs, std::memory_order order) {
253 value_.store(rhs.value_, order);
257template <
typename Enum>
258Flags<Enum> AtomicFlags<Enum>::Exchange(Flags<Enum> flags) {
259 return static_cast<Enum>(value_.exchange(flags.value_));
262template <
typename Enum>
263AtomicFlags<Enum>& AtomicFlags<Enum>::operator|=(Flags<Enum> rhs) {
268template <
typename Enum>
269AtomicFlags<Enum>& AtomicFlags<Enum>::operator&=(Flags<Enum> rhs) {
274template <
typename Enum>
275AtomicFlags<Enum>& AtomicFlags<Enum>::Clear(Flags<Enum> flags) {
280template <
typename Enum>
281Flags<Enum> AtomicFlags<Enum>::FetchOr(Flags<Enum> rhs, std::memory_order memory_order) {
282 return static_cast<Enum>(value_.fetch_or(rhs.value_, memory_order));
285template <
typename Enum>
286Flags<Enum> AtomicFlags<Enum>::FetchAnd(Flags<Enum> rhs, std::memory_order memory_order) {
287 return static_cast<Enum>(value_.fetch_and(rhs.value_, memory_order));
290template <
typename Enum>
291Flags<Enum> AtomicFlags<Enum>::FetchClear(Flags<Enum> flags, std::memory_order memory_order) {
292 return static_cast<Enum>(value_.fetch_and(~flags.value_, memory_order));
295template <
typename Enum>
296bool AtomicFlags<Enum>::CompareExchangeWeak(Flags<Enum>& expected, Flags<Enum> desired, std::memory_order order) {
297 auto expected_int = expected.GetValue();
298 const bool result = value_.compare_exchange_weak(expected_int, desired.GetValue(), order);
299 expected = Enum{expected_int};
303template <
typename Enum>
304bool AtomicFlags<Enum>::CompareExchangeStrong(Flags<Enum>& expected, Flags<Enum> desired, std::memory_order order) {
305 auto expected_int = expected.GetValue();
306 const bool result = value_.compare_exchange_strong(expected_int, desired.GetValue(), order);
307 expected = Enum{expected_int};
311template <
typename Enum>
312bool AtomicFlags<Enum>::CompareExchangeWeak(
313 Flags<Enum>& expected,
315 std::memory_order success,
316 std::memory_order failure
318 auto expected_int = expected.GetValue();
319 const bool result = value_.compare_exchange_weak(expected_int, desired.GetValue(), success, failure);
320 expected = Enum{expected_int};
324template <
typename Enum>
325bool AtomicFlags<Enum>::CompareExchangeStrong(
326 Flags<Enum>& expected,
328 std::memory_order success,
329 std::memory_order failure
331 auto expected_int = expected.GetValue();
332 const bool result = value_.compare_exchange_strong(expected_int, desired.GetValue(), success, failure);
333 expected = Enum{expected_int};
337template <
typename Enum>
338Flags<Enum> AtomicFlags<Enum>::operator|(Flags<Enum> rhs)
const {
339 return Flags<Enum>{*
this} |= rhs;
342template <
typename Enum>
343Flags<Enum> AtomicFlags<Enum>::operator&(Flags<Enum> rhs)
const {
344 return Flags<Enum>{*
this} &= rhs;
347template <
typename Enum>
348bool AtomicFlags<Enum>::operator==(Flags<Enum> rhs)
const {
349 return value_ == rhs.value_;
352template <
typename Enum>
353bool AtomicFlags<Enum>::operator!=(Flags<Enum> rhs)
const {
354 return !(*
this == rhs);
357template <
typename Enum>
358typename AtomicFlags<Enum>::ValueType AtomicFlags<Enum>::GetValue() {
359 return this->value_.load();
362template <
typename Enum>
363Flags<Enum> operator|(Enum lhs,
const AtomicFlags<Enum>& rhs) {
367template <
typename Enum>
368Flags<Enum> operator&(Enum lhs,
const AtomicFlags<Enum>& rhs) {
372template <
typename Enum>
373bool operator==(Enum lhs,
const AtomicFlags<Enum>& rhs) {
374 return rhs == Flags<Enum>{lhs};
377template <
typename Enum>
378bool operator!=(Enum lhs,
const AtomicFlags<Enum>& rhs) {
379 return rhs != Flags<Enum>{lhs};