vendredi 8 juillet 2022

atomic enum class compare and swap data corrupt

I have written some code to help compare and swap atomic enum type, when i run it in multi-thread, it corrupt the data alongside.

template <typename ET>                                                                                                                                                
bool AtomicCAS(std::atomic<ET>& atom, ET& com, ET change, std::memory_order order = std::memory_order_acq_rel) //code have problem
{
  using raw = std::underlying_type_t<ET>;
  std::atomic<raw>* atomic_p = reinterpret_cast<std::atomic<raw>*>(&atom);
  return atomic_p->compare_exchange_strong(*reinterpret_cast<raw*>(&com), static_cast<raw>(change), order);
}
template <typename T, bool AssertBit = true, bool ReturnHasBit = false, typename std::enable_if<std::is_enum_v<T>>::type* = nullptr>
T CASBit(std::atomic<T>& atom, T set_bit)
{
  using namespace enum_op_helper;
  T state = atom.load(std::memory_order_relaxed), new_state = BitwiseOr(state, set_bit);
  if constexpr(AssertBit)
  {
    assert(!BitwiseHas(state, set_bit));
  }
  if constexpr(ReturnHasBit)
  {
    if(BitwiseHas(state, set_bit))
    {
      return state;
    }
  }
  while(AtomicCAS(atom, state, new_state, std::memory_order_acq_rel))
  {
    new_state = BitwiseOr(state, set_bit);
    if constexpr(AssertBit)
    {
      assert(!BitwiseHas(state, set_bit));
    }
    if constexpr(ReturnHasBit)
    {
      if(BitwiseHas(state, set_bit))
      {
        return state;
      }
    }
  }
  return state;
}
enum class EventState : uint32_t
{
  INIT = 0,
  HAS_CALLBACK = 1,
  HAS_EVENT = 2,
};

struct EventCore : public EnableKeepAlive<EventCore>
{
  void SetCallback(FuncType&& f);

  std::atomic<EventState> state_{EventState::INIT}; //std::atomic<int> is oK
  std::function<void(DataType&&)> callback_;
};

I find when i update state_ in multi-thread use CAS, it will corrupt callback_, when i define state_ as std::atomic<int> and use c11 interface, it works well. I'm pretty sure AtomicCAS have some problem.

Aucun commentaire:

Enregistrer un commentaire