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};