cz.advel.stack.Stack Maven / Gradle / Ivy
Show all versions of stack-alloc Show documentation
/*
* 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 java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* 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:
*
* - classes needs to be instrumented by provided InstrumentationTask for ANT, otherwise
* error is throwed in runtime
* - stack is pushed only once per method, do not use stack allocation in loops
* - returning of stack allocated objects is not supported, use output parameter instead (like in the
* example)
* - working with stack is thread-safe, the data are separate for each thread
* - combining different libraries works fine, each must have their stack stored
* in different package, so you'll just end up with multiple stacks in final application,
* which is fine, because the values are used between them without problem
*
- when creating and destroying threads you must be aware that the implementation
* uses ThreadLocal to persist stack instances between method calls, it's advisable
* to call
cleanCurrentThread
method on thread just before destroying
*
*
*
* @author jezek2
*/
public class Stack {
final private static List> threadLocalList = new ArrayList>();
private Stack() {
}
/**
* Returns stack allocated object.
*
* Requires instrumentation of your classes in order to work.
*
* @param the type of object to allocate
* @param cls class type, must be compile-time constant
* @return stack allocated instance of given class
*/
public static T alloc(Class cls) {
throw new Error("not instrumented");
}
/**
* Returns stack allocated object with copied value from given parameter.
*
* Requires instrumentation of your classes in order to work.
*
* @param the type of object to allocate
* @param obj object to copy on stack, the type must be statically known
* @return stack allocated instance with copied data
*/
public static T alloc(T obj) {
throw new Error("not instrumented");
}
/**
* Used internally.
*
* @param local the thread-local data to be registered
*/
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.
*/
public static void libraryCleanCurrentThread() {
throw new Error("not instrumented");
}
}