forked from MagicBane/Server
Project cleanup pre merge.
This commit is contained in:
@@ -15,55 +15,55 @@ import java.nio.ByteBuffer;
|
||||
|
||||
public class ByteBufferPool extends LinkedObjectPool<ByteBuffer> {
|
||||
|
||||
private final int defaultBufferSize;
|
||||
private final int defaultBufferSize;
|
||||
|
||||
public ByteBufferPool(int defaultBufferSize) {
|
||||
super(ObjectPool.DEFAULT_SIZE);
|
||||
this.defaultBufferSize = defaultBufferSize;
|
||||
}
|
||||
public ByteBufferPool(int defaultBufferSize) {
|
||||
super(ObjectPool.DEFAULT_SIZE);
|
||||
this.defaultBufferSize = defaultBufferSize;
|
||||
}
|
||||
|
||||
public ByteBufferPool(int size, int defaultBufferSize) {
|
||||
super(size);
|
||||
this.defaultBufferSize = defaultBufferSize;
|
||||
}
|
||||
public ByteBufferPool(int size, int defaultBufferSize) {
|
||||
super(size);
|
||||
this.defaultBufferSize = defaultBufferSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuffer makeNewObject() {
|
||||
return ByteBuffer.allocate(defaultBufferSize);
|
||||
}
|
||||
@Override
|
||||
protected ByteBuffer makeNewObject() {
|
||||
return ByteBuffer.allocate(defaultBufferSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetObject(ByteBuffer obj) {
|
||||
obj.clear();
|
||||
}
|
||||
@Override
|
||||
protected void resetObject(ByteBuffer obj) {
|
||||
obj.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer get() {
|
||||
@Override
|
||||
public ByteBuffer get() {
|
||||
// Logger.debug("ByteBufferPool.get() BB.capacity(): " + bb.capacity()
|
||||
// + ", bb.pos(): " + bb.position() + ". Pool.size() is now: "
|
||||
// + this.getPoolSize());
|
||||
return super.get();
|
||||
}
|
||||
// + ", bb.pos(): " + bb.position() + ". Pool.size() is now: "
|
||||
// + this.getPoolSize());
|
||||
return super.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(ByteBuffer bb) {
|
||||
if(bb.isDirect())
|
||||
super.put(bb);
|
||||
// Logger.debug("ByteBufferPool.put() BB.capacity(): " + bb.capacity()
|
||||
// + ", bb.pos(): " + bb.position() + ". Pool.size() is now: "
|
||||
// + this.getPoolSize());
|
||||
}
|
||||
@Override
|
||||
public void put(ByteBuffer bb) {
|
||||
if (bb.isDirect())
|
||||
super.put(bb);
|
||||
// Logger.debug("ByteBufferPool.put() BB.capacity(): " + bb.capacity()
|
||||
// + ", bb.pos(): " + bb.position() + ". Pool.size() is now: "
|
||||
// + this.getPoolSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handlePoolExhaustion() {
|
||||
Logger.debug("ByteBufferPool(" + defaultBufferSize
|
||||
+ ") exhausted, making more objects.");
|
||||
@Override
|
||||
protected void handlePoolExhaustion() {
|
||||
Logger.debug("ByteBufferPool(" + defaultBufferSize
|
||||
+ ") exhausted, making more objects.");
|
||||
|
||||
// If none exist, make (and pool) a few
|
||||
// Dont sync the loop, let the makeNewObject()
|
||||
// call return before locking the pool object
|
||||
for (int i = 0; i < 5; ++i)
|
||||
this.makeAndAdd();
|
||||
}
|
||||
// If none exist, make (and pool) a few
|
||||
// Dont sync the loop, let the makeNewObject()
|
||||
// call return before locking the pool object
|
||||
for (int i = 0; i < 5; ++i)
|
||||
this.makeAndAdd();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2013 MagicBane Emulator Project
|
||||
* All Rights Reserved
|
||||
* All Rights Reserved
|
||||
*/
|
||||
package engine.pooling;
|
||||
|
||||
@@ -12,44 +12,44 @@ import java.sql.SQLException;
|
||||
|
||||
public class ConnectionPool extends LinkedObjectPool<Connection> {
|
||||
|
||||
static {
|
||||
//Register the Driver
|
||||
try {
|
||||
Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
|
||||
} catch (InstantiationException | ClassNotFoundException | IllegalAccessException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
static {
|
||||
//Register the Driver
|
||||
try {
|
||||
Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
|
||||
} catch (InstantiationException | ClassNotFoundException | IllegalAccessException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ConnectionPool() {
|
||||
super(10);
|
||||
}
|
||||
public ConnectionPool() {
|
||||
super(10);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Connection makeNewObject() {
|
||||
// Protocol
|
||||
String sqlURI = "jdbc:mysql://";
|
||||
sqlURI += ConfigManager.MB_DATABASE_ADDRESS.getValue() + ':' + ConfigManager.MB_DATABASE_PORT.getValue();
|
||||
sqlURI += '/' + ConfigManager.MB_DATABASE_NAME.getValue() + '?';
|
||||
sqlURI += "useServerPrepStmts=true";
|
||||
sqlURI += "&cachePrepStmts=false";
|
||||
sqlURI += "&cacheCallableStmts=true";
|
||||
sqlURI += "&characterEncoding=utf8";
|
||||
@Override
|
||||
protected Connection makeNewObject() {
|
||||
// Protocol
|
||||
String sqlURI = "jdbc:mysql://";
|
||||
sqlURI += ConfigManager.MB_DATABASE_ADDRESS.getValue() + ':' + ConfigManager.MB_DATABASE_PORT.getValue();
|
||||
sqlURI += '/' + ConfigManager.MB_DATABASE_NAME.getValue() + '?';
|
||||
sqlURI += "useServerPrepStmts=true";
|
||||
sqlURI += "&cachePrepStmts=false";
|
||||
sqlURI += "&cacheCallableStmts=true";
|
||||
sqlURI += "&characterEncoding=utf8";
|
||||
|
||||
Connection out = null;
|
||||
try {
|
||||
out = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(),
|
||||
ConfigManager.MB_DATABASE_PASS.getValue());
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Connection out = null;
|
||||
try {
|
||||
out = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(),
|
||||
ConfigManager.MB_DATABASE_PASS.getValue());
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetObject(Connection obj) {
|
||||
@Override
|
||||
protected void resetObject(Connection obj) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,127 +16,125 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public abstract class LinkedObjectPool<T> {
|
||||
private final LinkedBlockingQueue<T> pool;
|
||||
private final AtomicInteger poolSize;
|
||||
private final LinkedBlockingQueue<T> pool;
|
||||
private final AtomicInteger poolSize;
|
||||
|
||||
/**
|
||||
* Constructor that allows the caller to specify initial array size and
|
||||
* percent of prefill.
|
||||
*
|
||||
* @param size
|
||||
* - initial size for the containing array (pool)
|
||||
*/
|
||||
public LinkedObjectPool(int size) {
|
||||
this.pool = new LinkedBlockingQueue<>();
|
||||
this.poolSize = new AtomicInteger();
|
||||
}
|
||||
/**
|
||||
* Constructor that allows the caller to specify initial array size and
|
||||
* percent of prefill.
|
||||
*
|
||||
* @param size - initial size for the containing array (pool)
|
||||
*/
|
||||
public LinkedObjectPool(int size) {
|
||||
this.pool = new LinkedBlockingQueue<>();
|
||||
this.poolSize = new AtomicInteger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default Constructor that uses default initial Array size and percent
|
||||
* prefill values
|
||||
*/
|
||||
public LinkedObjectPool() {
|
||||
this(0);
|
||||
}
|
||||
/**
|
||||
* Default Constructor that uses default initial Array size and percent
|
||||
* prefill values
|
||||
*/
|
||||
public LinkedObjectPool() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces pool to add <i>numberOfObjects</i> to the pool. This may cause
|
||||
* internal ArrayList to resize.
|
||||
*
|
||||
* @param numberOfObjects
|
||||
*/
|
||||
public void fill(int numberOfObjects) {
|
||||
for (int i = 0; i < numberOfObjects; ++i)
|
||||
this.makeAndAdd();
|
||||
}
|
||||
/**
|
||||
* Forces pool to add <i>numberOfObjects</i> to the pool. This may cause
|
||||
* internal ArrayList to resize.
|
||||
*
|
||||
* @param numberOfObjects
|
||||
*/
|
||||
public void fill(int numberOfObjects) {
|
||||
for (int i = 0; i < numberOfObjects; ++i)
|
||||
this.makeAndAdd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces subclasses to implement factory routine for object creation.
|
||||
*/
|
||||
protected abstract T makeNewObject();
|
||||
/**
|
||||
* Forces subclasses to implement factory routine for object creation.
|
||||
*/
|
||||
protected abstract T makeNewObject();
|
||||
|
||||
/**
|
||||
* Forces subclasses to implement a way to reset object to a reusable state.
|
||||
*/
|
||||
protected abstract void resetObject(T obj);
|
||||
/**
|
||||
* Forces subclasses to implement a way to reset object to a reusable state.
|
||||
*/
|
||||
protected abstract void resetObject(T obj);
|
||||
|
||||
/**
|
||||
* Generic Get routine. If the pool is empty, then one (or more) of T type
|
||||
* objects will be created. If more than one T is created, then they will be
|
||||
* put into the pool. One T will always be created and returned.
|
||||
*/
|
||||
public T get() {
|
||||
T obj = pool.poll();
|
||||
|
||||
if(obj == null) {
|
||||
//Oops pool is empty.. make a new obj
|
||||
obj = this.makeNewObject();
|
||||
} else {
|
||||
poolSize.decrementAndGet();
|
||||
}
|
||||
/**
|
||||
* Generic Get routine. If the pool is empty, then one (or more) of T type
|
||||
* objects will be created. If more than one T is created, then they will be
|
||||
* put into the pool. One T will always be created and returned.
|
||||
*/
|
||||
public T get() {
|
||||
T obj = pool.poll();
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic put routine. If the current pool size is below threshold, this
|
||||
* object will be pooled, otherwise it will be NULL'ed and scheduled for
|
||||
* Garbage Collection
|
||||
*
|
||||
* @param obj
|
||||
*/
|
||||
public void put(T obj) {
|
||||
//Logger.debug("Objectpool.put(). Pool size: " + pool.size());
|
||||
this.resetObject(obj);
|
||||
this.poolSize.incrementAndGet();
|
||||
this.pool.add(obj);
|
||||
}
|
||||
if (obj == null) {
|
||||
//Oops pool is empty.. make a new obj
|
||||
obj = this.makeNewObject();
|
||||
} else {
|
||||
poolSize.decrementAndGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method. Attempts to create and add a new <i>T</i> object. If this
|
||||
* fails, an error is logged.
|
||||
*/
|
||||
protected final void makeAndAdd() {
|
||||
T obj = this.makeNewObject();
|
||||
if (obj == null) {
|
||||
Logger.error("Pooling failure: Object creation failed.");
|
||||
} else {
|
||||
this.put(obj);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the current size of the pool, not the maximum capacity of the
|
||||
* Array holding the pool.
|
||||
*/
|
||||
public final int getPoolSize() {
|
||||
return this.poolSize.get();
|
||||
}
|
||||
/**
|
||||
* Generic put routine. If the current pool size is below threshold, this
|
||||
* object will be pooled, otherwise it will be NULL'ed and scheduled for
|
||||
* Garbage Collection
|
||||
*
|
||||
* @param obj
|
||||
*/
|
||||
public void put(T obj) {
|
||||
//Logger.debug("Objectpool.put(). Pool size: " + pool.size());
|
||||
this.resetObject(obj);
|
||||
this.poolSize.incrementAndGet();
|
||||
this.pool.add(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Culls the pool and removes half of the stored objects. Removed objects
|
||||
* are NULL'ed and scheduled form Garbage Collection.
|
||||
*
|
||||
* @return the number of Objects removed from the pool.
|
||||
*/
|
||||
public int cullHalf() {
|
||||
int full, half;
|
||||
full = this.getPoolSize();
|
||||
if (full < 1) {
|
||||
return full;
|
||||
}
|
||||
/**
|
||||
* Helper method. Attempts to create and add a new <i>T</i> object. If this
|
||||
* fails, an error is logged.
|
||||
*/
|
||||
protected final void makeAndAdd() {
|
||||
T obj = this.makeNewObject();
|
||||
if (obj == null) {
|
||||
Logger.error("Pooling failure: Object creation failed.");
|
||||
} else {
|
||||
this.put(obj);
|
||||
}
|
||||
}
|
||||
|
||||
half = (full / 2);
|
||||
/**
|
||||
* @return the current size of the pool, not the maximum capacity of the
|
||||
* Array holding the pool.
|
||||
*/
|
||||
public final int getPoolSize() {
|
||||
return this.poolSize.get();
|
||||
}
|
||||
|
||||
for (int i = 0; i < (full / 2); ++i) {
|
||||
T obj = this.pool.poll();
|
||||
obj = null; // Null out for GC
|
||||
}
|
||||
return half;
|
||||
}
|
||||
/**
|
||||
* Culls the pool and removes half of the stored objects. Removed objects
|
||||
* are NULL'ed and scheduled form Garbage Collection.
|
||||
*
|
||||
* @return the number of Objects removed from the pool.
|
||||
*/
|
||||
public int cullHalf() {
|
||||
int full, half;
|
||||
full = this.getPoolSize();
|
||||
if (full < 1) {
|
||||
return full;
|
||||
}
|
||||
|
||||
protected void handlePoolExhaustion() {
|
||||
//Not needed in this implementation
|
||||
}
|
||||
half = (full / 2);
|
||||
|
||||
for (int i = 0; i < (full / 2); ++i) {
|
||||
T obj = this.pool.poll();
|
||||
obj = null; // Null out for GC
|
||||
}
|
||||
return half;
|
||||
}
|
||||
|
||||
protected void handlePoolExhaustion() {
|
||||
//Not needed in this implementation
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,175 +16,169 @@ import java.util.HashMap;
|
||||
|
||||
public class MultisizeByteBufferPool {
|
||||
|
||||
/**
|
||||
* Maps a power of two (0-30) to a BB Pool
|
||||
*/
|
||||
private final HashMap<Integer, ByteBufferPool> powerToPoolMap = new HashMap<>();
|
||||
/**
|
||||
* List of the powers of two from 2^0 to 2^30. The index of the array
|
||||
* corresponds to the power of two. Example: If you'd like to quickly lookup
|
||||
* 2^19, then reference powersOfTwo[19]
|
||||
*/
|
||||
public static final int[] powersOfTwo = {
|
||||
1, // 2^0
|
||||
2, // 2^1
|
||||
4, // 2^2
|
||||
8, // 2^3
|
||||
16, // 2^4
|
||||
32, // 2^5
|
||||
64, // 2^6
|
||||
128, // 2^7
|
||||
256, // 2^8
|
||||
512, // 2^9
|
||||
1024, // 2^10
|
||||
2048, // 2^11
|
||||
4096, // 2^12
|
||||
8192, // 2^13
|
||||
16384, // 2^14
|
||||
32768, // 2^15
|
||||
65536, // 2^16
|
||||
131072, // 2^17
|
||||
262144, // 2^18
|
||||
524288, // 2^19
|
||||
1048576, // 2^20
|
||||
2097152, // 2^21
|
||||
4194304, // 2^22
|
||||
8388608, // 2^23
|
||||
16777216, // 2^24
|
||||
33554432, // 2^25
|
||||
67108864, // 2^26
|
||||
134217728, // 2^27
|
||||
268435456, // 2^28
|
||||
536870912, // 2^29
|
||||
1073741824, // 2^30
|
||||
};
|
||||
/**
|
||||
* Maps a power of two (0-30) to a BB Pool
|
||||
*/
|
||||
private final HashMap<Integer, ByteBufferPool> powerToPoolMap = new HashMap<>();
|
||||
|
||||
public MultisizeByteBufferPool() {
|
||||
super();
|
||||
}
|
||||
public MultisizeByteBufferPool() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a ByteBuffer that is of the size 2^<i>powerOfTwo</i> from the
|
||||
* appropriate pool.
|
||||
*
|
||||
* @param powerOfTwo
|
||||
* int range of 0-30
|
||||
* @return
|
||||
*/
|
||||
public ByteBuffer getBuffer(int powerOfTwo) {
|
||||
// Validate input
|
||||
if (powerOfTwo > 30 || powerOfTwo < 0) {
|
||||
Logger.error("powerOfTwo out of range (0-30) in getBuffer(). Got: " + powerOfTwo);
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Returns the next power of two that is larger than or equal too the input
|
||||
* <i>value</i>
|
||||
*
|
||||
* @param value
|
||||
* @return the power of two that is larger than or equal too the input
|
||||
* <i>value</i>. A return of -1 indicates out of range.
|
||||
*/
|
||||
public static int getPowerThatWillFit(final int value) {
|
||||
return (value == 0 ? 0 : 32 - Integer.numberOfLeadingZeros(value - 1));
|
||||
}
|
||||
|
||||
// Check to see if there is a pool for this size
|
||||
ByteBufferPool bbp = this.getByteBufferPool(powerOfTwo);
|
||||
return bbp.get();
|
||||
}
|
||||
private static ByteBufferPool makeByteBufferPool(int bbInitialSize) {
|
||||
return new ByteBufferPool(bbInitialSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal getter to provide synchronization. Adds ByteBufferPool if not mapped.
|
||||
*
|
||||
* @param powerOfTwo
|
||||
* @return
|
||||
*/
|
||||
private ByteBufferPool getByteBufferPool(Integer powerOfTwo) {
|
||||
synchronized (this.powerToPoolMap) {
|
||||
// Check to see if there is a pool for this size
|
||||
ByteBufferPool bbp = powerToPoolMap.get(powerOfTwo);
|
||||
/**
|
||||
* Gets a ByteBuffer that is of the size 2^<i>powerOfTwo</i> from the
|
||||
* appropriate pool.
|
||||
*
|
||||
* @param powerOfTwo int range of 0-30
|
||||
* @return
|
||||
*/
|
||||
public ByteBuffer getBuffer(int powerOfTwo) {
|
||||
// Validate input
|
||||
if (powerOfTwo > 30 || powerOfTwo < 0) {
|
||||
Logger.error("powerOfTwo out of range (0-30) in getBuffer(). Got: " + powerOfTwo);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (bbp == null) {
|
||||
bbp = MultisizeByteBufferPool.makeByteBufferPool(powersOfTwo[powerOfTwo]);
|
||||
this.putByteBufferPool(powerOfTwo, bbp);
|
||||
}
|
||||
return bbp;
|
||||
}
|
||||
}
|
||||
// Check to see if there is a pool for this size
|
||||
ByteBufferPool bbp = this.getByteBufferPool(powerOfTwo);
|
||||
return bbp.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal setter to provide synchronization
|
||||
*
|
||||
* @param powerOfTwo
|
||||
* @param bbp
|
||||
* @return
|
||||
*/
|
||||
private ByteBufferPool putByteBufferPool(Integer powerOfTwo,
|
||||
/**
|
||||
* Internal getter to provide synchronization. Adds ByteBufferPool if not mapped.
|
||||
*
|
||||
* @param powerOfTwo
|
||||
* @return
|
||||
*/
|
||||
private ByteBufferPool getByteBufferPool(Integer powerOfTwo) {
|
||||
synchronized (this.powerToPoolMap) {
|
||||
// Check to see if there is a pool for this size
|
||||
ByteBufferPool bbp = powerToPoolMap.get(powerOfTwo);
|
||||
|
||||
if (bbp == null) {
|
||||
bbp = MultisizeByteBufferPool.makeByteBufferPool(powersOfTwo[powerOfTwo]);
|
||||
this.putByteBufferPool(powerOfTwo, bbp);
|
||||
}
|
||||
return bbp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal setter to provide synchronization
|
||||
*
|
||||
* @param powerOfTwo
|
||||
* @param bbp
|
||||
* @return
|
||||
*/
|
||||
private ByteBufferPool putByteBufferPool(Integer powerOfTwo,
|
||||
ByteBufferPool bbp) {
|
||||
synchronized (this.powerToPoolMap) {
|
||||
return powerToPoolMap.put(powerOfTwo, bbp);
|
||||
}
|
||||
}
|
||||
synchronized (this.powerToPoolMap) {
|
||||
return powerToPoolMap.put(powerOfTwo, bbp);
|
||||
}
|
||||
}
|
||||
|
||||
public ByteBuffer getBufferToFit(int numOfBytes) {
|
||||
int pow = MultisizeByteBufferPool.getPowerThatWillFit(numOfBytes);
|
||||
return this.getBuffer(pow);
|
||||
}
|
||||
public ByteBuffer getBufferToFit(int numOfBytes) {
|
||||
int pow = MultisizeByteBufferPool.getPowerThatWillFit(numOfBytes);
|
||||
return this.getBuffer(pow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a ByteBuffer that is of the size 2^<i>powerOfTwo</i> back into the
|
||||
* appropriate pool.
|
||||
*
|
||||
* @param bb
|
||||
* - Bytebuffer to put into a pool
|
||||
*
|
||||
*/
|
||||
public void putBuffer(ByteBuffer bb) {
|
||||
/**
|
||||
* Puts a ByteBuffer that is of the size 2^<i>powerOfTwo</i> back into the
|
||||
* appropriate pool.
|
||||
*
|
||||
* @param bb - Bytebuffer to put into a pool
|
||||
*/
|
||||
public void putBuffer(ByteBuffer bb) {
|
||||
|
||||
if (bb == null)
|
||||
return;
|
||||
if (bb == null)
|
||||
return;
|
||||
|
||||
// determine size:
|
||||
int pow = MultisizeByteBufferPool.getPowerThatWillFit(bb.capacity());
|
||||
// determine size:
|
||||
int pow = MultisizeByteBufferPool.getPowerThatWillFit(bb.capacity());
|
||||
|
||||
// if we get here and pow == -1 then we have a bytebuffer > 2^30 !!!!
|
||||
// so just file it under power of 30;
|
||||
if (pow == -1) {
|
||||
pow = 30;
|
||||
}
|
||||
// if we get here and pow == -1 then we have a bytebuffer > 2^30 !!!!
|
||||
// so just file it under power of 30;
|
||||
if (pow == -1) {
|
||||
pow = 30;
|
||||
}
|
||||
|
||||
// get pool
|
||||
ByteBufferPool bbp = this.getByteBufferPool(pow);
|
||||
// get pool
|
||||
ByteBufferPool bbp = this.getByteBufferPool(pow);
|
||||
|
||||
// put buffer (back) into pool
|
||||
bbp.put(bb);
|
||||
}
|
||||
// put buffer (back) into pool
|
||||
bbp.put(bb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next power of two that is larger than or equal too the input
|
||||
* <i>value</i>
|
||||
*
|
||||
* @param value
|
||||
* @return the power of two that is larger than or equal too the input
|
||||
* <i>value</i>. A return of -1 indicates out of range.
|
||||
*/
|
||||
public static int getPowerThatWillFit(final int value) {
|
||||
return (value == 0 ? 0 : 32 - Integer.numberOfLeadingZeros(value - 1));
|
||||
}
|
||||
/**
|
||||
* Returns the size of the ByteBufferPool mapped to the given powerOfTwo.
|
||||
*
|
||||
* @param powerOfTwo int range of 0-30
|
||||
* @return size of pool mapped to provided <i>powerOfTwo</i>. Returns -1 on
|
||||
* error and lastError will be set.
|
||||
*/
|
||||
public int getSizeOfPool(int powerOfTwo) {
|
||||
if (powerOfTwo > 30 || powerOfTwo < 0) {
|
||||
Logger.error("powerOfTwo out of range (0-30) in getSizeOfPool(). Got: "
|
||||
+ powerOfTwo);
|
||||
return -1;
|
||||
}
|
||||
ByteBufferPool bbp = this.getByteBufferPool(powerOfTwo);
|
||||
|
||||
private static ByteBufferPool makeByteBufferPool(int bbInitialSize) {
|
||||
return new ByteBufferPool(bbInitialSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the ByteBufferPool mapped to the given powerOfTwo.
|
||||
*
|
||||
* @param powerOfTwo
|
||||
* int range of 0-30
|
||||
* @return size of pool mapped to provided <i>powerOfTwo</i>. Returns -1 on
|
||||
* error and lastError will be set.
|
||||
*/
|
||||
public int getSizeOfPool(int powerOfTwo) {
|
||||
if (powerOfTwo > 30 || powerOfTwo < 0) {
|
||||
Logger.error("powerOfTwo out of range (0-30) in getSizeOfPool(). Got: "
|
||||
+ powerOfTwo);
|
||||
return -1;
|
||||
}
|
||||
ByteBufferPool bbp = this.getByteBufferPool(powerOfTwo);
|
||||
|
||||
return bbp.getPoolSize();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List of the powers of two from 2^0 to 2^30. The index of the array
|
||||
* corresponds to the power of two. Example: If you'd like to quickly lookup
|
||||
* 2^19, then reference powersOfTwo[19]
|
||||
*/
|
||||
public static final int[] powersOfTwo = {
|
||||
1, // 2^0
|
||||
2, // 2^1
|
||||
4, // 2^2
|
||||
8, // 2^3
|
||||
16, // 2^4
|
||||
32, // 2^5
|
||||
64, // 2^6
|
||||
128, // 2^7
|
||||
256, // 2^8
|
||||
512, // 2^9
|
||||
1024, // 2^10
|
||||
2048, // 2^11
|
||||
4096, // 2^12
|
||||
8192, // 2^13
|
||||
16384, // 2^14
|
||||
32768, // 2^15
|
||||
65536, // 2^16
|
||||
131072, // 2^17
|
||||
262144, // 2^18
|
||||
524288, // 2^19
|
||||
1048576, // 2^20
|
||||
2097152, // 2^21
|
||||
4194304, // 2^22
|
||||
8388608, // 2^23
|
||||
16777216, // 2^24
|
||||
33554432, // 2^25
|
||||
67108864, // 2^26
|
||||
134217728, // 2^27
|
||||
268435456, // 2^28
|
||||
536870912, // 2^29
|
||||
1073741824, // 2^30
|
||||
};
|
||||
return bbp.getPoolSize();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+151
-154
@@ -14,182 +14,179 @@ import org.pmw.tinylog.Logger;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class ObjectPool<T> {
|
||||
protected final static int DEFAULT_SIZE = 1000;
|
||||
protected final static int DEFAULT_SIZE = 1000;
|
||||
|
||||
// Simple + quick list
|
||||
private final ArrayList<T> pool;
|
||||
// Simple + quick list
|
||||
private final ArrayList<T> pool;
|
||||
|
||||
/**
|
||||
* Once the ArrayList fills to <b>threshold</b>, subsequent .put() calls
|
||||
* result in the object being thrown away. Default is 75% of supplied
|
||||
* <b>size</b>.
|
||||
*/
|
||||
private int threshold;
|
||||
/**
|
||||
* Once the ArrayList fills to <b>threshold</b>, subsequent .put() calls
|
||||
* result in the object being thrown away. Default is 75% of supplied
|
||||
* <b>size</b>.
|
||||
*/
|
||||
private int threshold;
|
||||
|
||||
/**
|
||||
* Constructor that allows the caller to specify initial array size and
|
||||
* percent of prefill.
|
||||
*
|
||||
* @param size
|
||||
* - initial size for the containing array (pool)
|
||||
*/
|
||||
public ObjectPool(int size) {
|
||||
if (size == 0) {
|
||||
size = DEFAULT_SIZE;
|
||||
}
|
||||
/**
|
||||
* Constructor that allows the caller to specify initial array size and
|
||||
* percent of prefill.
|
||||
*
|
||||
* @param size - initial size for the containing array (pool)
|
||||
*/
|
||||
public ObjectPool(int size) {
|
||||
if (size == 0) {
|
||||
size = DEFAULT_SIZE;
|
||||
}
|
||||
|
||||
threshold = (int) (0.75 * size);
|
||||
threshold = (int) (0.75 * size);
|
||||
|
||||
this.pool = new ArrayList<>(size);
|
||||
this.pool = new ArrayList<>(size);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default Constructor that uses default initial Array size and percent
|
||||
* prefill values
|
||||
*/
|
||||
public ObjectPool() {
|
||||
this(DEFAULT_SIZE);
|
||||
}
|
||||
/**
|
||||
* Default Constructor that uses default initial Array size and percent
|
||||
* prefill values
|
||||
*/
|
||||
public ObjectPool() {
|
||||
this(DEFAULT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces pool to add <i>numberOfObjects</i> to the pool. This may cause
|
||||
* internal ArrayList to resize.
|
||||
*
|
||||
* @param numberOfObjects
|
||||
*/
|
||||
public void fill(int numberOfObjects) {
|
||||
for (int i = 0; i < numberOfObjects; ++i)
|
||||
this.makeAndAdd();
|
||||
}
|
||||
/**
|
||||
* Forces pool to add <i>numberOfObjects</i> to the pool. This may cause
|
||||
* internal ArrayList to resize.
|
||||
*
|
||||
* @param numberOfObjects
|
||||
*/
|
||||
public void fill(int numberOfObjects) {
|
||||
for (int i = 0; i < numberOfObjects; ++i)
|
||||
this.makeAndAdd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces subclasses to implement factory routine for object creation.
|
||||
*/
|
||||
protected abstract T makeNewObject();
|
||||
/**
|
||||
* Forces subclasses to implement factory routine for object creation.
|
||||
*/
|
||||
protected abstract T makeNewObject();
|
||||
|
||||
/**
|
||||
* Forces subclasses to implement a way to reset object to a reusable state.
|
||||
*/
|
||||
protected abstract void resetObject(T obj);
|
||||
/**
|
||||
* Forces subclasses to implement a way to reset object to a reusable state.
|
||||
*/
|
||||
protected abstract void resetObject(T obj);
|
||||
|
||||
/**
|
||||
* Generic Get routine. If the pool is empty, then one (or more) of T type
|
||||
* objects will be created. If more than one T is created, then they will be
|
||||
* put into the pool. One T will always be created and returned.
|
||||
*/
|
||||
public T get() {
|
||||
synchronized (pool) {
|
||||
//Logger.debug("Objectpool.get(). Pool size before get: " + pool.size());
|
||||
if (pool.size() > 0) {
|
||||
return pool.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
this.handlePoolExhaustion();
|
||||
/**
|
||||
* Generic Get routine. If the pool is empty, then one (or more) of T type
|
||||
* objects will be created. If more than one T is created, then they will be
|
||||
* put into the pool. One T will always be created and returned.
|
||||
*/
|
||||
public T get() {
|
||||
synchronized (pool) {
|
||||
//Logger.debug("Objectpool.get(). Pool size before get: " + pool.size());
|
||||
if (pool.size() > 0) {
|
||||
return pool.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
T obj = this.makeNewObject();
|
||||
this.handlePoolExhaustion();
|
||||
|
||||
if (obj == null) {
|
||||
Logger.error("Pooling failure: Object creation failed.");
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
T obj = this.makeNewObject();
|
||||
|
||||
protected void handlePoolExhaustion(){
|
||||
Logger.debug("Pool exhausted, making more objects.");
|
||||
|
||||
// If none exist, make (and pool) a few
|
||||
// Dont sync the loop, let the makeNewObject()
|
||||
// call return before locking the pool object
|
||||
for (int i = 0; i < 5; ++i)
|
||||
this.makeAndAdd();
|
||||
if (obj == null) {
|
||||
Logger.error("Pooling failure: Object creation failed.");
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic put routine. If the current pool size is below threshold, this
|
||||
* object will be pooled, otherwise it will be NULL'ed and scheduled for
|
||||
* Garbage Collection
|
||||
*
|
||||
* @param obj
|
||||
*/
|
||||
public void put(T obj) {
|
||||
synchronized (pool) {
|
||||
if (pool.size() >= this.threshold) {
|
||||
//Logger.debug("Objectpool.put() rejected. Pool size: " + pool.size());
|
||||
return;
|
||||
}
|
||||
//Logger.debug("Objectpool.put(). Pool size: " + pool.size());
|
||||
this.resetObject(obj);
|
||||
this.pool.add(obj);
|
||||
}
|
||||
}
|
||||
protected void handlePoolExhaustion() {
|
||||
Logger.debug("Pool exhausted, making more objects.");
|
||||
|
||||
/**
|
||||
* Helper method. Attempts to create and add a new <i>T</i> object. If this
|
||||
* fails, an error is logged.
|
||||
*/
|
||||
protected final void makeAndAdd() {
|
||||
T obj = this.makeNewObject();
|
||||
if (obj == null) {
|
||||
Logger.error("Pooling failure: Object creation failed.");
|
||||
} else {
|
||||
this.put(obj);
|
||||
}
|
||||
}
|
||||
// If none exist, make (and pool) a few
|
||||
// Dont sync the loop, let the makeNewObject()
|
||||
// call return before locking the pool object
|
||||
for (int i = 0; i < 5; ++i)
|
||||
this.makeAndAdd();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the current size of the pool, not the maximum capacity of the
|
||||
* Array holding the pool.
|
||||
*/
|
||||
public final int getPoolSize() {
|
||||
synchronized (this.pool) {
|
||||
return this.pool.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Culls the pool and removes half of the stored objects. Removed objects
|
||||
* are NULL'ed and scheduled form Garbage Collection.
|
||||
*
|
||||
* @return the number of Objects removed from the pool.
|
||||
*/
|
||||
public int cullHalf() {
|
||||
int full, half;
|
||||
synchronized (this.pool) {
|
||||
full = this.pool.size();
|
||||
if (full < 1) {
|
||||
return full;
|
||||
}
|
||||
/**
|
||||
* Generic put routine. If the current pool size is below threshold, this
|
||||
* object will be pooled, otherwise it will be NULL'ed and scheduled for
|
||||
* Garbage Collection
|
||||
*
|
||||
* @param obj
|
||||
*/
|
||||
public void put(T obj) {
|
||||
synchronized (pool) {
|
||||
if (pool.size() >= this.threshold) {
|
||||
//Logger.debug("Objectpool.put() rejected. Pool size: " + pool.size());
|
||||
return;
|
||||
}
|
||||
//Logger.debug("Objectpool.put(). Pool size: " + pool.size());
|
||||
this.resetObject(obj);
|
||||
this.pool.add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
half = (full / 2);
|
||||
/**
|
||||
* Helper method. Attempts to create and add a new <i>T</i> object. If this
|
||||
* fails, an error is logged.
|
||||
*/
|
||||
protected final void makeAndAdd() {
|
||||
T obj = this.makeNewObject();
|
||||
if (obj == null) {
|
||||
Logger.error("Pooling failure: Object creation failed.");
|
||||
} else {
|
||||
this.put(obj);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < (full / 2); ++i) {
|
||||
T obj = this.get();
|
||||
obj = null; // Null out for GC
|
||||
}
|
||||
}
|
||||
return half;
|
||||
}
|
||||
/**
|
||||
* @return the current size of the pool, not the maximum capacity of the
|
||||
* Array holding the pool.
|
||||
*/
|
||||
public final int getPoolSize() {
|
||||
synchronized (this.pool) {
|
||||
return this.pool.size();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the threshold
|
||||
*/
|
||||
public final int getThreshold() {
|
||||
return threshold;
|
||||
}
|
||||
/**
|
||||
* Culls the pool and removes half of the stored objects. Removed objects
|
||||
* are NULL'ed and scheduled form Garbage Collection.
|
||||
*
|
||||
* @return the number of Objects removed from the pool.
|
||||
*/
|
||||
public int cullHalf() {
|
||||
int full, half;
|
||||
synchronized (this.pool) {
|
||||
full = this.pool.size();
|
||||
if (full < 1) {
|
||||
return full;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param threshold
|
||||
* the threshold to set
|
||||
*/
|
||||
public void setThreshold(int threshold) {
|
||||
if (threshold < 0)
|
||||
return;
|
||||
half = (full / 2);
|
||||
|
||||
this.threshold = threshold;
|
||||
}
|
||||
for (int i = 0; i < (full / 2); ++i) {
|
||||
T obj = this.get();
|
||||
obj = null; // Null out for GC
|
||||
}
|
||||
}
|
||||
return half;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the threshold
|
||||
*/
|
||||
public final int getThreshold() {
|
||||
return threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param threshold the threshold to set
|
||||
*/
|
||||
public void setThreshold(int threshold) {
|
||||
if (threshold < 0)
|
||||
return;
|
||||
|
||||
this.threshold = threshold;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,5 +10,5 @@
|
||||
package engine.pooling;
|
||||
|
||||
public interface Poolable {
|
||||
public void clear();
|
||||
public void clear();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user