package org.smartly.commons.pools;
import org.smartly.commons.Delegates;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Blocking Pool of objects.<br/>
* Call method "lock" to get an item from pool.<br/>
* Call method "release" to return item to pool.<br/>
* When pool is empty, a thread will loop until next item is released.
*/
public class GenericPool<T> {
// --------------------------------------------------------------------
// f i e l d s
// --------------------------------------------------------------------
private final Object _syncObj;
private final List<T> _pool;
// --------------------------------------------------------------------
// c o n s t r u c t o r
// --------------------------------------------------------------------
public GenericPool(final T... items) {
this(0, null); // unlimited pool
if (null != items && items.length > 0) {
this.init(items);
}
}
public GenericPool(final int capacity,
final Delegates.Function<T> callback) {
_syncObj = new Object();
_pool = Collections.synchronizedList(new ArrayList<T>(capacity));
this.init(capacity, callback);
}
// --------------------------------------------------------------------
// p u b l i c
// --------------------------------------------------------------------
public int size() {
synchronized (_pool) {
return _pool.size();
}
}
public T lock() {
synchronized (_syncObj) {
while (this.size() == 0) {
try {
Thread.sleep(100);
} catch (Throwable ignored) {
return null;
}
}
return this.firstItem();
}
}
public void release(final T item) {
this.putItem(item);
}
public Object[] clear() {
synchronized (_syncObj) {
final Object[] result = new Object[_pool.size()];
int i = 0;
for (final Object item : _pool) {
if (null != item) {
result[i] = item;
}
i++;
}
_pool.clear();
return result;
}
}
// --------------------------------------------------------------------
// p r i v a t e
// --------------------------------------------------------------------
private void init(final T... items) {
synchronized (_pool) {
_pool.addAll(Arrays.asList(items));
}
}
private void init(final int capacity, final Delegates.Function<T> callback) {
if (null != callback) {
synchronized (_pool) {
for (int i = 0; i < capacity; i++) {
final T item = callback.handle(i);
if (null != item) {
_pool.add(item);
}
}
}
}
}
private void putItem(final T item) {
synchronized (_pool) {
_pool.add(item);
}
}
public T firstItem() {
synchronized (_pool) {
return _pool.remove(0);
}
}
}