- refactored the thinker list.

This was an unorganized set of static members in DThinker but has now been regrouped into something more structured.
This commit is contained in:
Christoph Oelckers 2019-01-30 02:15:48 +01:00
parent e30f116faf
commit 3b4ded5694
11 changed files with 543 additions and 505 deletions

View file

@ -2724,7 +2724,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

@ -112,8 +112,6 @@
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern DThinker *NextToThink;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
namespace GC
@ -282,7 +280,6 @@ static void MarkRoot()
Mark(StatusBar);
M_MarkMenus();
Mark(DIntermissionController::CurrentIntermission);
DThinker::MarkRoots();
Mark(E_FirstEventHandler);
Mark(E_LastEventHandler);
for (auto Level : AllLevels())
@ -300,8 +297,6 @@ static void MarkRoot()
{
Level->Mark();
}
// NextToThink must not be freed while thinkers are ticking.
Mark(NextToThink);
// Mark soft roots.
if (SoftRoots != NULL)
{

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); // The level is needed to tick the lights
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
@ -79,29 +109,11 @@ public:
void ChangeStatNum (int statnum);
static void RunThinkers ();
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();
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;
@ -167,4 +179,5 @@ public:
}
};
extern FThinkerCollection Thinkers;
#endif //__DTHINKER_H__

View file

@ -469,7 +469,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
UnlatchCVars ();
G_VerifySkill();
UnlatchCVars ();
DThinker::DestroyThinkersInList(STAT_STATIC);
Thinkers.DestroyThinkersInList(STAT_STATIC);
if (paused)
{
@ -1466,7 +1466,7 @@ int FLevelLocals::FinishTravel ()
// 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;
}

View file

@ -393,7 +393,7 @@ public:
DThinker *thinker = static_cast<DThinker*>(cls->CreateNew());
assert(thinker->IsKindOf(RUNTIME_CLASS(DThinker)));
thinker->ObjectFlags |= OF_JustSpawned;
DThinker::FreshThinkers[statnum].AddTail(thinker);
Thinkers.Link(thinker, statnum);
thinker->Level = this;
return thinker;
}

View file

@ -295,8 +295,14 @@ void DPusher::Tick ()
void FLevelLocals::AdjustPusher(int tag, int magnitude, int angle, bool wind)
{
DPusher::EPusher type = wind ? DPusher::p_wind : DPusher::p_current;
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.
TArray<FThinkerCollection> Collection;
{

View file

@ -928,7 +928,7 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload)
if (arc.isReading())
{
DThinker::DestroyAllThinkers();
Thinkers.DestroyAllThinkers();
interpolator.ClearInterpolations();
arc.ReadObjects(hubload);
ActiveSequences = 0;
@ -1000,7 +1000,7 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload)
P_SerializeHealthGroups(this, arc);
// [ZZ] serialize events
E_SerializeEvents(arc);
DThinker::SerializeThinkers(arc, hubload);
Thinkers.SerializeThinkers(arc, hubload);
arc("polyobjs", Polyobjects);
SerializeSubsectors(arc, "subsectors");
StatusBar->SerializeMessages(arc);

View file

@ -349,7 +349,7 @@ void P_FreeLevelData ()
E_Shutdown(true);
R_FreePastViewers();
DThinker::DestroyAllThinkers ();
Thinkers.DestroyAllThinkers ();
level.ClearLevelData();
}
@ -573,8 +573,8 @@ void P_Init ()
}
static void P_Shutdown ()
{
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

@ -151,7 +151,7 @@ void P_Ticker (void)
E_WorldTick();
StatusBar->CallTick (); // [RH] moved this here
level.Tick (); // [RH] let the level tick
DThinker::RunThinkers ();
Thinkers.RunThinkers(&level);
//if added by MC: Freeze mode.
if (!level.isFrozen())