[jffi-next] 21/22: Rollback closure allocation changes for 0.6.0.1 maintenance release
Tim Potter
tpot-guest at moszumanska.debian.org
Wed Mar 4 04:51:24 UTC 2015
This is an automated email from the git hooks/post-receive script.
tpot-guest pushed a commit to tag 0.6.0.1
in repository jffi-next.
commit d5539e6caf58868719cb7e62ead5397f5e6ae820
Author: Wayne Meissner <wmeissner at gmail.com>
Date: Sat Oct 17 06:29:15 2009 +1000
Rollback closure allocation changes for 0.6.0.1 maintenance release
---
custom-build.xml | 2 +-
src/com/kenai/jffi/CallContext.java | 105 ----------
src/com/kenai/jffi/CallContextCache.java | 126 ------------
src/com/kenai/jffi/CallInfo.java | 8 -
src/com/kenai/jffi/Closure.java | 3 -
src/com/kenai/jffi/ClosureManager.java | 308 +++++++++++++++++++++++++---
src/com/kenai/jffi/ClosurePool.java | 281 -------------------------
src/com/kenai/jffi/DirectClosureBuffer.java | 145 -------------
8 files changed, 277 insertions(+), 701 deletions(-)
diff --git a/custom-build.xml b/custom-build.xml
index 058bcf0..8bb94e9 100644
--- a/custom-build.xml
+++ b/custom-build.xml
@@ -10,7 +10,7 @@
<property name="complete.jar" value="${dist.dir}/jffi-complete.jar"/>
<property name="jffi.version.major" value="0"/>
<property name="jffi.version.minor" value="6"/>
- <property name="jffi.version.micro" value="1"/>
+ <property name="jffi.version.micro" value="0"/>
<mkdir dir="${build.native.dir}"/>
<!-- normalize the various os.arch naming conventions -->
diff --git a/src/com/kenai/jffi/CallContext.java b/src/com/kenai/jffi/CallContext.java
deleted file mode 100644
index c869182..0000000
--- a/src/com/kenai/jffi/CallContext.java
+++ /dev/null
@@ -1,105 +0,0 @@
-
-package com.kenai.jffi;
-
-/**
- * Native function call context
- *
- * This class holds all the information that JFFI needs to correctly call a
- * native function, or to implement a callback from native code to java.
- */
-public final class CallContext implements CallInfo {
-
- /** The return type of this function */
- private final Type returnType;
-
- /** The parameter types of this function */
- private final Type[] parameterTypes;
-
- final int flags;
-
- final long nativeReturnType;
-
- final long[] nativeParameterTypes;
-
- /**
- * Creates a new instance of <tt>Function</tt> with default calling convention.
- *
- * @param address The native address of the function to invoke.
- * @param returnType The return type of the native function.
- * @param parameterTypes The parameter types the function accepts.
- */
- public CallContext(Type returnType, Type... paramTypes) {
- this(returnType, paramTypes, CallingConvention.DEFAULT, true);
- }
-
- /**
- * Creates a new instance of <tt>Function</tt>.
- *
- * <tt>Function</tt> instances created with this constructor will save the
- * C errno contents after each call.
- *
- * @param address The native address of the function to invoke.
- * @param returnType The return type of the native function.
- * @param parameterTypes The parameter types the function accepts.
- * @param convention The calling convention of the function.
- */
- public CallContext(Type returnType, Type[] paramTypes, CallingConvention convention) {
- this(returnType, paramTypes, convention, true);
- }
-
- /**
- * Creates a new instance of <tt>Function</tt>.
- *
- * @param address The native address of the function to invoke.
- * @param returnType The return type of the native function.
- * @param parameterTypes The parameter types the function accepts.
- * @param convention The calling convention of the function.
- * @param saveErrno Whether the errno should be saved or not
- */
- public CallContext(Type returnType, Type[] paramTypes, CallingConvention convention, boolean saveErrno) {
-
- this.flags = (!saveErrno ? Foreign.F_NOERRNO : 0)
- | (convention == CallingConvention.STDCALL ? Foreign.F_STDCALL : Foreign.F_DEFAULT);
-
- //
- // Keep references to the return and parameter types so they do not get
- // garbage collected
- //
- this.returnType = returnType;
- this.parameterTypes = (Type[]) paramTypes.clone();
-
- this.nativeReturnType = returnType.handle();
- this.nativeParameterTypes = Type.nativeHandles(paramTypes);
- }
-
- /**
- * Gets the number of parameters the native function accepts.
- *
- * @return The number of parameters the native function accepts.
- */
- public final int getParameterCount() {
- return parameterTypes.length;
- }
-
- /**
- * Gets the native return type of this function.
- *
- * @return The native return type of this function.
- */
- public final Type getReturnType() {
- return returnType;
- }
-
- /**
- * Gets the type of a parameter.
- *
- * @param index The index of the parameter in the function signature
- * @return The <tt>Type</tt> of the parameter.
- */
- public final Type getParameterType(int index) {
- return parameterTypes[index];
- }
-
- public synchronized final void dispose() {
- }
-}
diff --git a/src/com/kenai/jffi/CallContextCache.java b/src/com/kenai/jffi/CallContextCache.java
deleted file mode 100644
index 54e825a..0000000
--- a/src/com/kenai/jffi/CallContextCache.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package com.kenai.jffi;
-
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class CallContextCache {
-
- private final Map<Signature, CallContextRef> contextCache = new ConcurrentHashMap<Signature, CallContextRef>();
- private final ReferenceQueue<CallContext> contextReferenceQueue = new ReferenceQueue<CallContext>();
-
- /** Holder class to do lazy allocation of the ClosureManager instance */
- private static final class SingletonHolder {
- static final CallContextCache INSTANCE = new CallContextCache();
- }
-
- /**
- * Gets the global instance of the <tt>CallContextCache</tt>
- *
- * @return An instance of a <tt>CallContextCache</tt>
- */
- public static final CallContextCache getInstance() {
- return SingletonHolder.INSTANCE;
- }
-
- /** Constructs a ClosureManager */
- private CallContextCache() { }
-
- public final CallContext getCallContext(Type returnType, Type[] parameterTypes, CallingConvention convention) {
- Signature signature = new Signature(returnType, parameterTypes, convention);
- CallContextRef ref = contextCache.get(signature);
- CallContext ctx;
-
- if (ref != null && (ctx = ref.get()) != null) {
- return ctx;
- }
-
- // Cull any dead references
- while ((ref = (CallContextRef) contextReferenceQueue.poll()) != null) {
- contextCache.remove(ref.signature);
- }
-
- ctx = new CallContext(returnType, (Type[]) parameterTypes.clone(), convention);
- contextCache.put(signature, new CallContextRef(signature, ctx, contextReferenceQueue));
-
- return ctx;
- }
-
- private static final class CallContextRef extends SoftReference<CallContext> {
-
- final Signature signature;
-
- public CallContextRef(Signature signature, CallContext ctx, ReferenceQueue<CallContext> queue) {
- super(ctx, queue);
- this.signature = signature;
- }
- }
-
- private static final class Signature {
-
- /**
- * Keep references to the return and parameter types so they do not get
- * garbage collected until the closure does.
- */
- private final Type returnType;
- private final Type[] parameterTypes;
- private final CallingConvention convention;
- private int hashCode = 0;
-
- public Signature(Type returnType, Type[] parameterTypes, CallingConvention convention) {
- if (returnType == null || parameterTypes == null) {
- throw new NullPointerException("null return type or parameter types array");
- }
- this.returnType = returnType;
- this.parameterTypes = parameterTypes;
- this.convention = convention;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
-
- final Signature other = (Signature) obj;
-
- if (this.convention != other.convention) {
- return false;
- }
-
- if (this.returnType != other.returnType && !this.returnType.equals(other.returnType)) {
- return false;
- }
-
- if (this.parameterTypes.length == other.parameterTypes.length) {
- for (int i = 0; i < this.parameterTypes.length; ++i) {
- if (this.parameterTypes[i] != other.parameterTypes[i] && (this.parameterTypes[i] == null || !this.parameterTypes[i].equals(other.parameterTypes[i]))) {
- return false;
- }
- }
- // All param types are same, return type is same, convention is same, so this is the same signature
- return true;
- }
-
- return false;
- }
-
- private final int calculateHashCode() {
- int hash = 7;
- hash = 53 * hash + (this.returnType != null ? this.returnType.hashCode() : 0);
- int paramHash = 1;
- for (int i = 0; i < parameterTypes.length; ++i) {
- paramHash = 31 * paramHash + parameterTypes[i].hashCode();
- }
- hash = 53 * hash + paramHash;
- hash = 53 * hash + this.convention.hashCode();
- return hash;
- }
-
- @Override
- public int hashCode() {
- return hashCode != 0 ? hashCode : (hashCode = calculateHashCode());
- }
- }
-}
diff --git a/src/com/kenai/jffi/CallInfo.java b/src/com/kenai/jffi/CallInfo.java
deleted file mode 100644
index 2e95647..0000000
--- a/src/com/kenai/jffi/CallInfo.java
+++ /dev/null
@@ -1,8 +0,0 @@
-
-package com.kenai.jffi;
-
-public interface CallInfo {
- int getParameterCount();
- public Type getReturnType();
- public Type getParameterType(int parameterIndex);
-}
diff --git a/src/com/kenai/jffi/Closure.java b/src/com/kenai/jffi/Closure.java
index 4807d01..a7c1bbb 100644
--- a/src/com/kenai/jffi/Closure.java
+++ b/src/com/kenai/jffi/Closure.java
@@ -174,9 +174,6 @@ public interface Closure {
* time, and is non-deterministic. This allows explicit control over
* memory reclamation.
*/
- void dispose();
-
- //@Deprecated
void free();
}
}
diff --git a/src/com/kenai/jffi/ClosureManager.java b/src/com/kenai/jffi/ClosureManager.java
index 2cb1084..eda39c6 100644
--- a/src/com/kenai/jffi/ClosureManager.java
+++ b/src/com/kenai/jffi/ClosureManager.java
@@ -1,24 +1,15 @@
package com.kenai.jffi;
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
-import java.util.Map;
-import java.util.WeakHashMap;
+import java.lang.reflect.Method;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
- * Allocates and manages the lifecycle of native closures (aka callbacks)
+ * Allocates and manages the lifecycle of native closures (aka callbacks).rm hs
*/
public class ClosureManager {
-
- /**
- * ClosurePool instances are linked via a SoftReference in the lookup map, so
- * when all closure instances that that were allocated from the ClosurePool have been
- * reclaimed, and there is memory pressure, the native closure pool can be freed.
- * This will allow the CallContext instance to also be collected if it is not
- * strongly referenced elsewhere, and ejected from the {@link CallContextCache}
- */
- private final Map<CallContext, Reference<ClosurePool>> poolMap = new WeakHashMap<CallContext, Reference<ClosurePool>>();
+ private static final long ADDRESS_MASK = Platform.getPlatform().addressMask();
+ private static final Object lock = new Object();
/** Holder class to do lazy allocation of the ClosureManager instance */
private static final class SingletonHolder {
@@ -48,34 +39,287 @@ public class ClosureManager {
* @return A new {@link Closure.Handle} instance.
*/
public final Closure.Handle newClosure(Closure closure, Type returnType, Type[] parameterTypes, CallingConvention convention) {
- return newClosure(closure, CallContextCache.getInstance().getCallContext(returnType, parameterTypes, convention));
+ Proxy proxy = new Proxy(closure, returnType, parameterTypes);
+
+ long handle = 0;
+ synchronized (lock) {
+ handle = Foreign.getInstance().newClosure(proxy, Proxy.METHOD,
+ returnType.handle(), Type.nativeHandles(parameterTypes), 0);
+ }
+ if (handle == 0) {
+ throw new RuntimeException("Failed to create native closure");
+ }
+
+ return new Handle(handle, returnType, parameterTypes);
}
/**
- * Wraps a java object that implements the {@link Closure} interface in a
- * native closure.
+ * Manages the lifecycle of a native closure.
*
- * @param closure The java object to be called when the native closure is invoked.
- * @param returnType The return type of the closure.
- * @param parameterTypes The parameter types of the closure.
- * @param convention The calling convention of the closure.
- * @return A new {@link Closure.Handle} instance.
+ * Implements {@link Closure.Handle} interface.
+ */
+ private static final class Handle implements Closure.Handle {
+ /** Store a reference to the MemoryIO accessor here for easy access */
+ private static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance();
+
+ private final AtomicBoolean released = new AtomicBoolean(false);
+ private volatile boolean autorelease = true;
+
+ /**
+ * The address of the native closure structure.
+ *
+ * <b>Note:</b> This is <b>NOT</b> the code address, but a pointer to the structure
+ * which contains the code address.
+ */
+ final long handle;
+
+ /** The code trampoline address */
+ final long cbAddress;
+
+ /**
+ * Keep references to the return and parameter types so they do not get
+ * garbage collected until the closure does.
+ */
+ private final Type returnType;
+ private final Type[] parameterTypes;
+
+ /**
+ * Creates a new Handle to lifecycle manager the native closure.
+ *
+ * @param handle The address of the native closure structure.
+ */
+ Handle(long handle, Type returnType, Type[] parameterTypes) {
+ this.handle = handle;
+ cbAddress = IO.getAddress(handle);
+ this.returnType = returnType;
+ this.parameterTypes = (Type[]) parameterTypes.clone();
+ }
+
+ public long getAddress() {
+ return cbAddress;
+ }
+
+ public void setAutoRelease(boolean autorelease) {
+ this.autorelease = autorelease;
+ }
+
+ public void free() {
+ if (released.getAndSet(true)) {
+ throw new IllegalStateException("Closure already released");
+ }
+ synchronized (lock) {
+ Foreign.getInstance().freeClosure(handle);
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ if (autorelease && !released.getAndSet(true)) {
+ synchronized (lock) {
+ Foreign.getInstance().freeClosure(handle);
+ }
+ }
+ } catch (Throwable t) {
+ t.printStackTrace(System.err);
+ } finally {
+ super.finalize();
+ }
+ }
+ }
+
+ /**
+ * This is a proxy passed to the native code, to be called by the
+ * native trampoline code.
+ */
+ private static final class Proxy {
+ static final Method METHOD = getMethod();
+ final Closure closure;
+
+ /**
+ * Keep references to the return and parameter types so they do not get
+ * garbage collected until the closure does.
+ */
+ final Type returnType;
+ final Type[] parameterTypes;
+
+ /**
+ * Gets the
+ * @return
+ */
+ private static final Method getMethod() {
+ try {
+ return Proxy.class.getDeclaredMethod("invoke", new Class[] { long.class, long.class });
+ } catch (Throwable ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * Creates a new <tt>Proxy</tt> instance.
+ *
+ * @param closure The closure to call when this proxy is invoked
+ * @param returnType The native return type of the closure
+ * @param parameterTypes The parameterTypes of the closure
+ */
+ Proxy(Closure closure, Type returnType, Type[] parameterTypes) {
+ this.closure = closure;
+ this.returnType = returnType;
+ this.parameterTypes = (Type[]) parameterTypes.clone();
+ }
+
+ /**
+ * Invoked by the native closure trampoline to execute the java side of
+ * the closure.
+ *
+ * @param retvalAddress The address of the native return value buffer
+ * @param paramAddress The address of the native parameter buffer.
+ */
+ void invoke(long retvalAddress, long paramAddress) {
+ closure.invoke(new DirectBuffer(returnType, parameterTypes, retvalAddress, paramAddress));
+ }
+ }
+
+ /**
+ * Implementation of the {@link Closure.Buffer} interface to read/write
+ * parameter and return value data in native memory
+ */
+ private static final class DirectBuffer implements Closure.Buffer {
+ private static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance();
+ private static final NativeWordIO WordIO = NativeWordIO.getInstance();
+ private static final int PARAM_SIZE = Platform.getPlatform().addressSize() / 8;
+ private final long retval, parameters;
+
+ /* Keep references to the return and parameter types to prevent garbage collection */
+ private final Type returnType;
+ private final Type[] parameterTypes;
+
+ public DirectBuffer(Type returnType, Type[] parameterTypes, long retval, long parameters) {
+ this.returnType = returnType;
+ this.parameterTypes = parameterTypes;
+ this.retval = retval;
+ this.parameters = parameters;
+ }
+
+ public final byte getByte(int index) {
+ return IO.getByte(IO.getAddress(parameters + (index * PARAM_SIZE)));
+ }
+
+ public final short getShort(int index) {
+ return IO.getShort(IO.getAddress(parameters + (index * PARAM_SIZE)));
+ }
+
+ public final int getInt(int index) {
+ return IO.getInt(IO.getAddress(parameters + (index * PARAM_SIZE)));
+ }
+
+ public final long getLong(int index) {
+ return IO.getLong(IO.getAddress(parameters + (index * PARAM_SIZE)));
+ }
+
+ public final float getFloat(int index) {
+ return IO.getFloat(IO.getAddress(parameters + (index * PARAM_SIZE)));
+ }
+
+ public final double getDouble(int index) {
+ return IO.getDouble(IO.getAddress(parameters + (index * PARAM_SIZE)));
+ }
+
+ public final long getAddress(int index) {
+ return IO.getAddress(IO.getAddress(parameters + (index * PARAM_SIZE))) & ADDRESS_MASK;
+ }
+
+ public final long getStruct(int index) {
+ return IO.getAddress(parameters + (index * PARAM_SIZE));
+ }
+
+ public final void setByteReturn(byte value) {
+ WordIO.put(retval, value);
+ }
+
+ public final void setShortReturn(short value) {
+ WordIO.put(retval, value);
+ }
+
+ public final void setIntReturn(int value) {
+ WordIO.put(retval, value);
+ }
+
+ public final void setLongReturn(long value) {
+ IO.putLong(retval, value);
+ }
+
+ public final void setFloatReturn(float value) {
+ IO.putFloat(retval, value);
+ }
+
+ public final void setDoubleReturn(double value) {
+ IO.putDouble(retval, value);
+ }
+
+ public final void setAddressReturn(long address) {
+ IO.putAddress(retval, address);
+ }
+
+ public void setStructReturn(long value) {
+ IO.copyMemory(value, retval, returnType.size());
+ }
+
+ public void setStructReturn(byte[] data, int offset) {
+ IO.putByteArray(retval, data, offset, returnType.size());
+ }
+ }
+
+ /**
+ * Reads annd writes data types that are smaller than the size of a native
+ * long, as a native long for compatibility with FFI.
*/
- public final Closure.Handle newClosure(Closure closure, CallContext callContext) {
- ClosurePool pool = getClosurePool(callContext);
+ private static abstract class NativeWordIO {
+ public static final NativeWordIO getInstance() {
+ return Platform.getPlatform().addressSize() == 32
+ ? NativeWordIO32.INSTANCE : NativeWordIO64.INSTANCE;
+ }
+
+ /**
+ * Writes a native long argument to native memory.
+ *
+ * @param address The address to write the value at
+ * @param value The value to write.
+ */
+ abstract void put(long address, int value);
- return pool.newClosureHandle(closure);
+ /**
+ * Reads a native long argument from native memory.
+ * @param address The memory address to read the value from
+ * @return An integer
+ */
+ abstract int get(long address);
}
- private final synchronized ClosurePool getClosurePool(CallContext callContext) {
- Reference<ClosurePool> ref = poolMap.get(callContext);
- ClosurePool pool;
- if (ref != null && (pool = ref.get()) != null) {
- return pool;
+ private static final class NativeWordIO32 extends NativeWordIO {
+ private static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance();
+ static final NativeWordIO INSTANCE = new NativeWordIO32();
+
+ void put(long address, int value) {
+ IO.putInt(address, value);
}
- poolMap.put(callContext, new SoftReference<ClosurePool>(pool = new ClosurePool(callContext)));
+ int get(long address) {
+ return IO.getInt(address);
+ }
+ }
- return pool;
+ private static final class NativeWordIO64 extends NativeWordIO {
+
+ private static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance();
+ static final NativeWordIO INSTANCE = new NativeWordIO64();
+
+ void put(long address, int value) {
+ IO.putLong(address, value);
+ }
+
+ int get(long address) {
+ return (int) IO.getLong(address);
+ }
}
}
diff --git a/src/com/kenai/jffi/ClosurePool.java b/src/com/kenai/jffi/ClosurePool.java
deleted file mode 100644
index 1c9c950..0000000
--- a/src/com/kenai/jffi/ClosurePool.java
+++ /dev/null
@@ -1,281 +0,0 @@
-package com.kenai.jffi;
-
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-final class ClosurePool {
-
- private final List<MagazineHolder> partial = new LinkedList<MagazineHolder>();
- private final List<MagazineHolder> full = new LinkedList<MagazineHolder>();
- private final Set<Magazine> magazines = new HashSet<Magazine>();
- //
- // Since the CallContext native handle is used by the native pool code
- // a strong reference to the call context needs to be kept.
- //
- private final CallContext callContext;
-
- ClosurePool(CallContext callContext) {
- this.callContext = callContext;
- }
-
- synchronized void recycle(Magazine magazine) {
- magazine.recycle();
- if (!magazine.isEmpty()) {
- MagazineHolder h = new MagazineHolder(this, magazine);
- if (magazine.isFull()) {
- full.add(h);
- } else {
- partial.add(h);
- }
- } else {
- // If the magazine was empty during recycling, it means all the closures
- // allocated from it set autorelease=false, so we cannot re-use it.
- // Let GC clean it up.
- magazines.remove(magazine);
- }
- }
-
- private synchronized MagazineHolder getMagazineHolder() {
- if (!partial.isEmpty()) {
- return partial.get(0);
- } else if (!full.isEmpty()) {
- MagazineHolder h = full.remove(0);
- partial.add(h);
- return h;
- }
- Magazine m = new Magazine(callContext);
- MagazineHolder h = new MagazineHolder(this, m);
- partial.add(h);
- magazines.add(m);
- return h;
- }
-
- public synchronized Closure.Handle newClosureHandle(Closure closure) {
- Magazine.Slot s = null;
- MagazineHolder h = null;
- do {
- h = getMagazineHolder();
- s = h.magazine.get();
- if (s == null) {
- partial.remove(0);
- }
- } while (s == null);
- s.proxy.closure = closure;
- return new Handle(s, h);
- }
-
- /**
- * Manages the lifecycle of a native closure.
- *
- * Implements {@link Closure.Handle} interface.
- */
- private static final class Handle implements Closure.Handle {
- /**
- * Keep references to the closure pool so it does not get garbage collected
- * until all closures using it do.
- */
- private final MagazineHolder holder;
- private final Magazine.Slot slot;
-
- private volatile boolean disposed = false;
-
- /**
- * Creates a new Handle to lifecycle manager the native closure.
- *
- * @param handle The address of the native closure structure.
- * @param pool The native pool the closure was allocated from.
- */
- Handle(Magazine.Slot slot, MagazineHolder holder) {
- this.slot = slot;
- this.holder = holder;
- }
-
- public long getAddress() {
- return slot.cbAddress;
- }
-
- public void setAutoRelease(boolean autorelease) {
- slot.autorelease = autorelease;
- }
-
- @Deprecated
- public void free() {
- dispose();
- }
-
- public synchronized void dispose() {
- if (disposed) {
- throw new IllegalStateException("closure already disposed");
- }
- disposed = true;
- slot.autorelease = true;
- }
- }
-
- private static final class Magazine {
- private static final int MAX_SLOTS = 200;
-
- /** Store a reference to the MemoryIO accessor here for easy access */
- private static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance();
-
- private final CallContext ctx;
-
- private final List<Slot> free = new ArrayList<Slot>(MAX_SLOTS);
- private final List<Slot> all = new ArrayList<Slot>(MAX_SLOTS);
-
- Magazine(CallContext ctx) {
- this.ctx = ctx;
- }
-
- Slot get() {
- if (!free.isEmpty()) {
- return free.remove(free.size() - 1);
- }
-
- return all.size() < MAX_SLOTS ? newSlot() : null;
- }
-
- private Slot newSlot() {
- Proxy proxy = new Proxy(ctx);
- long h = Foreign.getInstance().newClosure(proxy, Proxy.METHOD, ctx.nativeReturnType, ctx.nativeParameterTypes, ctx.flags);
- if (h == 0) {
- return null;
- }
- Slot s = new Slot(h, proxy);
- all.add(s);
- return s;
- }
-
- boolean isFull() {
- return free.size() == all.size();
- }
-
- boolean isEmpty() {
- return free.isEmpty();
- }
-
- void recycle() {
- free.clear();
- for (Slot s : all) {
- if (s.autorelease) {
- s.proxy.closure = NULL_CLOSURE;
- free.add(s);
- }
- }
- all.retainAll(free);
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- for (Slot s : all) {
- if (s.autorelease) {
- Foreign.getInstance().freeClosure(s.handle);
- }
-
- }
- } finally {
- super.finalize();
- }
- }
-
- static final class Slot {
- /**
- * The address of the native closure structure.
- *
- * <b>Note:</b> This is <b>NOT</b> the code address, but a pointer to the structure
- * which contains the code address.
- */
- final long handle;
-
- /** The code trampoline address */
- final long cbAddress;
-
- final Proxy proxy;
- volatile boolean autorelease;
-
- public Slot(long handle, Proxy proxy) {
- this.handle = handle;
- this.proxy = proxy;
- this.autorelease = true;
- cbAddress = IO.getAddress(handle);
- }
- }
- }
-
- private static final class MagazineHolder {
- private final WeakReference<ClosurePool> poolref;
- private final Magazine magazine;
-
- public MagazineHolder(ClosurePool pool, Magazine magazine) {
- this.poolref = new WeakReference<ClosurePool>(pool);
- this.magazine = magazine;
- }
-
-
- @Override
- protected void finalize() throws Throwable {
- try {
- ClosurePool pool = poolref.get();
- if (pool != null) {
- pool.recycle(magazine);
- }
- } finally {
- super.finalize();
- }
- }
- }
-
- /**
- * This is a proxy passed to the native code, to be called by the
- * native trampoline code.
- */
- static final class Proxy {
- static final Method METHOD = getMethod();
- /**
- * Keep references to the return and parameter types so they do not get
- * garbage collected until the closure does.
- */
- final CallContext callContext;
-
- volatile Closure closure;
-
- /**
- * Gets the
- * @return
- */
- private static final Method getMethod() {
- try {
- return Proxy.class.getDeclaredMethod("invoke", new Class[]{long.class, long.class});
- } catch (Throwable ex) {
- throw new RuntimeException(ex);
- }
- }
-
- Proxy(CallContext callContext) {
- this.closure = NULL_CLOSURE;
- this.callContext = callContext;
- }
-
- /**
- * Invoked by the native closure trampoline to execute the java side of
- * the closure.
- *
- * @param retvalAddress The address of the native return value buffer
- * @param paramAddress The address of the native parameter buffer.
- */
- void invoke(long retvalAddress, long paramAddress) {
- closure.invoke(new DirectClosureBuffer(callContext, retvalAddress, paramAddress));
- }
- }
- private static final Closure NULL_CLOSURE = new Closure() {
-
- public void invoke(Buffer buffer) {
- }
- };
-}
diff --git a/src/com/kenai/jffi/DirectClosureBuffer.java b/src/com/kenai/jffi/DirectClosureBuffer.java
deleted file mode 100644
index 4c13527..0000000
--- a/src/com/kenai/jffi/DirectClosureBuffer.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package com.kenai.jffi;
-
-/**
- * Implementation of the {@link Closure.Buffer} interface to read/write
- * parameter and return value data in native memory
- */
-final class DirectClosureBuffer implements Closure.Buffer {
-
- private static final MemoryIO IO = MemoryIO.getInstance();
- private static final long ADDRESS_MASK = Platform.getPlatform().addressMask();
- private static final NativeWordIO WordIO = NativeWordIO.getInstance();
- private static final int PARAM_SIZE = Platform.getPlatform().addressSize() / 8;
- private final long retval;
- private final long parameters;
- /* Keep references to the return and parameter types to prevent garbage collection */
- private final CallContext callContext;
-
- public DirectClosureBuffer(CallContext callContext, long retval, long parameters) {
- super();
- this.callContext = callContext;
- this.retval = retval;
- this.parameters = parameters;
- }
-
- public final byte getByte(int index) {
- return IO.getByte(IO.getAddress(parameters + (index * PARAM_SIZE)));
- }
-
- public final short getShort(int index) {
- return IO.getShort(IO.getAddress(parameters + (index * PARAM_SIZE)));
- }
-
- public final int getInt(int index) {
- return IO.getInt(IO.getAddress(parameters + (index * PARAM_SIZE)));
- }
-
- public final long getLong(int index) {
- return IO.getLong(IO.getAddress(parameters + (index * PARAM_SIZE)));
- }
-
- public final float getFloat(int index) {
- return IO.getFloat(IO.getAddress(parameters + (index * PARAM_SIZE)));
- }
-
- public final double getDouble(int index) {
- return IO.getDouble(IO.getAddress(parameters + (index * PARAM_SIZE)));
- }
-
- public final long getAddress(int index) {
- return IO.getAddress(IO.getAddress(parameters + (index * PARAM_SIZE))) & ADDRESS_MASK;
- }
-
- public final long getStruct(int index) {
- return IO.getAddress(parameters + (index * PARAM_SIZE));
- }
-
- public final void setByteReturn(byte value) {
- WordIO.put(retval, value);
- }
-
- public final void setShortReturn(short value) {
- WordIO.put(retval, value);
- }
-
- public final void setIntReturn(int value) {
- WordIO.put(retval, value);
- }
-
- public final void setLongReturn(long value) {
- IO.putLong(retval, value);
- }
-
- public final void setFloatReturn(float value) {
- IO.putFloat(retval, value);
- }
-
- public final void setDoubleReturn(double value) {
- IO.putDouble(retval, value);
- }
-
- public final void setAddressReturn(long address) {
- IO.putAddress(retval, address);
- }
-
- public void setStructReturn(long value) {
- IO.copyMemory(value, retval, callContext.getReturnType().size());
- }
-
- public void setStructReturn(byte[] data, int offset) {
- IO.putByteArray(retval, data, offset, callContext.getReturnType().size());
- }
-
- /**
- * Reads annd writes data types that are smaller than the size of a native
- * long, as a native long for compatibility with FFI.
- */
- private static abstract class NativeWordIO {
- public static final NativeWordIO getInstance() {
- return Platform.getPlatform().addressSize() == 32
- ? NativeWordIO32.INSTANCE : NativeWordIO64.INSTANCE;
- }
-
- /**
- * Writes a native long argument to native memory.
- *
- * @param address The address to write the value at
- * @param value The value to write.
- */
- abstract void put(long address, int value);
-
- /**
- * Reads a native long argument from native memory.
- * @param address The memory address to read the value from
- * @return An integer
- */
- abstract int get(long address);
- }
-
- private static final class NativeWordIO32 extends NativeWordIO {
- private static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance();
- static final NativeWordIO INSTANCE = new NativeWordIO32();
-
- void put(long address, int value) {
- IO.putInt(address, value);
- }
-
- int get(long address) {
- return IO.getInt(address);
- }
- }
-
- private static final class NativeWordIO64 extends NativeWordIO {
-
- private static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance();
- static final NativeWordIO INSTANCE = new NativeWordIO64();
-
- void put(long address, int value) {
- IO.putLong(address, value);
- }
-
- int get(long address) {
- return (int) IO.getLong(address);
- }
- }
-}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/jffi-next.git
More information about the pkg-java-commits
mailing list