/*
* Copyright (C) 2014 Zhang,Yuexiang (xfeep)
* All rights reserved.
*/
package nginx.clojure;
import java.io.Serializable;
import nginx.clojure.wave.MethodDatabase;
public final class SuspendableConstructorUtilStack implements Serializable {
private static final long serialVersionUID = 1396934991052L;
private static final ThreadLocal<SuspendableConstructorUtilStack> cstacks = new ThreadLocal<SuspendableConstructorUtilStack>();
private static MethodDatabase db;
private long[] dataLong;
private Object[] dataObject;
private int sp = -1;
private int top = 0;
private int refs = 0;
private int desp = 0;
SuspendableConstructorUtilStack(int stackSize) {
if(stackSize <= 0) {
stackSize = 8;
}
this.dataLong = new long[stackSize];
this.dataObject = new Object[stackSize];
}
public static SuspendableConstructorUtilStack getStack() {
SuspendableConstructorUtilStack cs = cstacks.get();
if (cs == null) {
cstacks.set(cs = new SuspendableConstructorUtilStack(3));
}
return cs;
}
public static void setStack(SuspendableConstructorUtilStack cs) {
cstacks.set(cs);
}
public final boolean empty() {
return sp == -1;
}
public final void incRefsAndReserveSpace(int numSlots) {
refs++;
int dataTOS = top + numSlots;
sp = top;
top = dataTOS;
if (db != null && db.isDebug()) {
db.debug("th#%d: reserveSpace numSlots=%d, top=%d, nr(tos)=%d, %s", Thread.currentThread().getId(),numSlots, sp, Thread.currentThread().getStackTrace()[2]);
}
if(dataTOS > dataObject.length) {
growDataStack(dataTOS);
}
}
public static void push(int value, SuspendableConstructorUtilStack s, int idx) {
s.dataLong[s.sp + idx] = value;
}
public static void push(float value, SuspendableConstructorUtilStack s, int idx) {
s.dataLong[s.sp + idx] = Float.floatToRawIntBits(value);
}
public static void push(long value, SuspendableConstructorUtilStack s, int idx) {
s.dataLong[s.sp + idx] = value;
}
public static void push(double value, SuspendableConstructorUtilStack s, int idx) {
s.dataLong[s.sp + idx] = Double.doubleToRawLongBits(value);
}
public static void push(Object value, SuspendableConstructorUtilStack s, int idx) {
s.dataObject[s.sp + idx] = value;
}
public final int getInt(int idx) {
return (int)dataLong[desp + idx];
}
public final float getFloat(int idx) {
return Float.intBitsToFloat((int)dataLong[desp + idx]);
}
public final long getLong(int idx) {
return dataLong[desp + idx];
}
public final double getDouble(int idx) {
return Double.longBitsToDouble(dataLong[desp + idx]);
}
public final Object getObject(int idx) {
return dataObject[desp + idx];
}
public final void release(int c) {
desp += c;
if (--refs == 0) {
Stack.fillNull(dataObject, 0, top);
sp = -1;
top = 0;
desp = 0;
}
}
private void growDataStack(int required) {
int newSize = dataObject.length;
do {
newSize *= 2;
} while(newSize < required);
dataLong = Util.copyOf(dataLong, newSize);
dataObject = Util.copyOf(dataObject, newSize);
}
public static void setDb(MethodDatabase db) {
SuspendableConstructorUtilStack.db = db;
}
}