- fixed some garbage collection issues with interpolations:

* FInterpolator depended on external references to prevent its content from getting GC'd.
* none of the pointers in the interpolation objects were declared to the GC.

The result of these issues was that changing anything about the life cycle of interpolation objects caused corrupted memory crashes when a level was changed.
This commit is contained in:
Christoph Oelckers 2016-01-21 11:36:37 +01:00
parent e4982b1ced
commit d347415aee
5 changed files with 32 additions and 15 deletions

View file

@ -203,6 +203,11 @@ private: \
#define IMPLEMENT_ABSTRACT_CLASS(cls) \
_IMP_PCLASS(cls,NULL,NULL)
#define IMPLEMENT_ABSTRACT_POINTY_CLASS(cls) \
_IMP_PCLASS(cls,cls::PointerOffsets,NULL) \
const size_t cls::PointerOffsets[] = {
enum EObjectFlags
{
// GC flags

View file

@ -335,6 +335,7 @@ static void MarkRoot()
SectorMarker->SecNum = 0;
}
Mark(SectorMarker);
Mark(interpolator.Head);
// Mark bot stuff.
Mark(bglobal.firstthing);
Mark(bglobal.body1);

View file

@ -3353,6 +3353,7 @@ extern polyblock_t **PolyBlockMap;
void P_FreeLevelData ()
{
interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level.
Renderer->CleanLevelData();
FPolyObj::ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
SN_StopAllSequences ();
@ -3584,7 +3585,6 @@ void P_SetupLevel (const char *lumpname, int position)
// Free all level data from the previous map
P_FreeLevelData ();
interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level.
MapData *map = P_OpenMapData(lumpname, true);
if (map == NULL)

View file

@ -157,7 +157,10 @@ public:
//
//==========================================================================
IMPLEMENT_ABSTRACT_CLASS(DInterpolation)
IMPLEMENT_ABSTRACT_POINTY_CLASS(DInterpolation)
DECLARE_POINTER(Next)
DECLARE_POINTER(Prev)
END_POINTERS
IMPLEMENT_CLASS(DSectorPlaneInterpolation)
IMPLEMENT_CLASS(DSectorScrollInterpolation)
IMPLEMENT_CLASS(DWallScrollInterpolation)
@ -213,9 +216,9 @@ void FInterpolator::UpdateInterpolations()
void FInterpolator::AddInterpolation(DInterpolation *interp)
{
interp->Next = Head;
if (Head != NULL) Head->Prev = &interp->Next;
if (Head != NULL) Head->Prev = interp;
interp->Prev = NULL;
Head = interp;
interp->Prev = &Head;
count++;
}
@ -227,14 +230,19 @@ void FInterpolator::AddInterpolation(DInterpolation *interp)
void FInterpolator::RemoveInterpolation(DInterpolation *interp)
{
if (interp->Prev != NULL)
if (Head == interp)
{
*interp->Prev = interp->Next;
if (interp->Next != NULL) interp->Next->Prev = interp->Prev;
interp->Next = NULL;
interp->Prev = NULL;
count--;
Head = interp->Next;
if (Head != NULL) Head->Prev = NULL;
}
else
{
if (interp->Prev != NULL) interp->Prev->Next = interp->Next;
if (interp->Next != NULL) interp->Next->Prev = interp->Prev;
}
interp->Next = NULL;
interp->Prev = NULL;
count--;
}
//==========================================================================
@ -285,13 +293,15 @@ void FInterpolator::RestoreInterpolations()
void FInterpolator::ClearInterpolations()
{
for (DInterpolation *probe = Head; probe != NULL; )
DInterpolation *probe = Head;
Head = NULL;
while (probe != NULL)
{
DInterpolation *next = probe->Next;
probe->Next = probe->Prev = NULL;
probe->Destroy();
probe = next;
}
Head = NULL;
}

View file

@ -13,9 +13,10 @@ class DInterpolation : public DObject
friend struct FInterpolator;
DECLARE_ABSTRACT_CLASS(DInterpolation, DObject)
HAS_OBJECT_POINTERS
DInterpolation *Next;
DInterpolation **Prev;
TObjPtr<DInterpolation> Next;
TObjPtr<DInterpolation> Prev;
int refcount;
protected:
@ -40,7 +41,7 @@ public:
struct FInterpolator
{
DInterpolation *Head;
TObjPtr<DInterpolation> Head;
bool didInterp;
int count;