- changed global thinker storage into a struct instead of some static variables inside DThinker.

As it is now it can handle multiple thinker collections for different levels, but right now there's still only one global list for everything.
This commit is contained in:
Christoph Oelckers 2019-01-14 18:50:39 +01:00
parent dd5addd6ad
commit 703cb9cf4e
11 changed files with 545 additions and 514 deletions

View file

@ -2585,7 +2585,7 @@ void D_DoomMain (void)
gamestate = GS_FULLCONSOLE;
Net_NewMakeTic ();
ForAllLevels([](FLevelLocals *Level) {
DThinker::RunThinkers (Level);
Thinkers.RunThinkers (Level);
});
gamestate = GS_STARTUP;
@ -2702,7 +2702,7 @@ void D_DoomMain (void)
// clean up game state
ST_Clear();
D_ErrorCleanup ();
DThinker::DestroyThinkersInList(STAT_STATIC);
Thinkers.DestroyThinkersInList(STAT_STATIC);
E_Shutdown(false);
P_FreeLevelData();

View file

@ -282,7 +282,6 @@ static void MarkRoot()
Mark(StatusBar);
M_MarkMenus();
Mark(DIntermissionController::CurrentIntermission);
DThinker::MarkRoots();
Mark(E_FirstEventHandler);
Mark(E_LastEventHandler);

File diff suppressed because it is too large Load diff

View file

@ -53,13 +53,43 @@ enum { MAX_STATNUM = 127 };
// Doubly linked ring list of thinkers
struct FThinkerList
{
FThinkerList() : Sentinel(0) {}
// No destructor. If this list goes away it's the GC's task to clean the orphaned thinkers. Otherwise this may clash with engine shutdown.
void AddTail(DThinker *thinker);
DThinker *GetHead() const;
DThinker *GetTail() const;
bool IsEmpty() const;
void DestroyThinkers();
bool DoDestroyThinkers();
int TickThinkers(FThinkerList *dest); // Returns: # of thinkers ticked
int ProfileThinkers(FThinkerList *dest);
void SaveList(FSerializer &arc);
DThinker *Sentinel;
private:
DThinker *Sentinel = nullptr;
friend struct FThinkerCollection;
};
struct FThinkerCollection
{
void DestroyThinkersInList(int statnum)
{
Thinkers[statnum].DestroyThinkers();
FreshThinkers[statnum].DestroyThinkers();
}
void RunThinkers(FLevelLocals *Level);
void DestroyAllThinkers();
void SerializeThinkers(FSerializer &arc, bool keepPlayers);
void MarkRoots();
DThinker *FirstThinker(int statnum);
void Link(DThinker *thinker, int statnum);
private:
FThinkerList Thinkers[MAX_STATNUM + 2];
FThinkerList FreshThinkers[MAX_STATNUM + 1];
friend class FThinkerIterator;
};
class DThinker : public DObject
@ -89,35 +119,15 @@ public:
void ChangeStatNum (int statnum);
static void RunThinkers (FLevelLocals *Level);
static void RunThinkers (int statnum);
static void DestroyAllThinkers ();
static void DestroyThinkersInList(int statnum)
{
DestroyThinkersInList(Thinkers[statnum]);
DestroyThinkersInList(FreshThinkers[statnum]);
}
static void SerializeThinkers(FSerializer &arc, bool keepPlayers);
static void MarkRoots();
static DThinker *FirstThinker (int statnum);
FLevelLocals *Level;
protected:
DThinker() = default;
private:
static void DestroyThinkersInList (FThinkerList &list);
static bool DoDestroyThinkersInList(FThinkerList &list);
static int TickThinkers (FThinkerList *list, FThinkerList *dest); // Returns: # of thinkers ticked
static int ProfileThinkers(FThinkerList *list, FThinkerList *dest);
static void SaveList(FSerializer &arc, DThinker *node);
void Remove();
static FThinkerList Thinkers[MAX_STATNUM+2]; // Current thinkers
static FThinkerList FreshThinkers[MAX_STATNUM+1]; // Newly created thinkers
friend struct FThinkerList;
friend struct FThinkerCollection;
friend class FThinkerIterator;
friend class DObject;
friend class FSerializer;
@ -194,4 +204,5 @@ T* CreateThinker(Args&&... args)
return object;
}
extern FThinkerCollection Thinkers;
#endif //__DTHINKER_H__

