You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
5.7 KiB
184 lines
5.7 KiB
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . |
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· |
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ |
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ |
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ |
|
// Magicbane Emulator Project © 2013 - 2022 |
|
// www.magicbane.com |
|
|
|
|
|
package engine.pooling; |
|
|
|
import org.pmw.tinylog.Logger; |
|
|
|
import java.nio.ByteBuffer; |
|
import java.util.HashMap; |
|
|
|
public class MultisizeByteBufferPool { |
|
|
|
/** |
|
* 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(); |
|
} |
|
|
|
/** |
|
* 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)); |
|
} |
|
|
|
private static ByteBufferPool makeByteBufferPool(int bbInitialSize) { |
|
return new ByteBufferPool(bbInitialSize); |
|
} |
|
|
|
/** |
|
* 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; |
|
} |
|
|
|
// Check to see if there is a pool for this size |
|
ByteBufferPool bbp = this.getByteBufferPool(powerOfTwo); |
|
return bbp.get(); |
|
} |
|
|
|
/** |
|
* 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); |
|
} |
|
} |
|
|
|
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) { |
|
|
|
if (bb == null) |
|
return; |
|
|
|
// 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; |
|
} |
|
|
|
// get pool |
|
ByteBufferPool bbp = this.getByteBufferPool(pow); |
|
|
|
// put buffer (back) into pool |
|
bbp.put(bb); |
|
} |
|
|
|
/** |
|
* 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(); |
|
} |
|
|
|
}
|
|
|