[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