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