Removed libs/dist and now only have safe object pool (based on ArrayBlockingQueue)
This commit is contained in:
parent
253a777382
commit
2ae5328856
|
@ -11,7 +11,6 @@
|
|||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="jdk" jdkName="1.6" jdkType="JavaSDK" />
|
||||
<orderEntry type="library" name="JCTools (1.4 alpha MTAQ)" level="application" />
|
||||
<orderEntry type="library" name="junit-4.12" level="application" />
|
||||
</component>
|
||||
<component name="org.twodividedbyzero.idea.findbugs">
|
||||
|
|
|
@ -15,33 +15,74 @@
|
|||
*/
|
||||
package dorkbox.util.objectPool;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
|
||||
public
|
||||
interface ObjectPool<T> {
|
||||
class ObjectPool<T> {
|
||||
private final ArrayBlockingQueue<T> queue;
|
||||
private final PoolableObject<T> poolableObject;
|
||||
|
||||
ObjectPool(PoolableObject<T> poolableObject, int size) {
|
||||
this.poolableObject = poolableObject;
|
||||
|
||||
this.queue = new ArrayBlockingQueue<T>(size);
|
||||
|
||||
for (int x = 0; x < size; x++) {
|
||||
T e = poolableObject.create();
|
||||
poolableObject.onReturn(e);
|
||||
this.queue.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an object from the pool, Blocks until an item is available in the pool.
|
||||
*/
|
||||
T take() throws InterruptedException;
|
||||
public
|
||||
T take() throws InterruptedException {
|
||||
final T take = this.queue.take();
|
||||
poolableObject.onTake(take);
|
||||
return take;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an object from the pool, Blocks until an item is available in the pool.
|
||||
* <p/>
|
||||
* This method catches {@link InterruptedException} and discards it silently.
|
||||
*/
|
||||
T takeUninterruptibly();
|
||||
@SuppressWarnings({"Duplicates", "SpellCheckingInspection"})
|
||||
public
|
||||
T takeUninterruptibly() {
|
||||
try {
|
||||
T take = take();
|
||||
return take;
|
||||
} catch (InterruptedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return object to the pool, waking those threads that have blocked during take()
|
||||
*/
|
||||
void release(T object);
|
||||
public
|
||||
void release(T object) {
|
||||
poolableObject.onReturn(object);
|
||||
this.queue.offer(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new object instance created by the pool.
|
||||
*/
|
||||
T newInstance();
|
||||
public
|
||||
T newInstance() {
|
||||
return poolableObject.create();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the number of pooled objects
|
||||
*/
|
||||
int size();
|
||||
public
|
||||
int size() {
|
||||
return queue.size();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Copyright 2014 dorkbox, llc
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package dorkbox.util.objectPool;
|
||||
|
||||
|
||||
public
|
||||
class ObjectPoolFactory {
|
||||
|
||||
private
|
||||
ObjectPoolFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a pool of the specified size. The "Fast/Unsafe" object pool will always have a size rounded up to the nearest power of 2.
|
||||
*/
|
||||
public static
|
||||
<T> ObjectPool<T> create(PoolableObject<T> poolableObject, int size) {
|
||||
try {
|
||||
// here we use FAST (via UNSAFE)
|
||||
UnsafeObjectPool<T> fastObjectPool = new UnsafeObjectPool<T>(poolableObject, size);
|
||||
return fastObjectPool;
|
||||
} catch (Throwable ignored) {
|
||||
// fallback (LinkedBlockingDeque) in case UNSAFE isn't available. (ie: android)
|
||||
SafeObjectPool<T> slowObjectPool = new SafeObjectPool<T>(poolableObject, size);
|
||||
return slowObjectPool;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an UNSAFE pool of the specified size, rounded up to the nearest power of 2.
|
||||
*/
|
||||
public static
|
||||
<T> ObjectPool<T> createFast(PoolableObject<T> poolableObject, int size) {
|
||||
// here we use FAST (via UNSAFE)
|
||||
UnsafeObjectPool<T> fastObjectPool = null;
|
||||
try {
|
||||
fastObjectPool = new UnsafeObjectPool<T>(poolableObject, size);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Unable to create a fast object pool, use 'create()' instead. Aborting.", e);
|
||||
|
||||
}
|
||||
return fastObjectPool;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a SAFE pool of the specified size.
|
||||
*/
|
||||
public static
|
||||
<T> ObjectPool<T> createSafe(PoolableObject<T> poolableObject, int size) {
|
||||
// fallback (LinkedBlockingDeque) in case UNSAFE isn't available. (ie: android)
|
||||
SafeObjectPool<T> slowObjectPool = new SafeObjectPool<T>(poolableObject, size);
|
||||
return slowObjectPool;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* from: https://code.google.com/p/furious-objectpool/
|
||||
* copyright Eddie Raapoto 2012
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Modified by dorkbox, llc
|
||||
*/
|
||||
package dorkbox.util.objectPool;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
|
||||
|
||||
class SafeObjectPool<T> implements ObjectPool<T> {
|
||||
|
||||
private final ArrayBlockingQueue<T> queue;
|
||||
private final PoolableObject<T> poolableObject;
|
||||
|
||||
SafeObjectPool(PoolableObject<T> poolableObject, int size) {
|
||||
this.poolableObject = poolableObject;
|
||||
|
||||
this.queue = new ArrayBlockingQueue<T>(size);
|
||||
|
||||
for (int x = 0; x < size; x++) {
|
||||
T e = poolableObject.create();
|
||||
poolableObject.onReturn(e);
|
||||
this.queue.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
T take() throws InterruptedException {
|
||||
final T take = this.queue.take();
|
||||
poolableObject.onTake(take);
|
||||
return take;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"Duplicates", "SpellCheckingInspection"})
|
||||
@Override
|
||||
public
|
||||
T takeUninterruptibly() {
|
||||
try {
|
||||
T take = take();
|
||||
return take;
|
||||
} catch (InterruptedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void release(T object) {
|
||||
poolableObject.onReturn(object);
|
||||
this.queue.offer(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
T newInstance() {
|
||||
return poolableObject.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
int size() {
|
||||
return queue.size();
|
||||
}
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
* from: http://ashkrit.blogspot.com/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.
|
||||
*
|
||||
* Modified by dorkbox, llc
|
||||
*/
|
||||
package dorkbox.util.objectPool;
|
||||
|
||||
import org.jctools.queues.MpmcArrayQueue;
|
||||
import org.jctools.util.Pow2;
|
||||
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
|
||||
class UnsafeObjectPool<T> implements ObjectPool<T> {
|
||||
public static final int FULL_RETRY_LIMIT = 200;
|
||||
|
||||
private final MpmcArrayQueue<T> objects;
|
||||
|
||||
private final Lock lock = new ReentrantLock();
|
||||
private final Condition empty = lock.newCondition();
|
||||
private final PoolableObject<T> poolableObject;
|
||||
|
||||
UnsafeObjectPool(final PoolableObject<T> poolableObject, final int size) throws Throwable {
|
||||
this.poolableObject = poolableObject;
|
||||
int newSize = Pow2.roundToPowerOfTwo(size);
|
||||
objects = new MpmcArrayQueue<T>(newSize);
|
||||
|
||||
for (int x = 0; x < newSize; x++) {
|
||||
T e = poolableObject.create();
|
||||
poolableObject.onReturn(e);
|
||||
objects.offer(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
T take() throws InterruptedException {
|
||||
T poll = objects.poll();
|
||||
if (poll == null) {
|
||||
lock.lock();
|
||||
try {
|
||||
while ((poll = objects.poll()) == null) {
|
||||
empty.await();
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
poolableObject.onTake(poll);
|
||||
return poll;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"Duplicates", "SpellCheckingInspection"})
|
||||
@Override
|
||||
public
|
||||
T takeUninterruptibly() {
|
||||
try {
|
||||
final T take = take();
|
||||
return take;
|
||||
} catch (InterruptedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void release(T object) {
|
||||
poolableObject.onReturn(object);
|
||||
boolean waiting = objects.peek() == null;
|
||||
|
||||
// This could potentially happen due to optimistic calculations by the implementation queue.
|
||||
// From my observations, 1 retry was all that was needed.
|
||||
if (!objects.offer(object)) {
|
||||
int limit = FULL_RETRY_LIMIT;
|
||||
while (!objects.offer(object) && limit-- > 0) {
|
||||
try {
|
||||
Thread.sleep(2L);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
if (limit <= 0) {
|
||||
throw new RuntimeException("Unable to insert item into object pool. Pool is full, and retry limit exceeded.");
|
||||
}
|
||||
}
|
||||
|
||||
if (waiting) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (objects.peek() == null) {
|
||||
// we only need to signal one, since the take/release calls must be symmetric
|
||||
empty.signal();
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
T newInstance() {
|
||||
return poolableObject.create();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is an optimistic calculation, and if being used by multiple threads, can be inaccurate.
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
int size() {
|
||||
return objects.size();
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package dorkbox.util.objectPool;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public
|
||||
class ObjectPoolFactoryTest {
|
||||
|
||||
public static
|
||||
void main(String[] args) throws Exception {
|
||||
new ObjectPoolFactoryTest().testCreate();
|
||||
}
|
||||
|
||||
@Test
|
||||
public
|
||||
void testCreate() throws Exception {
|
||||
|
||||
final ObjectPool<Integer> pool = ObjectPoolFactory.create(new PoolableObject<Integer>() {
|
||||
int id = 1;
|
||||
|
||||
@Override
|
||||
public
|
||||
Integer create() {
|
||||
return this.id++;
|
||||
}
|
||||
}, 4);
|
||||
|
||||
Integer one = pool.take();
|
||||
Integer two = pool.take();
|
||||
Integer three = pool.take();
|
||||
Integer four = pool.take();
|
||||
|
||||
pool.release(one);
|
||||
pool.release(two);
|
||||
pool.release(three);
|
||||
pool.release(four);
|
||||
|
||||
one = pool.take();
|
||||
two = pool.take();
|
||||
pool.release(one);
|
||||
pool.release(two);
|
||||
|
||||
three = pool.take();
|
||||
four = pool.take();
|
||||
one = pool.take();
|
||||
two = pool.take();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue