Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* JCuda - Java bindings for NVIDIA CUDA driver and runtime API
*
* Copyright (c) 2009-2015 Marco Hutter - http://www.jcuda.org
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef POINTERUTILS
#define POINTERUTILS
#include "JNIUtils.hpp"
class PointerData;
PointerData* initPointerData(JNIEnv *env, jobject nativePointerObject);
bool releasePointerData(JNIEnv *env, PointerData* &pointerData, jint mode=0);
void setNativePointerValue(JNIEnv *env, jobject nativePointerObject, jlong pointer);
void* getNativePointerValue(JNIEnv *env, jobject nativePointerObject);
void setPointer(JNIEnv *env, jobject pointerObject, jlong pointer);
void* getPointer(JNIEnv *env, jobject pointerObject);
bool isDirectByteBuffer(JNIEnv *env, jobject object);
bool isPointerBackedByNativeMemory(JNIEnv *env, jobject object);
int initPointerUtils(JNIEnv *env);
extern jmethodID Buffer_isDirect; // ()Z
extern jmethodID Buffer_hasArray; // ()Z
extern jmethodID Buffer_array; // ()Ljava/lang/Object;
extern jfieldID NativePointerObject_nativePointer; // long
extern jclass Pointer_class;
extern jfieldID Pointer_buffer; // Ljava.nio.Buffer;
extern jfieldID Pointer_pointers; // [jcuda.Pointer;
extern jfieldID Pointer_byteOffset; // long
extern jmethodID Object_getClass; // ()Ljava/lang/Class;
extern jmethodID Class_getComponentType; // ()Ljava/lang/Class;
extern jmethodID Class_newInstance; // ()Ljava/lang/Object;
/**
* Virtual base class for all possible representations of pointers.
*/
class PointerData
{
public:
virtual ~PointerData() {}
/**
* Initialize this PointerData with the given object
*/
virtual bool init(JNIEnv *env, jobject object) = 0;
/**
* Release this PointerData. To be called immediately
* before the destructor call.
*/
virtual bool release(JNIEnv *env, jint mode=0) = 0;
/**
* Returns the actual pointer represented by this PointerData
*/
virtual void* getPointer(JNIEnv *env) = 0;
/**
* Releases the actual pointer. This should be called as soon
* as possible after the pointer obtained with 'getPointer'
* is no longer used, but it can be assumed that it is
* called in the 'release' method, if necessary.
*/
virtual void releasePointer(JNIEnv *env, jint mode=0) = 0;
/**
* When this pointer is an element of an array of pointers
* that is pointed to by another pointer, then the contents
* of this array may be modified by a CUDA function or
* kernel. In this case, the updated native pointer value
* will have to be written back into the Java NativePointerObject.
* This will only work for the NativePointerData and
* NativePointerObjectPointerData implementation. The method
* returns whether the update succeeded. Otherwise, an
* IllegalArgumentException will be thrown.
*/
virtual bool setNewNativePointerValue(JNIEnv *env, jlong nativePointerValue) = 0;
};
// TODO The PointerData handling should be cleaned up:
// - Consider allowing setNewNativePointerValue to be called
// on ALL implementations. Primarily, the array/buffer
// references that are stored in the PointerData object
// have to be cleared for that when the method is called,
// but this has to be considered in the 'release' method
// - Consider creating Pointer instances when the
// PointersArrayPointerData is released and points
// to an array containing 'null' entries, but is
// about to commit non-NULL local pointer values
/**
* A PointerData that is backed by a Java NativePointerObject
* (specifically, one that is not a Java Pointer). It only
* stores the nativePointer value from the Java object.
*/
class NativePointerObjectPointerData : public PointerData
{
private:
/** The global reference to the Java NativePointerObject */
jobject nativePointerObject;
/** The nativePointer value from the Java NativePointerObject */
jlong nativePointer;
public:
NativePointerObjectPointerData()
{
nativePointerObject = NULL;
nativePointer = 0;
}
~NativePointerObjectPointerData()
{
}
bool init(JNIEnv *env, jobject object)
{
if (object != NULL)
{
// Create a global reference to the given object
nativePointerObject = env->NewGlobalRef(object);
if (nativePointerObject == NULL)
{
ThrowByName(env, "java/lang/OutOfMemoryError",
"Out of memory while creating global reference for pointer data");
return false;
}
// Obtain the nativePointer value
nativePointer = env->GetLongField(object, NativePointerObject_nativePointer);
if (env->ExceptionCheck())
{
return false;
}
}
Logger::log(LOG_DEBUGTRACE, "Initialized NativePointerObjectPointerData %p\n", nativePointer);
return true;
}
bool release(JNIEnv *env, jint mode=0)
{
Logger::log(LOG_DEBUGTRACE, "Releasing NativePointerObjectPointerData %p\n", nativePointer);
if (nativePointerObject != NULL)
{
env->SetLongField(nativePointerObject, NativePointerObject_nativePointer, nativePointer);
env->DeleteGlobalRef(nativePointerObject);
}
return true;
}
void* getPointer(JNIEnv *env)
{
return (void*)nativePointer;
}
void releasePointer(JNIEnv *env, jint mode=0)
{
}
bool setNewNativePointerValue(JNIEnv *env, jlong nativePointerValue)
{
nativePointer = nativePointerValue;
return true;
}
};
/**
* A PointerData that is backed by a Java Pointer. It stores the
* nativePointer value from the NativePointerObject class, and
* the byteOffset from the Pointer class.
*/
class NativePointerData : public PointerData
{
private:
/** The global reference to the Java Pointer */
jobject pointer;
/** The nativePointer value from the Java NativePointerObject */
jlong nativePointer;
/** The byteOffset from the Java Pointer */
jlong byteOffset;
public:
NativePointerData()
{
nativePointer = 0;
byteOffset = 0;
}
~NativePointerData()
{
}
bool init(JNIEnv *env, jobject object)
{
// Create a global reference to the given object
pointer = env->NewGlobalRef(object);
if (pointer == NULL)
{
ThrowByName(env, "java/lang/OutOfMemoryError",
"Out of memory while creating global reference for pointer data");
return false;
}
// Obtain the nativePointer value
nativePointer = env->GetLongField(object, NativePointerObject_nativePointer);
if (env->ExceptionCheck())
{
return false;
}
// Obtain the byteOffset
byteOffset = env->GetLongField(object, Pointer_byteOffset);
if (env->ExceptionCheck())
{
return false;
}
Logger::log(LOG_DEBUGTRACE, "Initialized NativePointerData %p\n", nativePointer);
return true;
}
bool release(JNIEnv *env, jint mode=0)
{
Logger::log(LOG_DEBUGTRACE, "Releasing NativePointerData %p\n", nativePointer);
env->SetLongField(pointer, NativePointerObject_nativePointer, nativePointer);
env->SetLongField(pointer, Pointer_byteOffset, byteOffset);
env->DeleteGlobalRef(pointer);
return true;
}
void* getPointer(JNIEnv *env)
{
return (void*)(((char*)nativePointer)+byteOffset);
}
void releasePointer(JNIEnv *env, jint mode=0)
{
}
bool setNewNativePointerValue(JNIEnv *env, jlong nativePointerValue)
{
nativePointer = nativePointerValue;
byteOffset = 0;
return true;
}
};
/**
* A PointerData for a Java Pointer that points to an array
* of NativePointerObjects. Internally it maintains an array
* if PointerData objects, one for each NativePointerObject
* of the array in the Java Pointer.
*/
class PointersArrayPointerData : public PointerData
{
private:
/** The global reference to the Java NativePointerObject */
jobject nativePointerObject;
/**
* The array of PointerDatas, one for each of the Java
* NativePointerObjects from the array inside the Java
* Pointer
*/
PointerData **arrayPointerDatas;
/**
* A pointer to a memory region that contains the
* actual Pointer values from the NativePointerObjects
*/
void *startPointer;
/** The byteOffset from the Java Pointer */
jlong byteOffset;
/**
* Whether the pointers that the startPointer points
* to have already been initialized - that is,
* assigned the values from the respective
* arrayPointerDatas[i]->getPointer(env) call
*/
bool localPointersInitialized;
public:
PointersArrayPointerData()
{
arrayPointerDatas = NULL;
startPointer = NULL;
byteOffset = 0;
localPointersInitialized = false;
}
~PointersArrayPointerData()
{
}
void initLocalPointers(JNIEnv *env)
{
Logger::log(LOG_DEBUGTRACE, "Initializing PointersArrayPointerData local pointers\n");
jobjectArray pointersArray = (jobjectArray)env->GetObjectField(
nativePointerObject, Pointer_pointers);
long size = (long)env->GetArrayLength(pointersArray);
void **localPointer = (void**)startPointer;
for (int i=0; igetPointer(env);
}
else
{
localPointer[i] = NULL;
}
}
localPointersInitialized = true;
Logger::log(LOG_DEBUGTRACE, "Initialized PointersArrayPointerData local pointers\n");
}
bool init(JNIEnv *env, jobject object)
{
// Create a global reference to the given object
nativePointerObject = env->NewGlobalRef(object);
if (nativePointerObject == NULL)
{
ThrowByName(env, "java/lang/OutOfMemoryError",
"Out of memory while creating global reference for pointer data");
return false;
}
jobjectArray pointersArray = (jobjectArray)env->GetObjectField(
object, Pointer_pointers);
long size = (long)env->GetArrayLength(pointersArray);
// Prepare the pointer that points to the pointer
// values of the NativePointerObjects
void **localPointer = new void*[size];
if (localPointer == NULL)
{
ThrowByName(env, "java/lang/OutOfMemoryError",
"Out of memory while initializing pointer array");
return false;
}
startPointer = (void*)localPointer;
// Prepare the PointerData objects for the Java NativePointerObjects
arrayPointerDatas = new PointerData*[size];
if (arrayPointerDatas == NULL)
{
ThrowByName(env, "java/lang/OutOfMemoryError",
"Out of memory while initializing pointer data array");
return false;
}
// Initialize the PointerDatas and the pointer values
// from the NativePointerObjects in the Java Pointer.
for (int i=0; iGetObjectArrayElement(pointersArray, i);
if (env->ExceptionCheck())
{
return false;
}
if (p != NULL)
{
// Initialize a PointerData for the pointer object that
// the pointer points to
PointerData *arrayPointerData = initPointerData(env, p);
if (arrayPointerData == NULL)
{
return false;
}
arrayPointerDatas[i] = arrayPointerData;
}
else
{
arrayPointerDatas[i] = NULL;
}
}
// Obtain the byteOffset
byteOffset = env->GetLongField(object, Pointer_byteOffset);
if (env->ExceptionCheck())
{
return false;
}
Logger::log(LOG_DEBUGTRACE, "Initialized PointersArrayPointerData %p\n", startPointer);
return true;
}
bool release(JNIEnv *env, jint mode=0)
{
Logger::log(LOG_DEBUGTRACE, "Releasing PointersArrayPointerData %p\n", startPointer);
if (!localPointersInitialized)
{
initLocalPointers(env);
}
jobjectArray pointersArray = (jobjectArray)env->GetObjectField(
nativePointerObject, Pointer_pointers);
long size = (long)env->GetArrayLength(pointersArray);
void **localPointer = (void**)startPointer;
if (mode != JNI_ABORT)
{
// Write back the values from the native pointers array
// into the Java objects
for (int i=0; iGetObjectArrayElement(pointersArray, i);
if (env->ExceptionCheck())
{
return false;
}
if (p != NULL)
{
// Check whether the value inside the pointer array has changed.
void *oldLocalPointer = arrayPointerDatas[i]->getPointer(env);
Logger::log(LOG_DEBUGTRACE, "About to write back pointer %d in PointersArrayPointerData\n", i);
Logger::log(LOG_DEBUGTRACE, "Old local pointer was %p\n", oldLocalPointer);
Logger::log(LOG_DEBUGTRACE, "New local pointer is %p\n", localPointer[i]);
if (localPointer[i] != oldLocalPointer)
{
Logger::log(LOG_DEBUGTRACE, "In pointer %d setting value %p\n", i, localPointer[i]);
bool pointerUpdated = arrayPointerDatas[i]->setNewNativePointerValue(env, (jlong)localPointer[i]);
if (!pointerUpdated)
{
// If the pointer value could not be updated,
// (see setNewNativePointerValue documentation)
// then there is a pending IllegalArgumentException
return false;
}
}
}
else if (localPointer[i] != NULL)
{
// TODO: In future versions, it might be necessary to instantiate
// a pointer object here
ThrowByName(env, "java/lang/NullPointerException",
"Pointer points to an array containing a 'null' entry");
return false;
}
}
}
// Release the PointerDatas for the pointer objects that
// the pointer points to
if (arrayPointerDatas != NULL)
{
for (int i=0; iDeleteGlobalRef(nativePointerObject);
return true;
}
void* getPointer(JNIEnv *env)
{
if (!localPointersInitialized)
{
initLocalPointers(env);
}
return (void*)(((char*)startPointer)+byteOffset);
}
void releasePointer(JNIEnv *env, jint mode=0)
{
}
bool setNewNativePointerValue(JNIEnv *env, jlong nativePointerValue)
{
ThrowByName(env, "java/lang/IllegalArgumentException",
"Pointer to an array of pointers may not be overwritten");
return false;
}
};
/**
* A PointerData that is backed by a direct Java Buffer
*/
class DirectBufferPointerData : public PointerData
{
private:
/** The address obtained from the direct buffer */
void *startPointer;
/** The byteOffset from the Java Pointer */
jlong byteOffset;
public:
DirectBufferPointerData()
{
startPointer = NULL;
byteOffset = 0;
}
~DirectBufferPointerData()
{
}
bool init(JNIEnv *env, jobject object)
{
// Obtain the direct buffer address from the given buffer
jobject buffer = env->GetObjectField(object, Pointer_buffer);
startPointer = env->GetDirectBufferAddress(buffer);
if (startPointer == 0)
{
ThrowByName(env, "java/lang/IllegalArgumentException",
"Failed to obtain direct buffer address");
return false;
}
// Obtain the byteOffset
byteOffset = env->GetLongField(object, Pointer_byteOffset);
if (env->ExceptionCheck())
{
return false;
}
Logger::log(LOG_DEBUGTRACE, "Initialized DirectBufferPointerData %p\n", startPointer);
return true;
}
bool release(JNIEnv *env, jint mode=0)
{
Logger::log(LOG_DEBUGTRACE, "Releasing DirectBufferPointerData %p\n", startPointer);
return true;
}
void* getPointer(JNIEnv *env)
{
return (void*)(((char*)startPointer)+byteOffset);
}
void releasePointer(JNIEnv *env, jint mode=0)
{
}
bool setNewNativePointerValue(JNIEnv *env, jlong nativePointerValue)
{
ThrowByName(env, "java/lang/IllegalArgumentException",
"Pointer to a direct buffer may not be overwritten");
return false;
}
};
/**
* A PointerData that points to a Java Array
*/
class ArrayBufferPointerData : public PointerData
{
private:
/** A global reference to the Java array */
jarray array;
/** The address obtained from the Java array in 'getPointer' */
void *startPointer;
/** Whether the array was copied (and not pinned) */
jboolean isCopy;
/** The byteOffset from the Java Pointer */
jlong byteOffset;
public:
ArrayBufferPointerData()
{
startPointer = NULL;
array = NULL;
byteOffset = 0;
isCopy = JNI_FALSE;
}
~ArrayBufferPointerData()
{
}
bool init(JNIEnv *env, jobject object)
{
// Obtain the array reference
jobject buffer = env->GetObjectField(object, Pointer_buffer);
jobject localArray = env->CallObjectMethod(buffer, Buffer_array);
if (env->ExceptionCheck())
{
return false;
}
array = (jarray)env->NewGlobalRef(localArray);
if (array == NULL)
{
ThrowByName(env, "java/lang/OutOfMemoryError",
"Out of memory while creating array reference");
return false;
}
// Obtain the byteOffset
byteOffset = env->GetLongField(object, Pointer_byteOffset);
if (env->ExceptionCheck())
{
return false;
}
Logger::log(LOG_DEBUGTRACE, "Initialized ArrayBufferPointerData %p (initialization is deferred)\n", startPointer);
return true;
}
bool release(JNIEnv *env, jint mode=0)
{
Logger::log(LOG_DEBUGTRACE, "Releasing ArrayBufferPointerData %p\n", startPointer);
releasePointer(env, mode);
env->DeleteGlobalRef(array);
return true;
}
void* getPointer(JNIEnv *env)
{
if (startPointer == NULL)
{
Logger::log(LOG_DEBUGTRACE, "Initializing ArrayBufferPointerData critical\n");
isCopy = JNI_FALSE;
startPointer = env->GetPrimitiveArrayCritical(array, &isCopy);
if (startPointer == NULL)
{
return NULL;
}
Logger::log(LOG_DEBUGTRACE, "Initialized ArrayBufferPointerData %p (finished initialization, isCopy %d)\n", startPointer, isCopy);
}
return (void*)(((char*)startPointer)+byteOffset);
}
void releasePointer(JNIEnv *env, jint mode=0)
{
if (startPointer != NULL)
{
Logger::log(LOG_DEBUGTRACE, "Releasing ArrayBufferPointerData critical\n");
if (!isCopy)
{
env->ReleasePrimitiveArrayCritical(array, startPointer, JNI_ABORT);
}
else
{
env->ReleasePrimitiveArrayCritical(array, startPointer, mode);
}
startPointer = NULL;
}
}
bool setNewNativePointerValue(JNIEnv *env, jlong nativePointerValue)
{
ThrowByName(env, "java/lang/IllegalArgumentException",
"Pointer to an array may not be overwritten");
return false;
}
};
#endif