Author: mturk Date: Fri Apr 24 10:04:31 2009 New Revision: 768243 URL: http://svn.apache.org/viewvc?rev=768243&view=rev Log: Add new allocate method for DBB
Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/DirectByteBuffer.java commons/sandbox/runtime/trunk/src/main/native/shared/dbb.c commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestDirectByteBuffer.java Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/DirectByteBuffer.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/DirectByteBuffer.java?rev=768243&r1=768242&r2=768243&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/DirectByteBuffer.java (original) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/DirectByteBuffer.java Fri Apr 24 10:04:31 2009 @@ -60,6 +60,11 @@ private static native ByteBuffer alloc5(Pointer ptr) throws NullPointerException; + private static native ByteBuffer[] alloc6(Pointer ptr, long[] sizes, + int off, int len) + throws OutOfMemoryError, IllegalArgumentException, + IndexOutOfBoundsException; + private static native ByteBuffer attach(long mem, long offset, long size) throws NullPointerException, IllegalArgumentException; @@ -137,6 +142,73 @@ } /** + * Allocate a new ByteBuffer array from memory contained by {...@code ptr}. + * <p> + * Memory is internally aligned to 8 byte boundary + * meaning that there might be unused chunks of memory if + * the requested sizes are not aligned to a specified boundary. + * </p> + * <p> + * For example if two ByteBuffers are allocated with sizes + * {...@code 2} and {...@code 3} the overall allocated + * memory will be {...@code 16} bytes because each requested + * size is aligned to 8 byte boundary. + * </p> + * + * @param ptr {...@link Pointer} taht holds the native memory area. + * @param sizes Array of lengths for each ByteBuffer. + * @param off Start offset of the {...@code sizes} array. + * @param len The length of the {...@code sizes} array to use. + * @return The ByteBuffer array with allocated memory + * + * @throws OutOfMemoryError if memory cannot be allocated from the system. + * @throws IllegalArgumentException if {...@code off} or {...@code len} + * is invalid. + * @throws IndexOutOfBoundsException if copying would cause access of + * data outside array bounds. + */ + public static ByteBuffer[] allocate(Pointer ptr, long sizes[], int off, int len) + throws NullPointerException, IllegalArgumentException, + IndexOutOfBoundsException + { + return alloc6(ptr, sizes, off, len); + } + + /** + * Allocate a new ByteBuffer array from memory contained by {...@code ptr}. + * <p> + * Memory is internally aligned to 8 byte boundary + * meaning that there might be unused chunks of memory if + * the requested sizes are not aligned to a specified boundary. + * </p> + * <p> + * This method does the same as calling the: + * <pre> + * + * DirectByteBuffer.allocate(ptr, sizes, 0, sizes.length); + * + * </pre> + * + * @param ptr {...@link Pointer} taht holds the native memory area. + * @param sizes Array of lengths for each ByteBuffer. + * @param off Start offset of the {...@code sizes} array. + * @param len The length of the {...@code sizes} array to use. + * @return The ByteBuffer array with allocated memory + * + * @throws OutOfMemoryError if memory cannot be allocated from the system. + * @throws IllegalArgumentException if {...@code off} or {...@code len} + * is invalid. + * @throws IndexOutOfBoundsException if copying would cause access of + * data outside array bounds. + */ + public static ByteBuffer[] allocate(Pointer ptr, long sizes[]) + throws NullPointerException, IllegalArgumentException, + IndexOutOfBoundsException + { + return alloc6(ptr, sizes, 0, sizes.length); + } + + /** * Allocate a new ByteBuffer array from memory. * </p> * <b>Warning:</b><br/> Modified: commons/sandbox/runtime/trunk/src/main/native/shared/dbb.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/dbb.c?rev=768243&r1=768242&r2=768243&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/shared/dbb.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/shared/dbb.c Fri Apr 24 10:04:31 2009 @@ -284,6 +284,94 @@ return (*_E)->NewDirectByteBuffer(_E, sp, sl); } +ACR_JNI_EXPORT_DECLARE(jobject, DirectByteBuffer, alloc6)(ACR_JNISTDARGS, + jobject ptr, + jlongArray sizes, + jint off, jint len) +{ + jint i; + jlong *ia; + jsize is; + size_t sl; + size_t sz = 0; + jobjectArray rv = NULL; + char *sp = (char *)ACR_PointerGet(_E, ptr, &sl); + + UNREFERENCED_O; + + if (len < 1 || off < 0) { + ACR_ThrowException(_E, THROW_FMARK, ACR_EX_EINVAL, + ACR_EINVALSIZ); + return NULL; + } + if ((is = (*_E)->GetArrayLength(_E, sizes)) < 1) { + /* At least one element is needed */ + ACR_ThrowException(_E, THROW_FMARK, ACR_EX_EINVAL, + ACR_EINVALSIZ); + return NULL; + } + if ((jsize)(off + len) > is) { + ACR_ThrowException(_E, THROW_FMARK, ACR_EX_EINDEX, 0); + return NULL; + } + + if (!(ia = (*_E)->GetLongArrayElements(_E, sizes, NULL))) { + ACR_ThrowException(_E, THROW_FMARK, ACR_EX_EINVAL, + ACR_EISNULL); + return NULL; + } + if (!(rv = ACR_NewCoreObjectArray(_E, ACR_CC_DBBUFF, (jsize)len))) { + /* Failed creating ByteBuffer[] array */ + goto cleanup; + } + for (i = 0; i < len; i++) { + /* calculate overall size using the default alignment */ + sz += ACR_ALIGN_DEFAULT((size_t)ia[i + off]); + } + if (sp == NULL) { + if (!(sp = malloc(sz))) { + ACR_ThrowException(_E, THROW_FMARK, ACR_EX_ENOMEM, + ACR_GET_OS_ERROR()); + rv = NULL; + goto cleanup; + } + ACR_PointerSet(_E, ptr, sp, sz); + sl = sz; + } + if (sz <= sl) { + size_t offset = 0; + for (i = 0; i < len; i++) { + size_t n = ACR_ALIGN_DEFAULT((size_t)ia[i + off]); + jobject bb = (*_E)->NewDirectByteBuffer(_E, sp + offset, + ia[i + off]); + if (bb == NULL) { + /* One of the constructors failed. + * The entire ByteBuffer[] array is invalid. + */ + rv = NULL; + goto cleanup; + } + (*_E)->SetObjectArrayElement(_E, rv, (jsize)i, bb); + if ((*_E)->ExceptionCheck(_E)) { + /* One of the setters failed. + * The entire ByteBuffer[] array is invalid. + */ + rv = NULL; + goto cleanup; + } + offset += n; + } + } + else { + ACR_ThrowException(_E, THROW_FMARK, ACR_EX_EINDEX, 0); + rv = NULL; + } + +cleanup: + (*_E)->ReleaseLongArrayElements(_E, sizes, ia, JNI_ABORT); + return rv; +} + ACR_JNI_EXPORT_DECLARE(jobject, DirectByteBuffer, attach)(ACR_JNISTDARGS, jlong addr, jlong offset, Modified: commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestDirectByteBuffer.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestDirectByteBuffer.java?rev=768243&r1=768242&r2=768243&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestDirectByteBuffer.java (original) +++ commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestDirectByteBuffer.java Fri Apr 24 10:04:31 2009 @@ -209,5 +209,47 @@ } + public void testArrayCreatePtr() + throws Throwable + { + long [] sizes = { 100, 10, 100, 1000 }; + // Aligned size + // 100->104 + 1000->1000 = 1104 + Pointer mem = Memory.malloc(1104); + ByteBuffer[] a = DirectByteBuffer.allocate(mem, sizes, 2, 2); + assertNotNull("Array", a); + + for (int i = 0; i < 2; i++) { + assertEquals("Capacity" + i, sizes[i+2], a[i].capacity()); + } + + /* WARNING: Do not free any Buffer. + * Use Pointer.free() + */ + mem.free(); + + } + + public void testArrayCreateNull() + throws Throwable + { + long [] sizes = { 100, 10, 100, 1000 }; + Pointer mem = Memory.malloc(); + ByteBuffer[] a = DirectByteBuffer.allocate(mem, sizes, 2, 2); + assertNotNull("Array", a); + + for (int i = 0; i < 2; i++) { + assertEquals("Capacity" + i, sizes[i+2], a[i].capacity()); + } + // Aligned size + // 100->104 + 1000->1000 = 1104 + assertEquals("Size", 1104, mem.size().intValue()); + /* WARNING: Do not free any Buffer. + * Use Pointer.free() + */ + mem.free(); + + } + }