diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index 3d683aff1..4f0aa20db 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -78,6 +78,7 @@ #include "menu/menu.h" #include "intermission/intermission.h" #include "g_levellocals.h" +#include "events.h" // MACROS ------------------------------------------------------------------ @@ -331,6 +332,8 @@ static void MarkRoot() DThinker::MarkRoots(); FCanvasTextureInfo::Mark(); Mark(DACSThinker::ActiveThinker); + Mark(E_FirstEventHandler); + Mark(E_LastEventHandler); for (auto &s : level.sectorPortals) { Mark(s.mSkybox); diff --git a/src/events.cpp b/src/events.cpp index 4522f1989..afa98c99d 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -37,32 +37,42 @@ bool E_RegisterHandler(DStaticEventHandler* handler) // 2. MyHandler3->2: // E_FirstEventHandler = MyHandler2, E_LastEventHandler = MyHandler3 + // (Yes, all those write barriers here are really needed!) if (before != nullptr) { // if before is not null, link it before the existing handler. // note that before can be first handler, check for this. handler->next = before; + GC::WriteBarrier(handler, before); handler->prev = before->prev; + GC::WriteBarrier(handler, before->prev); before->prev = handler; + GC::WriteBarrier(before, handler); if (before == E_FirstEventHandler) + { E_FirstEventHandler = handler; + GC::WriteBarrier(handler); + } } else { // so if before is null, it means add last. // it can also mean that we have no handlers at all yet. handler->prev = E_LastEventHandler; + GC::WriteBarrier(handler, E_LastEventHandler); handler->next = nullptr; - if (E_FirstEventHandler == nullptr) - E_FirstEventHandler = handler; + if (E_FirstEventHandler == nullptr) E_FirstEventHandler = handler; E_LastEventHandler = handler; + GC::WriteBarrier(handler); if (handler->prev != nullptr) + { handler->prev->next = handler; + GC::WriteBarrier(handler->prev, handler); + } } if (handler->IsStatic()) { - handler->ObjectFlags |= OF_Fixed; handler->ObjectFlags |= OF_Transient; } @@ -80,16 +90,28 @@ bool E_UnregisterHandler(DStaticEventHandler* handler) // link out of normal list if (handler->prev) + { handler->prev->next = handler->next; + GC::WriteBarrier(handler->prev, handler->next); + } if (handler->next) + { handler->next->prev = handler->prev; + GC::WriteBarrier(handler->next, handler->prev); + } if (handler == E_FirstEventHandler) + { E_FirstEventHandler = handler->next; + GC::WriteBarrier(handler->next); + } if (handler == E_LastEventHandler) + { E_LastEventHandler = handler->prev; + GC::WriteBarrier(handler->prev); + } if (handler->IsStatic()) { - handler->ObjectFlags &= ~(OF_Fixed|OF_Transient); + handler->ObjectFlags &= ~OF_Transient; handler->Destroy(); } return true; diff --git a/src/events.h b/src/events.h index 71c8a27f6..f51a9ae6f 100755 --- a/src/events.h +++ b/src/events.h @@ -77,6 +77,7 @@ void E_SerializeEvents(FSerializer& arc); class DStaticEventHandler : public DObject // make it a part of normal GC process { DECLARE_CLASS(DStaticEventHandler, DObject) + HAS_OBJECT_POINTERS public: DStaticEventHandler() { @@ -99,6 +100,7 @@ public: void Serialize(FSerializer& arc) override { Super::Serialize(arc); + /* if (arc.isReading()) { Printf("DStaticEventHandler::Serialize: reading object %s\n", GetClass()->TypeName.GetChars()); @@ -107,6 +109,7 @@ public: { Printf("DStaticEventHandler::Serialize: store object %s\n", GetClass()->TypeName.GetChars()); } + */ arc("Order", Order); arc("IsUiProcessor", IsUiProcessor);