org.oscim.utils.pool.SyncPool Maven / Gradle / Ivy
/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see .
*/
package org.oscim.utils.pool;
import javax.annotation.CheckReturnValue;
@SuppressWarnings({"rawtypes", "unchecked"})
public abstract class SyncPool> {
protected final int mMaxFill;
protected final boolean mClearItems;
protected int mFill;
protected T mPool;
public SyncPool(int maxItemsInPool) {
this(maxItemsInPool, true);
}
public SyncPool(int maxItemsInPool, boolean clearItems) {
mMaxFill = maxItemsInPool;
mFill = 0;
mClearItems = clearItems;
}
public int getFill() {
return mFill;
}
/**
* To be implemented by subclass.
*
* @param items number of initial items
*/
public void init(int items) {
mFill = 0;
mPool = null;
}
public synchronized void clear() {
while (mPool != null) {
freeItem(mPool);
mPool = (T) mPool.next;
}
}
/**
* @param item set initial state
* @return 'true' when item should be added back to pool,
* 'false' when freeItem should be called.
*/
protected boolean clearItem(T item) {
return true;
}
/**
* @param item release resources
*/
protected void freeItem(T item) {
}
/**
* Creates the item. To be implemented by subclass.
*
* @return the item
*/
protected abstract T createItem();
/**
* Release 'item' to pool.
*
* Usage item = pool.release(item), to ensure to not keep a reference to
* item!
*/
@CheckReturnValue
public T release(T item) {
if (item == null)
return null;
if (mClearItems && !clearItem(item)) {
// dont add back to pool
freeItem(item);
return null;
}
if (mFill < mMaxFill) {
synchronized (this) {
mFill++;
((Inlist) item).next = (T) mPool;
mPool = item;
}
} else if (mClearItems) {
freeItem(item);
}
return null;
}
/**
* Release 'list' to pool.
*
* Usage list = pool.releaseAll(list), to ensure to not keep a reference to
* list!
*/
@CheckReturnValue
public T releaseAll(T item) {
if (item == null)
return null;
if (mFill > mMaxFill) {
while (item != null) {
if (mClearItems) {
clearItem(item);
freeItem(item);
}
item = (T) item.next;
}
return null;
}
synchronized (this) {
while (item != null) {
T next = (T) item.next;
if (mClearItems && !clearItem(item)) {
// dont add back to pool
freeItem(item);
item = next;
continue;
}
mFill++;
((Inlist) item).next = (T) mPool;
mPool = item;
item = next;
}
}
return null;
}
/**
* Gets an 'item' from pool, if pool is empty a new
* item will be created by createItem().
*
* @return the item
*/
public T get() {
synchronized (this) {
if (mPool == null) {
return createItem();
}
mFill--;
T ret = mPool;
mPool = (T) mPool.next;
ret.next = null;
return ret;
}
}
}