/*******************************************************************************
* Copyright 2012-present Pixate, 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.
******************************************************************************/
package com.pixate.freestyle.util;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Paint;
import android.graphics.Path;
/**
* A synchronized object pool implementation.
*
* @author Shalom Gibly
*/
public class ObjectPool<T, E> {
private static final int DEFAULT_POOL_SIZE = 10;
/**
* Factory class for creating pool instance.
*
* @author Shalom Gibly
*/
public interface ObjectPoolFactory<T, E> {
/**
* Create an instance that will be returned by the pool.
*
* @return T
*/
public T createInstance();
/**
* Resets the instance as it's being inserted back to the pool.
*
* @param object
*/
public void resetInstance(T object);
/**
* Initialize the instance with an initialization object.
*
* @param toInitialize
* @param initializerObject
*/
public void initializeInstance(T toInitialize, E initializerObject);
}
/**
* An implementation for {@link Paint} instances pool.
*/
public static ObjectPool<Paint, Paint> paintPool = new ObjectPool<Paint, Paint>(
new ObjectPoolFactory<Paint, Paint>() {
public Paint createInstance() {
return new Paint(Paint.ANTI_ALIAS_FLAG);
}
public void resetInstance(Paint paint) {
paint.reset();
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
}
public void initializeInstance(Paint toInitialize, Paint initializerObject) {
toInitialize.set(initializerObject);
}
}, DEFAULT_POOL_SIZE);
/**
* An implementation for {@link Path} instances pool.
*/
public static ObjectPool<Path, Path> pathPool = new ObjectPool<Path, Path>(
new ObjectPoolFactory<Path, Path>() {
public Path createInstance() {
return new Path();
}
public void resetInstance(Path path) {
path.reset();
}
public void initializeInstance(Path toInitialize, Path initializerObject) {
toInitialize.set(initializerObject);
}
}, DEFAULT_POOL_SIZE);
private final List<T> available;
private final ObjectPoolFactory<T, E> factory;
private int limit;
/**
* Constructs a new object pool
*
* @param factory
* @param limit
*/
public ObjectPool(ObjectPoolFactory<T, E> factory, int limit) {
this.limit = limit;
this.factory = factory;
available = new ArrayList<T>(limit);
}
/**
* Check out and return an instance. The instance will be taken out of the
* pooled existing instances. In case none exist, a new instance will be
* created and returned.
*
* @return A new instance (or a re-used one)
*/
public T checkOut() {
T object = null;
synchronized (available) {
if (available.isEmpty()) {
object = factory.createInstance();
} else {
object = available.remove(available.size() - 1);
}
return object;
}
}
/**
* Check out and return an instance. The instance will be taken out of the
* pooled existing instances and initialized with the initialization object
* before being returned. In case none exist, a new instance will be
* created, initialized, and returned.
*
* @return A new instance (or a re-used one)
*/
public T checkOut(E initilizationObject) {
T checkedOut = checkOut();
if (initilizationObject != null) {
factory.initializeInstance(checkedOut, initilizationObject);
}
return checkedOut;
}
/**
* Check in an instance into the pool.
*
* @param object
*/
public void checkIn(T object) {
if (object == null) {
return;
}
synchronized (available) {
if (available.size() < limit) {
factory.resetInstance(object);
available.add(object);
}
}
}
}