diff --git a/dtool/src/dtoolbase/deletedBufferChain.I b/dtool/src/dtoolbase/deletedBufferChain.I index 9eb17bd4fb..ac5243de76 100644 --- a/dtool/src/dtoolbase/deletedBufferChain.I +++ b/dtool/src/dtoolbase/deletedBufferChain.I @@ -27,7 +27,7 @@ validate(void *ptr) { #if defined(USE_DELETEDCHAINFLAG) && defined(USE_DELETED_CHAIN) const ObjectNode *obj = buffer_to_node(ptr); - return AtomicAdjust::get(obj->_flag) == DCF_alive; + return obj->_flag.load(std::memory_order_relaxed) == DCF_alive; #else return true; #endif // USE_DELETEDCHAINFLAG diff --git a/dtool/src/dtoolbase/deletedBufferChain.cxx b/dtool/src/dtoolbase/deletedBufferChain.cxx index d009510ad3..d38b833ea1 100644 --- a/dtool/src/dtoolbase/deletedBufferChain.cxx +++ b/dtool/src/dtoolbase/deletedBufferChain.cxx @@ -50,8 +50,8 @@ allocate(size_t size, TypeHandle type_handle) { _lock.unlock(); #ifdef USE_DELETEDCHAINFLAG - assert(obj->_flag == (AtomicAdjust::Integer)DCF_deleted); - obj->_flag = DCF_alive; + DeletedChainFlag orig_flag = obj->_flag.exchange(DCF_alive, std::memory_order_relaxed); + assert(orig_flag == DCF_deleted); #endif // USE_DELETEDCHAINFLAG void *ptr = node_to_buffer(obj); @@ -75,7 +75,7 @@ allocate(size_t size, TypeHandle type_handle) { obj = (ObjectNode *)(aligned - flag_reserved_bytes); #ifdef USE_DELETEDCHAINFLAG - obj->_flag = DCF_alive; + obj->_flag.store(DCF_alive, std::memory_order_relaxed); #endif // USE_DELETEDCHAINFLAG void *ptr = node_to_buffer(obj); @@ -116,14 +116,16 @@ deallocate(void *ptr, TypeHandle type_handle) { ObjectNode *obj = buffer_to_node(ptr); #ifdef USE_DELETEDCHAINFLAG - AtomicAdjust::Integer orig_flag = AtomicAdjust::compare_and_exchange(obj->_flag, DCF_alive, DCF_deleted); + DeletedChainFlag orig_flag = DCF_alive; + if (UNLIKELY(!obj->_flag.compare_exchange_strong(orig_flag, DCF_deleted, + std::memory_order_relaxed))) { + // If this assertion is triggered, you double-deleted an object. + assert(orig_flag != DCF_deleted); - // If this assertion is triggered, you double-deleted an object. - assert(orig_flag != (AtomicAdjust::Integer)DCF_deleted); - - // If this assertion is triggered, you tried to delete an object that was - // never allocated, or you have heap corruption. - assert(orig_flag == (AtomicAdjust::Integer)DCF_alive); + // If this assertion is triggered, you tried to delete an object that was + // never allocated, or you have heap corruption. + assert(orig_flag == DCF_alive); + } #endif // USE_DELETEDCHAINFLAG _lock.lock(); diff --git a/dtool/src/dtoolbase/deletedBufferChain.h b/dtool/src/dtoolbase/deletedBufferChain.h index 10ac5847fd..3bfd8cc071 100644 --- a/dtool/src/dtoolbase/deletedBufferChain.h +++ b/dtool/src/dtoolbase/deletedBufferChain.h @@ -20,6 +20,7 @@ #include "atomicAdjust.h" #include "numeric_types.h" #include "typeHandle.h" +#include "patomic.h" #include // Though it's tempting, it doesn't seem to be possible to implement @@ -37,7 +38,7 @@ #endif // NDEBUG #ifdef USE_DELETEDCHAINFLAG -enum DeletedChainFlag { +enum DeletedChainFlag : unsigned int { DCF_deleted = 0xfeedba0f, DCF_alive = 0x12487654, }; @@ -73,7 +74,7 @@ private: // In development mode, we piggyback this extra data. This is maintained // out-of-band from the actual pointer returned, so we can safely use this // flag to indicate the difference between allocated and freed pointers. - TVOLATILE AtomicAdjust::Integer _flag; + patomic _flag; #endif // This pointer sits within the buffer, in the same space referenced by