rx.internal.util.ObjectPool Maven / Gradle / Ivy
/**
* Copyright 2014 Netflix, Inc.
*
* 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 from http://www.javacodegeeks.com/2013/08/simple-and-lightweight-pool-implementation.html
*/
package rx.internal.util;
import java.util.Queue;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
import rx.internal.schedulers.*;
import rx.internal.util.unsafe.*;
import rx.plugins.RxJavaHooks;
public abstract class ObjectPool implements SchedulerLifecycle {
Queue pool;
final int minSize;
final int maxSize;
private final long validationInterval;
private final AtomicReference> periodicTask;
public ObjectPool() {
this(0, 0, 67); // NOPMD
}
/**
* Creates the pool.
*
* @param minIdle
* minimum number of objects residing in the pool
* @param maxIdle
* maximum number of objects residing in the pool
* @param validationInterval
* time in seconds for periodical checking of minIdle / maxIdle conditions in a separate thread.
* When the number of objects is less than minIdle, missing instances will be created.
* When the number of objects is greater than maxIdle, too many instances will be removed.
*/
private ObjectPool(final int min, final int max, final long validationInterval) {
this.minSize = min;
this.maxSize = max;
this.validationInterval = validationInterval;
this.periodicTask = new AtomicReference>();
// initialize pool
initialize(min);
start();
}
/**
* Gets the next free object from the pool. If the pool doesn't contain any objects,
* a new object will be created and given to the caller of this method back.
*
* @return T borrowed object
*/
public T borrowObject() {
T object;
if ((object = pool.poll()) == null) {
object = createObject();
}
return object;
}
/**
* Returns object back to the pool.
*
* @param object
* object to be returned
*/
public void returnObject(T object) {
if (object == null) {
return;
}
this.pool.offer(object);
}
/**
* Shutdown this pool.
*/
@Override
public void shutdown() {
Future> f = periodicTask.getAndSet(null);
if (f != null) {
f.cancel(false);
}
}
@Override
public void start() {
for (;;) {
if (periodicTask.get() != null) {
return;
}
ScheduledExecutorService w = GenericScheduledExecutorService.getInstance();
Future> f;
try {
f = w.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
int size = pool.size();
if (size < minSize) {
int sizeToBeAdded = maxSize - size;
for (int i = 0; i < sizeToBeAdded; i++) {
pool.add(createObject());
}
} else if (size > maxSize) {
int sizeToBeRemoved = size - maxSize;
for (int i = 0; i < sizeToBeRemoved; i++) {
// pool.pollLast();
pool.poll();
}
}
}
}, validationInterval, validationInterval, TimeUnit.SECONDS);
} catch (RejectedExecutionException ex) {
RxJavaHooks.onError(ex);
break;
}
if (!periodicTask.compareAndSet(null, f)) {
f.cancel(false);
} else {
break;
}
}
}
/**
* Creates a new object.
*
* @return T new object
*/
protected abstract T createObject();
private void initialize(final int min) {
if (UnsafeAccess.isUnsafeAvailable()) {
pool = new MpmcArrayQueue(Math.max(maxSize, 1024));
} else {
pool = new ConcurrentLinkedQueue();
}
for (int i = 0; i < min; i++) {
pool.add(createObject());
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy