001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: ContinuationStack.java 3810 2007-06-25 13:36:58Z gbevin $
007: */
008: package com.uwyn.rife.continuations;
009:
010: import com.uwyn.rife.continuations.instrument.ContinuationDebug;
011: import com.uwyn.rife.tools.ObjectUtils;
012: import java.lang.reflect.Array;
013: import java.util.Arrays;
014:
015: /**
016: * [PRIVATE AND UNSUPPORTED] Contains the local state of a continuation.
017: * <p>This needs to be publicly accessible for the instrumented code to be
018: * able to interact with it, but it's not supposed to be used directly.
019: *
020: * @since 1.6
021: */
022: public class ContinuationStack {
023: static final int NONE = 0;
024: static final int INTEGER = 1;
025: static final int LONG = 2;
026: static final int FLOAT = 3;
027: static final int DOUBLE = 4;
028: static final int REFERENCE = 5;
029:
030: private int[] mPositionMapping = null;
031: private int[] mTypeMapping = null;
032: private int mStackHeight = 0;
033:
034: private int[] mIntStack = null;
035: private long[] mLongStack = null;
036: private float[] mFloatStack = null;
037: private double[] mDoubleStack = null;
038: private Object[] mReferenceStack = null;
039:
040: private int mIntTop = 0;
041: private int mLongTop = 0;
042: private int mDoubleTop = 0;
043: private int mFloatTop = 0;
044: private int mReferenceTop = 0;
045:
046: ContinuationStack() {
047: }
048:
049: ContinuationStack initialize() {
050: mIntStack = new int[10];
051: mLongStack = new long[5];
052: mFloatStack = new float[5];
053: mDoubleStack = new double[5];
054: mReferenceStack = new Object[5];
055:
056: mPositionMapping = new int[] { -1, -1, -1, -1, -1, -1, -1, -1,
057: -1, -1 };
058: mTypeMapping = new int[] { -1, -1, -1, -1, -1, -1, -1, -1, -1,
059: -1 };
060:
061: return this ;
062: }
063:
064: public synchronized int getType(int index) {
065: if (index <= mTypeMapping.length - 1) {
066: return mTypeMapping[index];
067: }
068: return NONE;
069: }
070:
071: public synchronized int popInt() {
072: return getInt(--mStackHeight);
073: }
074:
075: public synchronized long popLong() {
076: return getLong(--mStackHeight);
077: }
078:
079: public synchronized float popFloat() {
080: return getFloat(--mStackHeight);
081: }
082:
083: public synchronized double popDouble() {
084: return getDouble(--mStackHeight);
085: }
086:
087: public synchronized Object popReference() {
088: return getReference(--mStackHeight);
089: }
090:
091: public synchronized int getInt(int index) {
092: int position = mPositionMapping[index];
093: if (-1 == position || position >= mIntStack.length) {
094: return 0;
095: }
096: return mIntStack[position];
097: }
098:
099: public synchronized long getLong(int index) {
100: int position = mPositionMapping[index];
101: if (-1 == position || position >= mLongStack.length) {
102: return 0L;
103: }
104: return mLongStack[position];
105: }
106:
107: public synchronized float getFloat(int index) {
108: int position = mPositionMapping[index];
109: if (-1 == position || position >= mFloatStack.length) {
110: return 0f;
111: }
112: return mFloatStack[position];
113: }
114:
115: public synchronized double getDouble(int index) {
116: int position = mPositionMapping[index];
117: if (-1 == position || position >= mDoubleStack.length) {
118: return 0d;
119: }
120: return mDoubleStack[position];
121: }
122:
123: public synchronized Object getReference(int index) {
124: int position = mPositionMapping[index];
125: if (-1 == position || position >= mReferenceStack.length) {
126: return null;
127: }
128: return mReferenceStack[position];
129: }
130:
131: private synchronized void storeIndex(int index, int position,
132: int type) {
133: if (index > mPositionMapping.length - 1) {
134: int size = (((index + 1) / 10) + 1) * 10;
135: int[] new_positionmapping = new int[size];
136: int[] new_typemapping = new int[size];
137: Arrays.fill(new_positionmapping, mPositionMapping.length,
138: new_positionmapping.length, -1);
139: Arrays.fill(new_typemapping, mTypeMapping.length,
140: new_typemapping.length, -1);
141: System.arraycopy(mPositionMapping, 0, new_positionmapping,
142: 0, mPositionMapping.length);
143: System.arraycopy(mTypeMapping, 0, new_typemapping, 0,
144: mTypeMapping.length);
145: mPositionMapping = new_positionmapping;
146: mTypeMapping = new_typemapping;
147: }
148: mPositionMapping[index] = position;
149: mTypeMapping[index] = type;
150: }
151:
152: public synchronized void incrementInt(int index, int increment) {
153: int position = -1;
154:
155: position = mPositionMapping[index];
156: mIntStack[position] += increment;
157: }
158:
159: public synchronized void pushInt(int value) {
160: storeInt(mStackHeight++, value);
161: }
162:
163: public synchronized void pushLong(long value) {
164: storeLong(mStackHeight++, value);
165: }
166:
167: public synchronized void pushFloat(float value) {
168: storeFloat(mStackHeight++, value);
169: }
170:
171: public synchronized void pushDouble(double value) {
172: storeDouble(mStackHeight++, value);
173: }
174:
175: public synchronized void pushReference(Object value) {
176: storeReference(mStackHeight++, value);
177: }
178:
179: public synchronized void storeInt(int index, int value) {
180: int position = -1;
181:
182: if (getType(index) != INTEGER) {
183: position = mIntTop++;
184:
185: storeIndex(index, position, INTEGER);
186:
187: if (position > mIntStack.length - 1) {
188: int size = (((position + 1) / 10) + 1) * 10;
189: int[] new_stack = new int[size];
190: System.arraycopy(mIntStack, 0, new_stack, 0,
191: mIntStack.length);
192: mIntStack = new_stack;
193: }
194: } else {
195: position = mPositionMapping[index];
196: }
197:
198: mIntStack[position] = value;
199: }
200:
201: public synchronized void storeLong(int index, long value) {
202: int position = -1;
203:
204: if (getType(index) != LONG) {
205: position = mLongTop++;
206:
207: storeIndex(index, position, LONG);
208:
209: if (position > mLongStack.length - 1) {
210: int size = (((position + 1) / 10) + 1) * 10;
211: long[] new_stack = new long[size];
212: System.arraycopy(mLongStack, 0, new_stack, 0,
213: mLongStack.length);
214: mLongStack = new_stack;
215: }
216: } else {
217: position = mPositionMapping[index];
218: }
219:
220: mLongStack[position] = value;
221: }
222:
223: public synchronized void storeFloat(int index, float value) {
224: int position = -1;
225:
226: if (getType(index) != FLOAT) {
227: position = mFloatTop++;
228:
229: storeIndex(index, position, FLOAT);
230:
231: if (position > mFloatStack.length - 1) {
232: int size = (((position + 1) / 10) + 1) * 10;
233: float[] new_stack = new float[size];
234: System.arraycopy(mFloatStack, 0, new_stack, 0,
235: mFloatStack.length);
236: mFloatStack = new_stack;
237: }
238: } else {
239: position = mPositionMapping[index];
240: }
241:
242: mFloatStack[position] = value;
243: }
244:
245: public synchronized void storeDouble(int index, double value) {
246: int position = -1;
247:
248: if (getType(index) != DOUBLE) {
249: position = mDoubleTop++;
250:
251: storeIndex(index, position, DOUBLE);
252:
253: if (position > mDoubleStack.length - 1) {
254: int size = (((position + 1) / 10) + 1) * 10;
255: double[] new_stack = new double[size];
256: System.arraycopy(mDoubleStack, 0, new_stack, 0,
257: mDoubleStack.length);
258: mDoubleStack = new_stack;
259: }
260: } else {
261: position = mPositionMapping[index];
262: }
263:
264: mDoubleStack[position] = value;
265: }
266:
267: public synchronized void storeReference(int index, Object value) {
268: int position = -1;
269:
270: if (getType(index) != REFERENCE) {
271: position = mReferenceTop++;
272:
273: storeIndex(index, position, REFERENCE);
274:
275: if (position > mReferenceStack.length - 1) {
276: int size = (((position + 1) / 10) + 1) * 10;
277: Object[] new_stack = new Object[size];
278: System.arraycopy(mReferenceStack, 0, new_stack, 0,
279: mReferenceStack.length);
280: mReferenceStack = new_stack;
281: }
282: } else {
283: position = mPositionMapping[index];
284: }
285:
286: mReferenceStack[position] = value;
287: }
288:
289: ///CLOVER:OFF
290: public synchronized void outputState() {
291: ContinuationDebug.LOGGER.finest("");
292: ContinuationDebug.LOGGER.finest("STACK : " + this );
293: ContinuationDebug.LOGGER.finest("mPositionMapping["
294: + mPositionMapping.length + "] = "
295: + join(mPositionMapping, ","));
296: ContinuationDebug.LOGGER.finest("mTypeMapping["
297: + mTypeMapping.length + "] = "
298: + join(mTypeMapping, ","));
299: ContinuationDebug.LOGGER.finest("mIntStack[" + mIntStack.length
300: + "] = " + join(mIntStack, ","));
301: ContinuationDebug.LOGGER.finest("mLongStack["
302: + mLongStack.length + "] = "
303: + join(mLongStack, ","));
304: ContinuationDebug.LOGGER.finest("mFloatStack["
305: + mFloatStack.length + "] = "
306: + join(mFloatStack, ","));
307: ContinuationDebug.LOGGER.finest("mDoubleStack["
308: + mDoubleStack.length + "] = "
309: + join(mDoubleStack, ","));
310: ContinuationDebug.LOGGER.finest("mReferenceStack["
311: + mReferenceStack.length + "] = "
312: + join(mReferenceStack, ","));
313: }
314:
315: // adding a join method here to remove a viral dependency on the StringUtils class
316: private static String join(Object array, String separator) {
317: if (null == array) {
318: return "";
319: }
320:
321: if (!array.getClass().isArray()) {
322: return String.valueOf(array);
323: }
324:
325: StringBuilder result = new StringBuilder();
326: for (int i = 0; i < Array.getLength(array); i++) {
327: if (result.length() > 0) {
328: result.append(separator);
329: }
330:
331: result.append(Array.get(array, i));
332: }
333:
334: return result.toString();
335: }
336:
337: ///CLOVER:ON
338:
339: public synchronized ContinuationStack clone(Object elementInstance)
340: throws CloneNotSupportedException {
341: ContinuationStack new_stack = new ContinuationStack();
342:
343: new_stack.mPositionMapping = mPositionMapping.clone();
344: new_stack.mTypeMapping = mTypeMapping.clone();
345: new_stack.mStackHeight = mStackHeight;
346:
347: new_stack.mIntStack = mIntStack.clone();
348: new_stack.mLongStack = mLongStack.clone();
349: new_stack.mFloatStack = mFloatStack.clone();
350: new_stack.mDoubleStack = mDoubleStack.clone();
351: new_stack.mReferenceStack = new Object[mReferenceStack.length];
352: for (int i = 0; i < mReferenceStack.length; i++) {
353: if (mReferenceStack[i] != null
354: && mReferenceStack[i].getClass() == elementInstance
355: .getClass()) {
356: new_stack.mReferenceStack[i] = elementInstance;
357: } else {
358: new_stack.mReferenceStack[i] = ObjectUtils
359: .deepClone(mReferenceStack[i]);
360: }
361: }
362:
363: new_stack.mIntTop = mIntTop;
364: new_stack.mLongTop = mLongTop;
365: new_stack.mDoubleTop = mDoubleTop;
366: new_stack.mFloatTop = mFloatTop;
367: new_stack.mReferenceTop = mReferenceTop;
368:
369: return new_stack;
370: }
371: }
|