Making an object pool: suggestions?

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Post Reply
User avatar
Major Cooke
Posts: 8176
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Location: QZDoom Maintenance Team

Making an object pool: suggestions?

Post by Major Cooke »

I thought I'd give an object pool a try for recycling actors (in particularly special effects) a try, simply starting off with just special effects and maybe missile actors.

However, something tells me this may not have as much of a beneficial impact due to the VM versus just spawning and destroying, but I'd like to hear thoughts about that.

Would it be more beneficial just to have all the actors in a single dynamic array and search through them all? Or would it be better to have two arrays and two dedicated functions meant to 'mark' (like memory) the objects as free or used and move them over?

-----
The former means calling fewer functions for the VM to execute, but it has to search through every actor in there (there's multiple types too so I can't just push/pop it).

The latter means shorter searches and can immediately grab the first proper entry that matches the class type as it's guaranteed to be free. This moves over to the used array and is set as such, but there's more VM calls... they're just not as intensive as spawn/destroy.

-----

How it works so far:

Code: Select all

Class D4DHandler : EventHandler
{
	Array<D4DActor> Pool, Free;

	override void WorldUnloaded(WorldEvent e)
	{
		Pool.Clear();
		Free.Clear();
	}

	D4DActor FindFree(Class<D4DActor> mo)
	{
		if (!mo || Free.Size() < 1)
			return null;
			
		for (int i = 0; i < Free.Size(); i++)
		{
			let mo = D4DActor(Free[i]);
			if (mo && mo.GetClass() == mo)
				return mo;
		}
		
		return null;
	}
	
	// Indicate this object is free to re-use.
	void MarkFree(D4DActor mo)
	{
		if (!mo)	return;
		
		int i = Pool.Find(mo);
		if (i < Pool.Size())
		{
			Pool.Delete(i);
			if (Free.Find(mo) >= Free.Size())
				Free.Push(mo);
		}
		mo.freed = true;
	}
	
	// Indicate this object is being used
	void MarkUsed(D4DActor mo)
	{
		if (!mo)	return;
		
		int i = Free.Find(mo);
		if (i < Free.Size())
		{
			Free.Delete(i);
			if (Pool.Find(mo) >= Pool.Size())
				Pool.Push(mo);
		}
		mo.freed = false;
	}
}
-----
Furthermore, when an actor is marked as free, they gain NOINTERACTION, NOSECTOR, don't move, turn completely invisible and their tick functions do nothing until no longer free. When used again, they go through an A_SpawnItemEx-esque chain of code (for now, until I can get the rest of the spawn functions up and going) for 'reinitialization'... which is the reason why it's currently limited to just SFX so I don't have to take care of so many variables that aren't even touched.
Post Reply

Return to “Scripting”