Here's my idea for the object pools (This will be completely thread save now, actually). There are two options.
First option:
Code:
public final class ObjectPool {
private static final HashMap<Thread, Stack<Vec2>> vec2Pool = new HashMap<Thread, Stack<Vec2>>();
private static final HashMap<Thread, Stack<Mat22>> mat22Pool = new HashMap<Thread, Stack<Mat22>>();
// others, etc
private ObjectPool() {
};
/**
* Initializes the pools for the thread. This would normally be in the
* get____() logic, but to speed things up we just have each thread call
* this before the pools work.
*/
public static final void initPools() {
vec2Pool.put(Thread.currentThread(), new Stack<Vec2>());
mat22Pool.put(Thread.currentThread(), new Stack<Mat22>());
// others, etc
}
public static final Vec2 getVec2() {
Stack<Vec2> pool = vec2Pool.get(Thread.currentThread());
assert (pool != null) : "Pool was null, make sure you call initPools() for each thread";
if (pool.isEmpty()) {
pool.push(new Vec2());
pool.push(new Vec2());
pool.push(new Vec2());
pool.push(new Vec2());
pool.push(new Vec2());
}
return pool.pop();
}
public static final Vec2 getVec2(Vec2 toCopy) {
Stack<Vec2> pool = vec2Pool.get(Thread.currentThread());
assert (pool != null) : "Pool was null, make sure you call initPools() for each thread";
if (pool.isEmpty()) {
pool.push(new Vec2());
pool.push(new Vec2());
pool.push(new Vec2());
pool.push(new Vec2());
pool.push(new Vec2());
}
return pool.pop().set(toCopy);
}
public static final void returnVec2(Vec2 argToRecycle) {
Stack<Vec2> pool = vec2Pool.get(Thread.currentThread());
assert (pool != null) : "Pool was null, make sure you call initPools() for each thread";
pool.push(argToRecycle);
}
public static final Mat22 getMat22() {
Stack<Mat22> pool = mat22Pool.get(Thread.currentThread());
assert (pool != null) : "Pool was null, make sure you call initPools() for each thread";
if (pool.isEmpty()) {
pool.push(new Mat22());
pool.push(new Mat22());
pool.push(new Mat22());
pool.push(new Mat22());
pool.push(new Mat22());
}
return pool.pop();
}
public static final Mat22 getMat22(Mat22 toCopy) {
Stack<Mat22> pool = mat22Pool.get(Thread.currentThread());
assert (pool != null) : "Pool was null, make sure you call initPools() for each thread";
if (pool.isEmpty()) {
pool.push(new Mat22());
pool.push(new Mat22());
pool.push(new Mat22());
pool.push(new Mat22());
pool.push(new Mat22());
}
return pool.pop().set(toCopy);
}
public static final void returnMat22(Mat22 argToRecycle) {
Stack<Mat22> pool = mat22Pool.get(Thread.currentThread());
assert (pool != null) : "Pool was null, make sure you call initPools() for each thread";
pool.push(argToRecycle);
}
// others, etc
}
Second options (a little slower, but more dynamic):
Code:
public final class ObjectPool {
private static final HashMap<Thread, HashMap<Class<?>,Stack<?>> objectPool = new HashMap<Thread, Stack<Vec2>>();
private ObjectPool() {
};
/**
* Initializes the pools for the thread. This would normally be in the
* get____() logic, but to speed things up we just have each thread call
* this before the pools work.
*/
public static final void initPools() {
HashMap<Class<?>, Stack<?>> objectMap = new HashMap<Class<?>,Stack<?>>();
objectMap.put(Vec2.class, new Stack<Vec2>());
objectMap.put(Mat22.class, new Stack<Mat22>());
// others, etc
objectPool.put(Thead.currentThread(), objectMap );
}
public static final Object getObject(Class<?> argClass){
// basically
HashMap<Class<?>,Stack<?>> map = objectPool.get(Thread.currentThread());
Stack<?> stack = map.get(argClass);
// something in here for creating more if there are none
return stack.pop();
}
}
And that initPools could be removed too, and put into the get logic.
What do you think? I'm leaning more towards the first one.