Optimize ObjectPool for debug
This commit is contained in:
@@ -0,0 +1,347 @@
|
||||
package lime.utils;
|
||||
|
||||
import haxe.ds.ObjectMap;
|
||||
|
||||
|
||||
/**
|
||||
A generic object pool for reusing objects.
|
||||
**/
|
||||
#if !lime_debug
|
||||
@:fileXml('tags="haxe,release"')
|
||||
@:noDebug
|
||||
#end
|
||||
#if !js @:generic #end class ObjectPool<T>
|
||||
{
|
||||
/**
|
||||
The number of active objects in the pool.
|
||||
**/
|
||||
public var activeObjects(default, null):Int;
|
||||
|
||||
/**
|
||||
The number of inactive objects in the pool.
|
||||
**/
|
||||
public var inactiveObjects(default, null):Int;
|
||||
|
||||
/**
|
||||
The total size of the object pool (both active and inactive objects).
|
||||
**/
|
||||
public var size(get, set):Null<Int>;
|
||||
|
||||
@:noCompletion private var __inactiveObject0:T;
|
||||
@:noCompletion private var __inactiveObject1:T;
|
||||
@:noCompletion private var __inactiveObjectList:List<T>;
|
||||
@:noCompletion private var __pool:Map<T, Bool>;
|
||||
@:noCompletion private var __size:Null<Int>;
|
||||
|
||||
/**
|
||||
Creates a new ObjectPool instance.
|
||||
|
||||
@param create A function that creates a new instance of type T.
|
||||
@param clean A function that cleans up an instance of type T before it is reused.
|
||||
@param size The maximum size of the object pool.
|
||||
**/
|
||||
public function new(create:Void->T = null, clean:T->Void = null, size:Null<Int> = null)
|
||||
{
|
||||
__pool = cast new ObjectMap();
|
||||
|
||||
activeObjects = 0;
|
||||
inactiveObjects = 0;
|
||||
|
||||
__inactiveObject0 = null;
|
||||
__inactiveObject1 = null;
|
||||
__inactiveObjectList = new List<T>();
|
||||
|
||||
if (create != null)
|
||||
{
|
||||
this.create = create;
|
||||
}
|
||||
if (clean != null)
|
||||
{
|
||||
this.clean = clean;
|
||||
}
|
||||
if (size != null)
|
||||
{
|
||||
this.size = size;
|
||||
}
|
||||
}
|
||||
/**
|
||||
Adds an object to the object pool.
|
||||
|
||||
@param object The object to add to the pool.
|
||||
**/
|
||||
public function add(object:T):Void
|
||||
{
|
||||
if (object != null && !__pool.exists(object))
|
||||
{
|
||||
__pool.set(object, false);
|
||||
clean(object);
|
||||
__addInactive(object);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Dynamic function.
|
||||
|
||||
Cleans up an object before returning it to the pool.
|
||||
|
||||
@param object The object to clean up.
|
||||
**/
|
||||
public dynamic function clean(object:T):Void {}
|
||||
|
||||
/**
|
||||
Clears the object pool, removing all objects.
|
||||
**/
|
||||
public function clear():Void
|
||||
{
|
||||
__pool = cast new ObjectMap();
|
||||
|
||||
activeObjects = 0;
|
||||
inactiveObjects = 0;
|
||||
|
||||
__inactiveObject0 = null;
|
||||
__inactiveObject1 = null;
|
||||
__inactiveObjectList.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
Dynamic function.
|
||||
|
||||
Creates a new Object.
|
||||
**/
|
||||
public dynamic function create():T
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a new object and adds it to the pool, or returns an existing inactive object from the pool.
|
||||
|
||||
@return The object retrieved from the pool, or null if the pool is full and no new objects can be created.
|
||||
**/
|
||||
public function get():T
|
||||
{
|
||||
var object = null;
|
||||
|
||||
if (inactiveObjects > 0)
|
||||
{
|
||||
object = __getInactive();
|
||||
}
|
||||
else if (__size == null || activeObjects < __size)
|
||||
{
|
||||
object = create();
|
||||
|
||||
if (object != null)
|
||||
{
|
||||
__pool.set(object, true);
|
||||
activeObjects++;
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
Releases an active object back into the pool.
|
||||
|
||||
@param object The object to release.
|
||||
**/
|
||||
public function release(object:T):Void
|
||||
{
|
||||
#if lime_pool_debug
|
||||
if (object == null || !__pool.exists(object))
|
||||
{
|
||||
Log.error("Object is not a member of the pool");
|
||||
}
|
||||
else if (!__pool.get(object))
|
||||
{
|
||||
Log.error("Object has already been released");
|
||||
}
|
||||
#end
|
||||
|
||||
activeObjects--;
|
||||
|
||||
if (__size == null || activeObjects + inactiveObjects < __size)
|
||||
{
|
||||
clean(object);
|
||||
__addInactive(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
__pool.remove(object);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Removes an object from the pool.
|
||||
|
||||
@param object The object to remove from the pool.
|
||||
**/
|
||||
public function remove(object:T):Void
|
||||
{
|
||||
if (object != null && __pool.exists(object))
|
||||
{
|
||||
__pool.remove(object);
|
||||
|
||||
if (__inactiveObject0 == object)
|
||||
{
|
||||
__inactiveObject0 = null;
|
||||
inactiveObjects--;
|
||||
}
|
||||
else if (__inactiveObject1 == object)
|
||||
{
|
||||
__inactiveObject1 = null;
|
||||
inactiveObjects--;
|
||||
}
|
||||
else if (__inactiveObjectList.remove(object))
|
||||
{
|
||||
inactiveObjects--;
|
||||
}
|
||||
else
|
||||
{
|
||||
activeObjects--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@:noCompletion private inline function __addInactive(object:T):Void
|
||||
{
|
||||
#if lime_pool_debug
|
||||
__pool.set(object, false);
|
||||
#end
|
||||
|
||||
if (__inactiveObject0 == null)
|
||||
{
|
||||
__inactiveObject0 = object;
|
||||
}
|
||||
else if (__inactiveObject1 == null)
|
||||
{
|
||||
__inactiveObject1 = object;
|
||||
}
|
||||
else
|
||||
{
|
||||
__inactiveObjectList.add(object);
|
||||
}
|
||||
|
||||
inactiveObjects++;
|
||||
}
|
||||
|
||||
@:noCompletion private inline function __getInactive():T
|
||||
{
|
||||
var object = null;
|
||||
|
||||
if (__inactiveObject0 != null)
|
||||
{
|
||||
object = __inactiveObject0;
|
||||
__inactiveObject0 = null;
|
||||
}
|
||||
else if (__inactiveObject1 != null)
|
||||
{
|
||||
object = __inactiveObject1;
|
||||
__inactiveObject1 = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
object = __inactiveObjectList.pop();
|
||||
|
||||
if (__inactiveObjectList.length > 0)
|
||||
{
|
||||
__inactiveObject0 = __inactiveObjectList.pop();
|
||||
}
|
||||
|
||||
if (__inactiveObjectList.length > 0)
|
||||
{
|
||||
__inactiveObject1 = __inactiveObjectList.pop();
|
||||
}
|
||||
}
|
||||
|
||||
#if lime_pool_debug
|
||||
__pool.set(object, true);
|
||||
#end
|
||||
|
||||
inactiveObjects--;
|
||||
activeObjects++;
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
@:noCompletion private function __removeInactive(count:Int):Void
|
||||
{
|
||||
if (count <= 0 || inactiveObjects == 0) return;
|
||||
|
||||
if (__inactiveObject0 != null)
|
||||
{
|
||||
__pool.remove(__inactiveObject0);
|
||||
__inactiveObject0 = null;
|
||||
inactiveObjects--;
|
||||
count--;
|
||||
}
|
||||
|
||||
if (count == 0 || inactiveObjects == 0) return;
|
||||
|
||||
if (__inactiveObject1 != null)
|
||||
{
|
||||
__pool.remove(__inactiveObject1);
|
||||
__inactiveObject1 = null;
|
||||
inactiveObjects--;
|
||||
count--;
|
||||
}
|
||||
|
||||
if (count == 0 || inactiveObjects == 0) return;
|
||||
|
||||
for (object in __inactiveObjectList)
|
||||
{
|
||||
__pool.remove(object);
|
||||
__inactiveObjectList.remove(object);
|
||||
inactiveObjects--;
|
||||
count--;
|
||||
|
||||
if (count == 0 || inactiveObjects == 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get & Set Methods
|
||||
@:noCompletion private function get_size():Null<Int>
|
||||
{
|
||||
return __size;
|
||||
}
|
||||
|
||||
@:noCompletion private function set_size(value:Null<Int>):Null<Int>
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
__size = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var current = inactiveObjects + activeObjects;
|
||||
__size = value;
|
||||
|
||||
if (current > value)
|
||||
{
|
||||
__removeInactive(current - value);
|
||||
}
|
||||
else if (value > current)
|
||||
{
|
||||
var object;
|
||||
|
||||
for (i in 0...(value - current))
|
||||
{
|
||||
object = create();
|
||||
|
||||
if (object != null)
|
||||
{
|
||||
__pool.set(object, false);
|
||||
__inactiveObjectList.add(object);
|
||||
inactiveObjects++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user