io.legaldocml.pool.UnsafePool Maven / Gradle / Ivy
The newest version!
package io.legaldocml.pool;
import io.legaldocml.unsafe.UnsafeHelper;
import java.io.Closeable;
/**
* @author Jacques Militello
*/
final class UnsafePool implements Pool>, Closeable{
private final long adr;
private static final sun.misc.Unsafe UNSAFE = UnsafeHelper.getUnsafe();
private final UnsafeHolder[] holders;
private final int size;
private final PoolableObject poolableObject;
private int index;
private boolean isClosed;
@SuppressWarnings("unchecked")
UnsafePool(int size, PoolableObject poolableObject) {
this.poolableObject = poolableObject;
this.adr = UNSAFE.allocateMemory((long)size * 8);
this.holders = new UnsafeHolder[size];
for (int i = 0; i < size; i++) {
holders[i] = new UnsafeHolder(poolableObject.newInstance());
}
this.size = size;
this.isClosed = false;
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings("unchecked")
public UnsafeHolder checkOut() {
int size = this.size;
int index = this.index;
UnsafeHolder[] holders = this.holders;
for (int i = index; i < size; i++) {
if (UNSAFE.compareAndSwapInt(holders[i], UnsafeHolder.FIELD_OFFSET, UnsafeHolder.FREE, UnsafeHolder.USED)) {
// it's free => return;
this.index = i;
return holders[i];
}
}
for (int i = 0; i < index; i++) {
if (UNSAFE.compareAndSwapInt(holders[i], UnsafeHolder.FIELD_OFFSET, UnsafeHolder.FREE, UnsafeHolder.USED)) {
this.index = i;
// it's free => return;
return holders[i];
}
}
// all are used => retry
return checkOut(0, size, holders);
}
@SuppressWarnings("unchecked")
private UnsafeHolder checkOut(int count, int size, UnsafeHolder[] holders) {
if (count == 100) {
return new UnsafeHolder<>(poolableObject.newInstance(), UnsafeHolder.SINGLE);
}
Thread.yield();
for (int i = 0; i < size; i++) {
if (UNSAFE.compareAndSwapInt(holders[i], UnsafeHolder.FIELD_OFFSET, UnsafeHolder.FREE, UnsafeHolder.USED)) {
return holders[i];
}
}
return checkOut(count + 1, size, holders);
}
/**
* {@inheritDoc}
*/
@Override
public void checkIn(PoolHolder holder) {
// single instance => not a member of the pool ==> skip
if (UnsafeHolder.SINGLE == holder.getState()) {
return;
}
holder.setState(UnsafeHolder.FREE);
this.poolableObject.passivate(holder.get());
}
/**
* {@inheritDoc}
*/
@Override
public void close() {
if (!this.isClosed) {
UNSAFE.freeMemory(this.adr);
this.isClosed = true;
}
}
/**
* {@inheritDoc}
*/
@Override
protected void finalize() throws Throwable {
close();
super.finalize();
}
}