diff --git a/src/d_think.h b/src/d_think.h index efc1589bf62e277a67ab309f05d33d66af741865..58912458783a2f3b2187e50ebaf00a667a0e0a78 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -51,6 +51,7 @@ typedef struct thinker_s // killough 11/98: count of how many other objects reference // this one using pointers. Used for garbage collection. INT32 references; + boolean cachable; #ifdef PARANOIA INT32 debug_mobjtype; diff --git a/src/p_local.h b/src/p_local.h index 2d97f19da9f5d1bca3979cc64ff428d8996dcce7..454c39d5f17e178f664274fb7295ff347822543e 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -71,6 +71,7 @@ typedef enum NUM_THINKERLISTS } thinklistnum_t; /**< Thinker lists. */ extern thinker_t thlist[]; +extern mobj_t *mobjcache; void P_InitThinkers(void); void P_AddThinker(const thinklistnum_t n, thinker_t *thinker); diff --git a/src/p_mobj.c b/src/p_mobj.c index 6658cdfcc69f70621e14dee7570e30641557bd4e..c94bd51f215afe141e525300d6b7671fbca03656 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -45,6 +45,8 @@ actioncache_t actioncachehead; static mobj_t *overlaycap = NULL; +mobj_t *mobjcache = NULL; + void P_InitCachedActions(void) { actioncachehead.prev = actioncachehead.next = &actioncachehead; @@ -10787,7 +10789,16 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) if (type == MT_NULL) return NULL; - mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + if (mobjcache != NULL) + { + mobj = mobjcache; + mobjcache = mobjcache->hnext; + memset(mobj, 0, sizeof(*mobj)); + } + else + { + mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + } // this is officially a mobj, declared as soon as possible. mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; @@ -11402,7 +11413,9 @@ void P_RemoveMobj(mobj_t *mobj) INT32 prevreferences; if (!mobj->thinker.references) { - Z_Free(mobj); // No refrrences? Can be removed immediately! :D + // no references, dump it directly in the mobj cache + mobj->hnext = mobjcache; + mobjcache = mobj; return; } diff --git a/src/p_setup.c b/src/p_setup.c index 442db943091904fff17f6eeefcb2368fed0ef757..6f5ec17dcd59814ddae0032911704c3c9e4f6b16 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7876,6 +7876,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) Patch_FreeTag(PU_PATCH_LOWPRIORITY); Patch_FreeTag(PU_PATCH_ROTATED); Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); + mobjcache = NULL; R_InitializeLevelInterpolators(); diff --git a/src/p_tick.c b/src/p_tick.c index c6832bfc3ee90d3ee0bc5bd1cd1e13e572bd753f..dca806ebee2810b5556f8cf6d288c7ffd1607069 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -217,6 +217,7 @@ void P_AddThinker(const thinklistnum_t n, thinker_t *thinker) thlist[n].prev = thinker; thinker->references = 0; // killough 11/98: init reference counter to 0 + thinker->cachable = n == THINK_MOBJ; #ifdef PARANOIA thinker->debug_mobjtype = MT_NULL; @@ -320,7 +321,16 @@ void P_RemoveThinkerDelayed(thinker_t *thinker) (next->prev = currentthinker = thinker->prev)->next = next; R_DestroyLevelInterpolators(thinker); - Z_Free(thinker); + if (thinker->cachable) + { + // put cachable thinkers in the mobj cache, so we can avoid allocations + ((mobj_t *)thinker)->hnext = mobjcache; + mobjcache = (mobj_t *)thinker; + } + else + { + Z_Free(thinker); + } } //