- made PSprites submission GC aware.

This commit is contained in:
Christoph Oelckers 2016-05-21 13:11:43 +02:00
parent 8c205ebac3
commit d767d10322
3 changed files with 47 additions and 16 deletions

View file

@ -436,6 +436,7 @@ public:
AWeapon *ReadyWeapon; AWeapon *ReadyWeapon;
AWeapon *PendingWeapon; // WP_NOCHANGE if not changing AWeapon *PendingWeapon; // WP_NOCHANGE if not changing
TObjPtr<DPSprite> psprites; // view sprites (gun, etc)
int cheats; // bit flags int cheats; // bit flags
int timefreezer; // Player has an active time freezer int timefreezer; // Player has an active time freezer
@ -528,7 +529,6 @@ public:
int GetSpawnClass(); int GetSpawnClass();
// PSprite layers // PSprite layers
DPSprite *psprites; // view sprites (gun, etc)
void TickPSprites(); void TickPSprites();
void DestroyPSprites(); void DestroyPSprites();
DPSprite *GetPSprite(psprnum_t layer); // Used ONLY for compatibility with the old hardcoded layers. DPSprite *GetPSprite(psprnum_t layer); // Used ONLY for compatibility with the old hardcoded layers.

View file

@ -113,12 +113,25 @@ END_POINTERS
DPSprite::DPSprite(player_t *owner, AInventory *caller, int id) DPSprite::DPSprite(player_t *owner, AInventory *caller, int id)
: processPending(true), firstTic(true), Owner(owner), Caller(caller), ID(id) : processPending(true), firstTic(true), Owner(owner), Caller(caller), ID(id)
{ {
DPSprite **prev = &Owner->psprites; DPSprite *prev = nullptr;
while (*prev && (*prev)->ID < ID) DPSprite *next = Owner->psprites;
prev = &(*prev)->Next; while (next != nullptr && next->ID < ID)
{
Next = *prev; prev = next;
*prev = this; next = next->Next;
}
Next = next;
GC::WriteBarrier(this, next);
if (prev == NULL)
{
Owner->psprites = this;
GC::WriteBarrier(this);
}
else
{
prev->Next = this;
GC::WriteBarrier(prev, this);
}
if (Next && Next->ID == ID && ID != 0) if (Next && Next->ID == ID && ID != 0)
Next->Destroy(); // Replace it. Next->Destroy(); // Replace it.
@ -1349,10 +1362,13 @@ void DPSprite::Serialize(FArchive &arc)
void player_t::DestroyPSprites() void player_t::DestroyPSprites()
{ {
DPSprite *pspr = psprites; DPSprite *pspr = psprites;
psprites = nullptr;
while (pspr) while (pspr)
{ {
DPSprite *next = pspr->Next;
pspr->Next = nullptr;
pspr->Destroy(); pspr->Destroy();
pspr = pspr->Next; pspr = next;
} }
} }
@ -1364,12 +1380,27 @@ void player_t::DestroyPSprites()
void DPSprite::Destroy() void DPSprite::Destroy()
{ {
DPSprite **prev = &Owner->psprites; // Do not crash if this gets called on partially initialized objects.
while (*prev != this) if (Owner != nullptr && Owner->psprites != nullptr)
prev = &(*prev)->Next; {
if (Owner->psprites != this)
*prev = Next; {
DPSprite *prev = Owner->psprites;
while (prev != nullptr && prev->Next != this)
prev = prev->Next;
if (prev != nullptr && prev->Next == this)
{
prev->Next = Next;
GC::WriteBarrier(prev, Next);
}
}
else
{
Owner->psprites = Next;
GC::WriteBarrier(Next);
}
}
Super::Destroy(); Super::Destroy();
} }

View file

@ -66,8 +66,8 @@ public:
int GetSprite() const { return Sprite; } int GetSprite() const { return Sprite; }
int GetFrame() const { return Frame; } int GetFrame() const { return Frame; }
FState* GetState() const { return State; } FState* GetState() const { return State; }
DPSprite* GetNext() const { return Next; } DPSprite* GetNext() { return Next; }
TObjPtr<AInventory> GetCaller() const { return Caller; } AInventory* GetCaller() { return Caller; }
double x, y; double x, y;
double oldx, oldy; double oldx, oldy;
@ -82,7 +82,7 @@ private:
void Destroy(); void Destroy();
TObjPtr<AInventory> Caller; TObjPtr<AInventory> Caller;
DPSprite *Next; TObjPtr<DPSprite> Next;
player_t *Owner; player_t *Owner;
FState *State; FState *State;
int Sprite; int Sprite;