Fixed classpath. Added a REALLY Fast ObjectPool
This commit is contained in:
parent
40429ac6f8
commit
fe08b9d9bd
@ -2,7 +2,6 @@
|
|||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="src" path="src"/>
|
<classpathentry kind="src" path="src"/>
|
||||||
<classpathentry kind="src" path="test"/>
|
<classpathentry kind="src" path="test"/>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
|
||||||
<classpathentry exported="true" kind="lib" path="/Dependencies/logging/slf4j-api-1.7.5.jar" sourcepath="/Dependencies/logging/slf4j-api-1.7.5-sources.zip"/>
|
<classpathentry exported="true" kind="lib" path="/Dependencies/logging/slf4j-api-1.7.5.jar" sourcepath="/Dependencies/logging/slf4j-api-1.7.5-sources.zip"/>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
|
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
|
||||||
<classpathentry kind="lib" path="/Dependencies/kryo/kryo2-debug.jar" sourcepath="/Dependencies/kryo/kryo2-source.zip"/>
|
<classpathentry kind="lib" path="/Dependencies/kryo/kryo2-debug.jar" sourcepath="/Dependencies/kryo/kryo2-source.zip"/>
|
||||||
@ -24,5 +23,6 @@
|
|||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="lib" path="/Dependencies/asm/asm-5.0.3.jar" sourcepath="/Dependencies/asm/asm-5.0.3-src.zip"/>
|
<classpathentry kind="lib" path="/Dependencies/asm/asm-5.0.3.jar" sourcepath="/Dependencies/asm/asm-5.0.3-src.zip"/>
|
||||||
<classpathentry combineaccessrules="false" kind="src" path="/JavaLauncher-Util"/>
|
<classpathentry combineaccessrules="false" kind="src" path="/JavaLauncher-Util"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
<classpathentry kind="output" path="classes"/>
|
<classpathentry kind="output" path="classes"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
@ -76,7 +76,14 @@ Legal:
|
|||||||
|
|
||||||
- BouncyCastle - MIT X11 License
|
- BouncyCastle - MIT X11 License
|
||||||
http://www.bouncycastle.org
|
http://www.bouncycastle.org
|
||||||
Copyright (c) 2000 - 2009 The Legion Of The Bouncy Castle
|
Copyright 2000 - 2009 The Legion Of The Bouncy Castle
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- FastObjectPool - Apache 2.0 license
|
||||||
|
http://ashkrit.blogspot.com/2013/05/lock-less-java-object-pool.html
|
||||||
|
https://github.com/ashkrit/blog/tree/master/FastObjectPool
|
||||||
|
Copyright 2013 Ashkrit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -88,7 +95,7 @@ Legal:
|
|||||||
|
|
||||||
- MathUtils, IntArray, IntMap - Apache 2.0 license
|
- MathUtils, IntArray, IntMap - Apache 2.0 license
|
||||||
http://github.com/libgdx/libgdx/
|
http://github.com/libgdx/libgdx/
|
||||||
Copyright (c) 2013
|
Copyright 2013
|
||||||
Mario Zechner <badlogicgames@gmail.com>
|
Mario Zechner <badlogicgames@gmail.com>
|
||||||
Nathan Sweet <nathan.sweet@gmail.com>
|
Nathan Sweet <nathan.sweet@gmail.com>
|
||||||
|
|
||||||
@ -96,5 +103,5 @@ Legal:
|
|||||||
|
|
||||||
- MersenneTwisterFast, v20 - BSD license
|
- MersenneTwisterFast, v20 - BSD license
|
||||||
http://www.cs.gmu.edu/~sean/research/mersenne/MersenneTwisterFast.java
|
http://www.cs.gmu.edu/~sean/research/mersenne/MersenneTwisterFast.java
|
||||||
Copyright (c) 2003 by Sean Luke.
|
Copyright 2003 by Sean Luke
|
||||||
Portions copyright (c) 1993 by Michael Lecuyer.
|
Portions copyright 1993 by Michael Lecuyer
|
||||||
|
167
Dorkbox-Util/src/dorkbox/util/FastObjectPool.java
Normal file
167
Dorkbox-Util/src/dorkbox/util/FastObjectPool.java
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
package dorkbox.util;
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* from: http://ashkrit.blogspot.de/2013/05/lock-less-java-object-pool.html
|
||||||
|
* https://github.com/ashkrit/blog/tree/master/FastObjectPool
|
||||||
|
* copyright ashkrit 2013
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
import sun.misc.Unsafe;
|
||||||
|
|
||||||
|
|
||||||
|
public class FastObjectPool<T> {
|
||||||
|
|
||||||
|
private Holder<T>[] objects;
|
||||||
|
|
||||||
|
private volatile int takePointer;
|
||||||
|
private int releasePointer;
|
||||||
|
|
||||||
|
private final int mask;
|
||||||
|
private final long BASE;
|
||||||
|
private final long INDEXSCALE;
|
||||||
|
private final long ASHIFT;
|
||||||
|
|
||||||
|
public ReentrantLock lock = new ReentrantLock();
|
||||||
|
private ThreadLocal<Holder<T>> localValue = new ThreadLocal<>();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public FastObjectPool(PoolFactory<T> factory , int size)
|
||||||
|
{
|
||||||
|
|
||||||
|
int newSize=1;
|
||||||
|
while(newSize<size)
|
||||||
|
{
|
||||||
|
newSize = newSize << 1;
|
||||||
|
}
|
||||||
|
size = newSize;
|
||||||
|
this.objects = new Holder[size];
|
||||||
|
for(int x=0;x<size;x++)
|
||||||
|
{
|
||||||
|
this.objects[x] = new Holder<T>(factory.create());
|
||||||
|
}
|
||||||
|
this.mask = size-1;
|
||||||
|
this.releasePointer = size;
|
||||||
|
this.BASE = THE_UNSAFE.arrayBaseOffset(Holder[].class);
|
||||||
|
this.INDEXSCALE = THE_UNSAFE.arrayIndexScale(Holder[].class);
|
||||||
|
this.ASHIFT = 31 - Integer.numberOfLeadingZeros((int) this.INDEXSCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Holder<T> take()
|
||||||
|
{
|
||||||
|
int localTakePointer;
|
||||||
|
|
||||||
|
Holder<T> localObject = this.localValue.get();
|
||||||
|
if(localObject!=null)
|
||||||
|
{
|
||||||
|
if(localObject.state.compareAndSet(Holder.FREE, Holder.USED))
|
||||||
|
{
|
||||||
|
return localObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while(this.releasePointer != (localTakePointer=this.takePointer) )
|
||||||
|
{
|
||||||
|
int index = localTakePointer & this.mask;
|
||||||
|
Holder<T> holder = this.objects[index];
|
||||||
|
//if(holder!=null && THE_UNSAFE.compareAndSwapObject(objects, (index*INDEXSCALE)+BASE, holder, null))
|
||||||
|
if(holder!=null && THE_UNSAFE.compareAndSwapObject(this.objects, (index<<this.ASHIFT)+this.BASE, holder, null))
|
||||||
|
{
|
||||||
|
this.takePointer = localTakePointer+1;
|
||||||
|
if(holder.state.compareAndSet(Holder.FREE, Holder.USED))
|
||||||
|
{
|
||||||
|
this.localValue.set(holder);
|
||||||
|
return holder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void release(Holder<T> object) throws InterruptedException
|
||||||
|
{
|
||||||
|
this.lock.lockInterruptibly();
|
||||||
|
try{
|
||||||
|
int localValue=this.releasePointer;
|
||||||
|
//long index = ((localValue & mask) * INDEXSCALE ) + BASE;
|
||||||
|
long index = ((localValue & this.mask)<<this.ASHIFT ) + this.BASE;
|
||||||
|
if(object.state.compareAndSet(Holder.USED, Holder.FREE))
|
||||||
|
{
|
||||||
|
THE_UNSAFE.putOrderedObject(this.objects, index, object);
|
||||||
|
this.releasePointer = localValue+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Invalid reference passed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Holder<T>
|
||||||
|
{
|
||||||
|
private T value;
|
||||||
|
public static final int FREE=0;
|
||||||
|
public static final int USED=1;
|
||||||
|
|
||||||
|
private AtomicInteger state = new AtomicInteger(FREE);
|
||||||
|
public Holder(T value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static interface PoolFactory<T>
|
||||||
|
{
|
||||||
|
public T create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Unsafe THE_UNSAFE;
|
||||||
|
static
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final PrivilegedExceptionAction<Unsafe> action = new PrivilegedExceptionAction<Unsafe>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Unsafe run() throws Exception
|
||||||
|
{
|
||||||
|
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
|
||||||
|
theUnsafe.setAccessible(true);
|
||||||
|
return (Unsafe) theUnsafe.get(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
THE_UNSAFE = AccessController.doPrivileged(action);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Unable to load unsafe", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user