diff --git a/src/hx/atomic/AtomicInt.cpp b/src/hx/atomic/AtomicInt.cpp index dfe4dfb4e..99ad3cb7e 100644 --- a/src/hx/atomic/AtomicInt.cpp +++ b/src/hx/atomic/AtomicInt.cpp @@ -2,6 +2,9 @@ #include "hx/atomic/AtomicInt.hpp" #include +// Atomic operations never block, so they don't enter a GC free zone. Each one is still a GC +// safe point, so that a loop which spins on atomics without allocating can't stall a collection. + struct hx::atomic::AtomicInt_obj::Impl { std::atomic_int atomic; @@ -14,42 +17,42 @@ hx::atomic::AtomicInt_obj::AtomicInt_obj(int val) : impl(new Impl()) int hx::atomic::AtomicInt_obj::fetchAdd(int val) { - hx::AutoGCFreeZone _; + __hxcpp_gc_safe_point(); return impl->atomic.fetch_add(val); } int hx::atomic::AtomicInt_obj::fetchSub(int val) { - hx::AutoGCFreeZone _; + __hxcpp_gc_safe_point(); return impl->atomic.fetch_sub(val); } int hx::atomic::AtomicInt_obj::fetchAnd(int val) { - hx::AutoGCFreeZone _; + __hxcpp_gc_safe_point(); return impl->atomic.fetch_and(val); } int hx::atomic::AtomicInt_obj::fetchXor(int val) { - hx::AutoGCFreeZone _; + __hxcpp_gc_safe_point(); return impl->atomic.fetch_xor(val); } int hx::atomic::AtomicInt_obj::fetchOr(int val) { - hx::AutoGCFreeZone _; + __hxcpp_gc_safe_point(); return impl->atomic.fetch_or(val); } int hx::atomic::AtomicInt_obj::store(int val) { - hx::AutoGCFreeZone _; + __hxcpp_gc_safe_point(); impl->atomic.store(val); @@ -58,21 +61,21 @@ int hx::atomic::AtomicInt_obj::store(int val) int hx::atomic::AtomicInt_obj::load() { - hx::AutoGCFreeZone _; + __hxcpp_gc_safe_point(); return impl->atomic.load(); } int hx::atomic::AtomicInt_obj::exchange(int val) { - hx::AutoGCFreeZone _; + __hxcpp_gc_safe_point(); return impl->atomic.exchange(val); } int hx::atomic::AtomicInt_obj::compareExchange(int expected, int replacement) { - hx::AutoGCFreeZone _; + __hxcpp_gc_safe_point(); // On failure, compare_exchange_strong stores the current value in `original`. int original{ expected }; diff --git a/src/hx/atomic/AtomicObject.cpp b/src/hx/atomic/AtomicObject.cpp index b2ea5c5ac..d7babd200 100644 --- a/src/hx/atomic/AtomicObject.cpp +++ b/src/hx/atomic/AtomicObject.cpp @@ -2,6 +2,9 @@ #include "hx/atomic/AtomicObject.hpp" #include +// Atomic operations never block, so they don't enter a GC free zone. Each one is still a GC +// safe point, so that a loop which spins on atomics without allocating can't stall a collection. + struct hx::atomic::AtomicObject_obj::Impl { std::atomic atomic; @@ -34,9 +37,9 @@ void hx::atomic::AtomicObject_obj::__Visit(HX_VISIT_PARAMS) Dynamic hx::atomic::AtomicObject_obj::store(Dynamic val) { - hx::EnterGCFreeZone(); + __hxcpp_gc_safe_point(); + impl->atomic.store(val); - hx::ExitGCFreeZone(); HX_OBJ_WB_GET(this, val.mPtr); @@ -45,16 +48,16 @@ Dynamic hx::atomic::AtomicObject_obj::store(Dynamic val) Dynamic hx::atomic::AtomicObject_obj::load() { - hx::AutoGCFreeZone _; + __hxcpp_gc_safe_point(); return impl->atomic.load(); } Dynamic hx::atomic::AtomicObject_obj::exchange(Dynamic val) { - hx::EnterGCFreeZone(); + __hxcpp_gc_safe_point(); + Dynamic old{ impl->atomic.exchange(val) }; - hx::ExitGCFreeZone(); HX_OBJ_WB_GET(this, val.mPtr); @@ -63,25 +66,19 @@ Dynamic hx::atomic::AtomicObject_obj::exchange(Dynamic val) Dynamic hx::atomic::AtomicObject_obj::compareExchange(Dynamic expected, Dynamic replacement) { + __hxcpp_gc_safe_point(); + // Note: using Dynamic instead of hx::Object* is important // Dynamic has an overloaded == operator, a raw pointer to hx::Object does not. Dynamic original{ impl->atomic.load() }; while (original == expected) { - hx::EnterGCFreeZone(); if (impl->atomic.compare_exchange_strong(original.mPtr, replacement.mPtr)) { - hx::ExitGCFreeZone(); - HX_OBJ_WB_GET(this, replacement.mPtr); return original; } - else - { - hx::ExitGCFreeZone(); - continue; - } } return original;