View file

@ -489,7 +489,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
UnlatchCVars ();
G_VerifySkill();
UnlatchCVars ();
DThinker::DestroyThinkersInList(STAT_STATIC);
Thinkers.DestroyThinkersInList(STAT_STATIC);
if (paused)
{
@ -1515,7 +1515,7 @@ int G_FinishTravel (FLevelLocals *Level)
// make sure that, after travelling has completed, no travelling thinkers are left.
// Since this list is excluded from regular thinker cleaning, anything that may survive through here
// will endlessly multiply and severely break the following savegames or just simply crash on broken pointers.
DThinker::DestroyThinkersInList(STAT_TRAVELLING);
Thinkers.DestroyThinkersInList(STAT_TRAVELLING);
return failnum;
}
@ -1529,7 +1529,7 @@ FLevelLocals::~FLevelLocals()
{
SN_StopAllSequences(this);
ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
DThinker::DestroyAllThinkers();
Thinkers.DestroyAllThinkers();
// delete allocated data in the level arrays.
if (sectors.Size() > 0)
@ -2217,6 +2217,7 @@ void FLevelLocals::Mark()
GC::Mark(ACSThinker);
GC::Mark(interpolator.Head);
GC::Mark(SequenceListHead);
Thinkers.MarkRoots();
canvasTextureInfo.Mark();
for (auto &c : CorpseQueue)

View file

@ -533,7 +533,7 @@ CUSTOM_CVAR (Int, cl_maxdecals, 1024, CVAR_ARCHIVE)
{
while (Level->ImpactDecalCount > self)
{
DThinker *thinker = DThinker::FirstThinker(STAT_AUTODECAL);
DThinker *thinker = Thinkers.FirstThinker(STAT_AUTODECAL);
if (thinker != NULL)
{
thinker->Destroy();
@ -552,7 +552,7 @@ void DImpactDecal::CheckMax ()
{
if (++Level->ImpactDecalCount >= cl_maxdecals)
{
DThinker *thinker = DThinker::FirstThinker (STAT_AUTODECAL);
DThinker *thinker = Thinkers.FirstThinker (STAT_AUTODECAL);
if (thinker != NULL)
{
thinker->Destroy();

View file

@ -415,8 +415,15 @@ void P_SpawnPushers (FLevelLocals *Level)
}
}
void AdjustPusher (FLevelLocals *Level, int tag, int magnitude, int angle, bool wind)
{
struct FThinkerCollection
{
int RefNum;
DThinker *Obj;
};
DPusher::EPusher type = wind? DPusher::p_wind : DPusher::p_current;
// Find pushers already attached to the sector, and change their parameters.

View file

@ -914,7 +914,7 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload)
if (arc.isReading())
{
DThinker::DestroyAllThinkers();
Thinkers.DestroyAllThinkers();
Level->interpolator.ClearInterpolations();
arc.ReadObjects(hubload);
}
@ -977,7 +977,7 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload)
P_SerializeHealthGroups(Level, arc);
// [ZZ] serialize events
E_SerializeEvents(arc);
DThinker::SerializeThinkers(arc, hubload);
Thinkers.SerializeThinkers(arc, hubload);
arc("polyobjs", Level->Polyobjects);
SerializeSubsectors(arc, Level, "subsectors");
StatusBar->SerializeMessages(arc);

View file

@ -426,7 +426,7 @@ static void P_Shutdown ()
{
delete currentSession;
currentSession = nullptr;
DThinker::DestroyThinkersInList(STAT_STATIC);
Thinkers.DestroyThinkersInList(STAT_STATIC);
P_FreeLevelData ();
// [ZZ] delete global event handlers
E_Shutdown(false);

View file

@ -40,12 +40,6 @@ class FScanner;
struct level_info_t;
struct FDoorAnimation;
struct FThinkerCollection
{
int RefNum;
DThinker *Obj;
};
enum class EScroll : int
{
sc_side,

View file

@ -152,7 +152,7 @@ void P_Ticker (void)
memset(&Level->Scrolls[0], 0, sizeof(Level->Scrolls[0]) * Level->Scrolls.Size());
}
DThinker::RunThinkers(Level);
Thinkers.RunThinkers(Level);
//if added by MC: Freeze mode.
if (!currentSession->isFrozen())