diff options
author | Sven Gothel <[email protected]> | 2011-04-27 19:47:43 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2011-04-27 19:47:43 +0200 |
commit | 8f8aa3f73e3c9804c4a86f5d4fdac257d50d831a (patch) | |
tree | 87497a9ffd60f4d3c2be2535312a72f84087a23d /src/java/com/jogamp/common/nio/PointerBuffer.java | |
parent | a07892f07f15c96ca248fc12133748be7058241f (diff) |
NativeBuffer/PointerBuffer API/Impl Change (remove explicit backup array, alloc referenced data map if used only)
This patch doesn't impact GlueGen's code generation,
but enhance and fix PointerBuffer usage only.
remove explicit backup array
As suggested by Michael Bien with a proposed patch,
PointerBuffer's backup array is not only redundant in case it's not used,
but also erroneous - due to possible sliced buffers.
Removes the explicit backup array implementation
leaving it up to the user, ie how PointerBuffer is created (alloc/allocDirect)
and use the underlying nio's buffer backup array, if available.
This also fixes the (never tested) case of indirect w/ backup array usage
on 32bit platform size. In this case the array shall be of type int[],
holding 32bit pointer - on 64bit long[].
Previous to this patch, it was always long[].
Added more thorough tests of PointerBuffer, notably indirect w/ backup array
and native deep copy and filling of a pointer array.
alloc referenced data map if used only
As suggested by Michael Bien with a proposed patch,
the allocation of the dataMap hash map is redundant in case it's not used.
The hash map will be initialized lazy, if needed only.
Diffstat (limited to 'src/java/com/jogamp/common/nio/PointerBuffer.java')
-rw-r--r-- | src/java/com/jogamp/common/nio/PointerBuffer.java | 190 |
1 files changed, 151 insertions, 39 deletions
diff --git a/src/java/com/jogamp/common/nio/PointerBuffer.java b/src/java/com/jogamp/common/nio/PointerBuffer.java index 5f866e1..69f8bbd 100644 --- a/src/java/com/jogamp/common/nio/PointerBuffer.java +++ b/src/java/com/jogamp/common/nio/PointerBuffer.java @@ -31,10 +31,14 @@ */ package com.jogamp.common.nio; -import com.jogamp.common.os.*; -import java.nio.ByteBuffer; import java.nio.Buffer; -import java.util.HashMap; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.nio.LongBuffer; + +import com.jogamp.common.os.NativeLibrary; +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.LongObjectHashMap; /** * Hardware independent container for native pointer arrays. @@ -42,78 +46,184 @@ import java.util.HashMap; * The native values (NIO direct ByteBuffer) might be 32bit or 64bit wide, * depending of the CPU pointer width. * - * @author Michael Bien * @author Sven Gothel + * @author Michael Bien */ -public abstract class PointerBuffer extends AbstractLongBuffer<PointerBuffer> { - - protected HashMap<Long, Buffer> dataMap = new HashMap<Long, Buffer>(); +public class PointerBuffer extends AbstractBuffer<PointerBuffer> { + public static final int ELEMENT_SIZE = Platform.is32Bit() ? Buffers.SIZEOF_INT : Buffers.SIZEOF_LONG ; + protected LongObjectHashMap dataMap = null; static { NativeLibrary.ensureNativeLibLoaded(); } - protected PointerBuffer(ByteBuffer bb) { - super(bb, elementSize()); + /** no backup array, use for direct usage only */ + PointerBuffer(ByteBuffer bb) { + super(Platform.is32Bit() ? bb.asIntBuffer() : bb.asLongBuffer(), ELEMENT_SIZE); + } + + /** supports backup array */ + PointerBuffer(IntBuffer b) { + super(b, ELEMENT_SIZE); + } + + /** supports backup array */ + PointerBuffer(LongBuffer b) { + super(b, ELEMENT_SIZE); + } + + private final void validateDataMap() { + if(null == dataMap) { + dataMap = new LongObjectHashMap(); + dataMap.setKeyNotFoundValue(null); + } } + /** Returns a non direct PointerBuffer in native order, having a backup array */ public static PointerBuffer allocate(int size) { - return new PointerBufferSE(ByteBuffer.wrap(new byte[elementSize() * size])); + if (Platform.is32Bit()) { + return new PointerBuffer(IntBuffer.wrap(new int[size])); + } else { + return new PointerBuffer(LongBuffer.wrap(new long[size])); + } } + /** Returns a direct PointerBuffer in native order, w/o backup array */ public static PointerBuffer allocateDirect(int size) { - return new PointerBufferSE(Buffers.newDirectByteBuffer(elementSize() * size)); + return new PointerBuffer(Buffers.newDirectByteBuffer(ELEMENT_SIZE * size)); } public static PointerBuffer wrap(ByteBuffer src) { - PointerBuffer res = new PointerBufferSE(src); - res.updateBackup(); - return res; + return new PointerBuffer(src); + } + /** + * Relative bulk get method. Copy the source values <code> src[position .. capacity] [</code> + * to this buffer and increment the position by <code>capacity-position</code>. */ + public final PointerBuffer put(PointerBuffer src) { + if (remaining() < src.remaining()) { + throw new IndexOutOfBoundsException(); + } + if( null == src.dataMap && null == dataMap ) { + // fast path no dataMap usage on both + while (src.hasRemaining()) { + put(src.get()); + } + } else { + while (src.hasRemaining()) { + final long addr = src.get(); + put(addr); + if( null != src.dataMap) { + Buffer bb = (Buffer) src.dataMap.get(addr); + if(null!=bb) { + validateDataMap(); + dataMap.put(addr, bb); + } else if( null != dataMap ) { + dataMap.remove(addr); + } + } else if( null != dataMap ) { + dataMap.remove(addr); + } + } + } + return this; + } + + /** Relative get method. Get the pointer value at the current position and increment the position by one. */ + public final long get() { + long r = get(position); + position++; + return r; } - public static int elementSize() { - return Platform.is32Bit() ? Buffers.SIZEOF_INT : Buffers.SIZEOF_LONG; + /** Absolute get method. Get the pointer value at the given index */ + public final long get(int idx) { + if (0 > idx || idx >= capacity) { + throw new IndexOutOfBoundsException(); + } + if (Platform.is32Bit()) { + return (long) ((IntBuffer) buffer).get(idx) & 0x00000000FFFFFFFFL; + } else { + return ((LongBuffer) buffer).get(idx); + } + } + + /** + * Relative bulk get method. Copy the pointer values <code> [ position .. position+length [</code> + * to the destination array <code> [ dest[offset] .. dest[offset+length] [ </code> + * and increment the position by <code>length</code>. */ + public final PointerBuffer get(long[] dest, int offset, int length) { + if (dest.length<offset+length) { + throw new IndexOutOfBoundsException(); + } + if (remaining() < length) { + throw new IndexOutOfBoundsException(); + } + while(length>0) { + dest[offset++] = get(position++); + length--; + } + return this; } - @Override - public final PointerBuffer put(PointerBuffer src) { - if (remaining() < src.remaining()) { + /** Absolute put method. Put the pointer value at the given index */ + public final PointerBuffer put(int idx, long v) { + if (0 > idx || idx >= capacity) { throw new IndexOutOfBoundsException(); } - long addr; - while (src.hasRemaining()) { - addr = src.get(); - put(addr); - Long addrL = new Long(addr); - Buffer bb = (Buffer) dataMap.get(addrL); - if(null!=bb) { - dataMap.put(addrL, bb); - } else { - dataMap.remove(addrL); - } + if (Platform.is32Bit()) { + ((IntBuffer) buffer).put(idx, (int) v); + } else { + ((LongBuffer) buffer).put(idx, v); + } + return this; + } + + /** Relative put method. Put the pointer value at the current position and increment the position by one. */ + public final PointerBuffer put(long value) { + put(position, value); + position++; + return this; + } + + /** + * Relative bulk put method. Put the pointer values <code> [ src[offset] .. src[offset+length] [</code> + * at the current position and increment the position by <code>length</code>. */ + public final PointerBuffer put(long[] src, int offset, int length) { + if (src.length<offset+length) { + throw new IndexOutOfBoundsException(); + } + if (remaining() < length) { + throw new IndexOutOfBoundsException(); + } + while(length>0) { + put(position++, src[offset++]); + length--; } return this; } /** Put the address of the given direct Buffer at the given position of this pointer array. - Adding a reference of the given direct Buffer to this object. */ + Adding a reference of the given direct Buffer to this object. + + @throws IllegalArgumentException if bb is null or not a direct buffer + */ public final PointerBuffer referenceBuffer(int index, Buffer bb) { if(null==bb) { - throw new RuntimeException("Buffer is null"); + throw new IllegalArgumentException("Buffer is null"); } if(!Buffers.isDirect(bb)) { - throw new RuntimeException("Buffer is not direct"); + throw new IllegalArgumentException("Buffer is not direct"); } long mask = Platform.is32Bit() ? 0x00000000FFFFFFFFL : 0xFFFFFFFFFFFFFFFFL ; long bbAddr = getDirectBufferAddressImpl(bb) & mask; if(0==bbAddr) { throw new RuntimeException("Couldn't determine native address of given Buffer: "+bb); } - - put(index, bbAddr); - dataMap.put(new Long(bbAddr), bb); + validateDataMap(); + put(index, bbAddr); + dataMap.put(bbAddr, bb); return this; } @@ -127,8 +237,11 @@ public abstract class PointerBuffer extends AbstractLongBuffer<PointerBuffer> { } public final Buffer getReferencedBuffer(int index) { - long addr = get(index); - return dataMap.get(new Long(addr)); + if(null != dataMap) { + long addr = get(index); + return (Buffer) dataMap.get(addr); + } + return null; } public final Buffer getReferencedBuffer() { @@ -143,5 +256,4 @@ public abstract class PointerBuffer extends AbstractLongBuffer<PointerBuffer> { public String toString() { return "PointerBuffer:"+super.toString(); } - } |