/* * JStackAlloc (c) 2008 Martin Dvorak * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ package cz.advel.stack; import cz.advel.stack.instrument.InstrumentationTask; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.io.*; /** * Support for stack allocation of "value" objects. The only requirements for "value" * objects is that they must have public zero argument constructor and set * method with one argument of the same type (or superclass) which copies data from * given instance.

* * Example usage: *

 * public static Vector3f average(Vector3f v1, Vector3f v2, Vector3f out) {
 *     out.add(v1, v2);
 *     out.scale(0.5f);
 *     return out;
 * }
 * 
 * public static void test() {
 *     Vector3f v1 = Stack.alloc(Vector3f.class);
 *     v1.set(0f, 1f, 2f);
 * 
 *     Vector3f v2 = Stack.alloc(v1);
 *     v2.x = 10f;
 * 
 *     Vector3f avg = average(v1, v2, Stack.alloc(Vector3f.class));
 * }
 * 
* which is transformed into something like the following code. The actual * generated code has mangled names for unique type identification and can have * other minor differences. *
 * public static void test() {
 *     $Stack stack = $Stack.get();
 *     stack.pushVector3f();
 *     try {
 *         Vector3f v1 = stack.getVector3f();
 *         v1.set(0f, 1f, 2f);
 * 
 *         Vector3f v2 = stack.getVector3f(v1);
 *         v2.x = 10f;
 * 
 *         Vector3f avg = average(v1, v2, stack.getVector3f());
 *     }
 *     finally {
 *         stack.popVector3f();
 *     }
 * }
 * 
* * Rules: * * * @author jezek2 */ public class Stack { private static List> threadLocalList = new ArrayList>(); private Stack() { } /** * Returns stack allocated object.

* * Requires instrumentation of your classes in order to work. * * @param cls class type, must be compile-time constant * @return stack allocated instance of given class */ public static T alloc(Class cls) { try { return (T) cls.newInstance(); } catch (Exception e) { throw new Error("not instrumented"); // return null; } } /** * Returns stack allocated object with copied value from given parameter.

* * Requires instrumentation of your classes in order to work. * * @param obj object to copy on stack, the type must be statically known * @return stack allocated instance with copied data */ public static Object alloc(T obj) { if (obj == null) return null; if (obj instanceof javax.vecmath.Vector3f) { return new javax.vecmath.Vector3f((javax.vecmath.Vector3f) obj); } if (obj instanceof javax.vecmath.Matrix3f) { return new javax.vecmath.Matrix3f((javax.vecmath.Matrix3f) obj); } if (obj instanceof com.bulletphysics.linearmath.Transform) { com.bulletphysics.linearmath.Transform t = (com.bulletphysics.linearmath.Transform) obj; com.bulletphysics.linearmath.Transform tr = new com.bulletphysics.linearmath.Transform(); tr.basis.set(t.basis); tr.origin.set(t.origin); return tr; } return (T) serialclone(obj); //throw new Error("not instrumented"); } static public Object serialclone(Object o) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(o); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bais); Object obj = in.readObject(); in.close(); out.close(); return obj; } catch (Exception e) { System.err.println(e); return null; } } /** * Used internally. */ public static synchronized void internalRegisterThreadLocal(ThreadLocal local) { threadLocalList.add(new WeakReference(local)); } /** * Removes all cached stack instances for current thread. */ public static synchronized void cleanCurrentThread() { for (Iterator> it = threadLocalList.iterator(); it.hasNext(); ) { WeakReference ref = it.next(); ThreadLocal local = ref.get(); if (local != null) { local.remove(); } else { it.remove(); } } } /** * Removes all cached stack instances for current thread in current library.

* * Requires instrumentation of your classes in order to work. * * @see InstrumentationTask#setIsolated(boolean) */ public static void libraryCleanCurrentThread() { throw new Error("not instrumented"); } }