diff options
author | Ethan Vrhel <ethanvrhel@gmail.com> | 2021-10-30 14:26:24 -0700 |
---|---|---|
committer | Ethan Vrhel <ethanvrhel@gmail.com> | 2021-10-30 14:26:24 -0700 |
commit | ee0bbe7e6314c08ff14b60fbf23816da81167318 (patch) | |
tree | fa531fb8e05eec0d18b249a1d79b729ed8bda5c2 /demos | |
parent | 9f68f20f94c252c99b497599e9320c52c0cc5d4c (diff) | |
download | ghostpdl-ee0bbe7e6314c08ff14b60fbf23816da81167318.tar.gz |
Fixed multi threading issues in gs_jni
Diffstat (limited to 'demos')
-rw-r--r-- | demos/java/jni/gs_jni/callbacks.cpp | 163 | ||||
-rw-r--r-- | demos/java/jni/gs_jni/callbacks.h | 12 | ||||
-rw-r--r-- | demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp | 97 | ||||
-rw-r--r-- | demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.h | 2 | ||||
-rw-r--r-- | demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.h | 2 | ||||
-rw-r--r-- | demos/java/jni/gs_jni/gs_jni.vcxproj | 1 | ||||
-rw-r--r-- | demos/java/jni/gs_jni/gs_jni.vcxproj.filters | 3 | ||||
-rw-r--r-- | demos/java/jni/gs_jni/instance_data.cpp | 62 | ||||
-rw-r--r-- | demos/java/jni/gs_jni/instance_data.h | 6 | ||||
-rw-r--r-- | demos/java/jni/gs_jni/jni_util.cpp | 4 | ||||
-rw-r--r-- | demos/java/jni/gs_jni/jni_util.h | 4 | ||||
-rw-r--r-- | demos/java/mtdemo/Main.java | 10 | ||||
-rw-r--r-- | demos/java/mtdemo/README.txt | 32 | ||||
-rw-r--r-- | demos/java/mtdemo/Worker.java | 16 | ||||
-rw-r--r-- | demos/java/mtdemo/runmtd.bat | 3 |
15 files changed, 240 insertions, 177 deletions
diff --git a/demos/java/jni/gs_jni/callbacks.cpp b/demos/java/jni/gs_jni/callbacks.cpp index 8d9ab2122..646219330 100644 --- a/demos/java/jni/gs_jni/callbacks.cpp +++ b/demos/java/jni/gs_jni/callbacks.cpp @@ -34,95 +34,92 @@ Lcom/artifex/gsjava/IntReference;)I" using namespace util; -void callbacks::setJNIEnv(void *instance, JNIEnv *env) +void callbacks::setJNIEnv(GSInstanceData *idata, JNIEnv *env) { - GSInstanceData *gsdata = findDataFromInstance(instance); - assert(gsdata); - - gsdata->env = env; + idata->env = env; } -void callbacks::setIOCallbacks(void *instance, jobject stdIn, jobject stdOut, jobject stdErr) +void callbacks::setIOCallbacks(GSInstanceData *idata, jobject stdIn, jobject stdOut, jobject stdErr) { - GSInstanceData *gsdata = findDataFromInstance(instance); - assert(gsdata); - - if (gsdata->env) + if (idata->env) { - if (gsdata->stdIn) - gsdata->env->DeleteGlobalRef(gsdata->stdIn); + if (idata->stdIn) + idata->env->DeleteGlobalRef(idata->stdIn); - if (gsdata->stdOut) - gsdata->env->DeleteGlobalRef(gsdata->stdOut); + if (idata->stdOut) + idata->env->DeleteGlobalRef(idata->stdOut); - if (gsdata->stdErr) - gsdata->env->DeleteGlobalRef(gsdata->stdErr); + if (idata->stdErr) + idata->env->DeleteGlobalRef(idata->stdErr); - gsdata->stdIn = gsdata->env->NewGlobalRef(stdIn); - gsdata->stdOut = gsdata->env->NewGlobalRef(stdOut); - gsdata->stdErr = gsdata->env->NewGlobalRef(stdErr); + idata->stdIn = idata->env->NewGlobalRef(stdIn); + idata->stdOut = idata->env->NewGlobalRef(stdOut); + idata->stdErr = idata->env->NewGlobalRef(stdErr); } } int callbacks::stdInFunction(void *callerHandle, char *buf, int len) { - int code = 0; - - GSInstanceData *gsdata = findDataFromHandle(callerHandle); + GSInstanceData *gsdata = (GSInstanceData *)callerHandle; assert(gsdata); - if (gsdata->env && gsdata->stdIn) - { - jbyteArray byteArray = gsdata->env->NewByteArray(len); - gsdata->env->SetByteArrayRegion(byteArray, 0, len, (jbyte *)buf); - code = callIntMethod(gsdata->env, gsdata->stdIn, "onStdIn", STDIN_SIG, (jlong)gsdata->stdioHandle, byteArray, (jint)len); - } - return code; + if (!gsdata->env || !gsdata->stdErr) return 0; + + jbyteArray byteArray = gsdata->env->NewByteArray(len); + gsdata->env->SetByteArrayRegion(byteArray, 0, len, (jbyte *)buf); + + jint result = callIntMethod(gsdata->env, gsdata->stdIn, "onStdIn", STDIN_SIG, (jlong)gsdata->stdioHandle, byteArray, (jint)len); + if (gsdata->env->ExceptionCheck()) return 0; + + jboolean isCopy = JNI_FALSE; + jbyte *arr = gsdata->env->GetByteArrayElements(byteArray, &isCopy); + + jsize copySize = result < len ? result : len; + memcpy(buf, arr, copySize); + + return copySize; } int callbacks::stdOutFunction(void *callerHandle, const char *str, int len) { - int code = 0; - - GSInstanceData *gsdata = findDataFromHandle(callerHandle); + GSInstanceData *gsdata = (GSInstanceData *)callerHandle; assert(gsdata); - if (gsdata->env && gsdata->stdOut) - { - jbyteArray byteArray = gsdata->env->NewByteArray(len); - gsdata->env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)str); - code = callIntMethod(gsdata->env, gsdata->stdOut, "onStdOut", STDOUT_SIG, (jlong)gsdata->stdioHandle, byteArray, (jint)len); - } - return code; + if (!gsdata->env || !gsdata->stdOut) return len; + + jbyteArray byteArray = gsdata->env->NewByteArray(len); + gsdata->env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)str); + + jint result = callIntMethod(gsdata->env, gsdata->stdOut, "onStdOut", STDOUT_SIG, (jlong)gsdata->stdioHandle, byteArray, (jint)len); + if (gsdata->env->ExceptionCheck()) return 0; + + return result; } int callbacks::stdErrFunction(void *callerHandle, const char *str, int len) { - int code = 0; - - GSInstanceData *gsdata = findDataFromHandle(callerHandle); + GSInstanceData *gsdata = (GSInstanceData *)callerHandle; assert(gsdata); - if (gsdata->env && gsdata->stdErr) - { - jbyteArray byteArray = gsdata->env->NewByteArray(len); - gsdata->env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)str); - code = callIntMethod(gsdata->env, gsdata->stdErr, "onStdErr", STDERR_SIG, (jlong)gsdata->stdioHandle, byteArray, (jint)len); - } - return code; + if (!gsdata->env || !gsdata->stdErr) return len; + + jbyteArray byteArray = gsdata->env->NewByteArray(len); + gsdata->env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)str); + + jint result = callIntMethod(gsdata->env, gsdata->stdErr, "onStdErr", STDERR_SIG, (jlong)gsdata->stdioHandle, byteArray, (jint)len); + if (gsdata->env->ExceptionCheck()) return 0; + + return result; } -void callbacks::setPollCallback(void *instance, jobject poll) +void callbacks::setPollCallback(GSInstanceData *idata, jobject poll) { - GSInstanceData *gsdata = findDataFromInstance(instance); - assert(gsdata); - - if (gsdata->env) + if (idata->env) { - if (gsdata->poll) - gsdata->env->DeleteGlobalRef(gsdata->poll); + if (idata->poll) + idata->env->DeleteGlobalRef(idata->poll); - gsdata->poll = gsdata->env->NewGlobalRef(poll); + idata->poll = idata->env->NewGlobalRef(poll); } } @@ -130,7 +127,7 @@ int callbacks::pollFunction(void *callerHandle) { int code = 0; - GSInstanceData *gsdata = findDataFromHandle(callerHandle); + GSInstanceData *gsdata = (GSInstanceData *)callerHandle; assert(gsdata); if (gsdata->env && gsdata->poll) @@ -140,35 +137,29 @@ int callbacks::pollFunction(void *callerHandle) return code; } -void callbacks::setDisplayCallback(void *instance, jobject displayCallback) +void callbacks::setDisplayCallback(GSInstanceData *idata, jobject displayCallback) { - GSInstanceData *gsdata = findDataFromInstance(instance); - assert(gsdata); - - if (gsdata->env) + if (idata->env) { - if (gsdata->displayCallback) + if (idata->displayCallback) { - gsdata->env->DeleteGlobalRef(gsdata->displayCallback); - gsdata->displayCallback = NULL; + idata->env->DeleteGlobalRef(idata->displayCallback); + idata->displayCallback = NULL; } - gsdata->displayCallback = gsdata->env->NewGlobalRef(displayCallback); + idata->displayCallback = idata->env->NewGlobalRef(displayCallback); //g_displayCallback = displayCallback; } } -void callbacks::setCalloutCallback(void *instance, jobject callout) +void callbacks::setCalloutCallback(GSInstanceData *idata, jobject callout) { - GSInstanceData *gsdata = findDataFromInstance(instance); - assert(gsdata); - - if (gsdata->env) + if (idata->env) { - if (gsdata->callout) - gsdata->env->DeleteGlobalRef(gsdata->callout); + if (idata->callout) + idata->env->DeleteGlobalRef(idata->callout); - gsdata->callout = gsdata->env->NewGlobalRef(callout); + idata->callout = idata->env->NewGlobalRef(callout); } } @@ -193,7 +184,7 @@ int callbacks::display::displayOpenFunction(void *handle, void *device) { int code = 0; - GSInstanceData *gsdata = findDataFromHandle(handle); + GSInstanceData *gsdata = (GSInstanceData *)handle; assert(gsdata); if (gsdata->env && gsdata->displayCallback) @@ -211,7 +202,7 @@ int callbacks::display::displayPrecloseFunction(void *handle, void *device) { int code = 0; - GSInstanceData *gsdata = findDataFromHandle(handle); + GSInstanceData *gsdata = (GSInstanceData *)handle; assert(gsdata); if (gsdata->env && gsdata->displayCallback) @@ -226,7 +217,7 @@ int callbacks::display::displayCloseFunction(void *handle, void *device) { int code = 0; - GSInstanceData *gsdata = findDataFromHandle(handle); + GSInstanceData *gsdata = (GSInstanceData *)handle; assert(gsdata); if (gsdata->env && gsdata->displayCallback) @@ -241,7 +232,7 @@ int callbacks::display::displayPresizeFunction(void *handle, void *device, int w { int code = 0; - GSInstanceData *gsdata = findDataFromHandle(handle); + GSInstanceData *gsdata = (GSInstanceData *)handle; assert(gsdata); if (gsdata->env && gsdata->displayCallback) @@ -258,7 +249,7 @@ int callbacks::display::displaySizeFunction(void *handle, void *device, int widt { int code = 0; - GSInstanceData *gsdata = findDataFromHandle(handle); + GSInstanceData *gsdata = (GSInstanceData *)handle; assert(gsdata); if (gsdata->env && gsdata->displayCallback) @@ -320,7 +311,7 @@ int callbacks::display::displaySyncFunction(void *handle, void *device) { int code = 0; - GSInstanceData *gsdata = findDataFromHandle(handle); + GSInstanceData *gsdata = (GSInstanceData *)handle; assert(gsdata); if (gsdata->env && gsdata->displayCallback) @@ -335,7 +326,7 @@ int callbacks::display::displayPageFunction(void *handle, void *device, int copi { int code = 0; - GSInstanceData *gsdata = findDataFromHandle(handle); + GSInstanceData *gsdata = (GSInstanceData *)handle; assert(gsdata); if (gsdata->env && gsdata->displayCallback) @@ -351,7 +342,7 @@ int callbacks::display::displayUpdateFunction(void *handle, void *device, int x, { int code = 0; - GSInstanceData *gsdata = findDataFromHandle(handle); + GSInstanceData *gsdata = (GSInstanceData *)handle; assert(gsdata); if (gsdata->env && gsdata->displayCallback) @@ -368,7 +359,7 @@ int callbacks::display::displaySeparationFunction(void *handle, void *device, in { int code = 0; - GSInstanceData *gsdata = findDataFromHandle(handle); + GSInstanceData *gsdata = (GSInstanceData *)handle; assert(gsdata); if (gsdata->env && gsdata->displayCallback) @@ -387,7 +378,7 @@ int callbacks::display::displayAdjustBandHeightFunction(void *handle, void *devi { int code = 0; - GSInstanceData *gsdata = findDataFromHandle(handle); + GSInstanceData *gsdata = (GSInstanceData *)handle; assert(gsdata); if (gsdata->env && gsdata->displayCallback) @@ -404,7 +395,7 @@ int callbacks::display::displayRectangleRequestFunction(void *handle, void *devi { int code = 0; - GSInstanceData *gsdata = findDataFromHandle(handle); + GSInstanceData *gsdata = (GSInstanceData *)handle; assert(gsdata); if (gsdata->env && gsdata->displayCallback) diff --git a/demos/java/jni/gs_jni/callbacks.h b/demos/java/jni/gs_jni/callbacks.h index f2a6bc75a..e8a23f938 100644 --- a/demos/java/jni/gs_jni/callbacks.h +++ b/demos/java/jni/gs_jni/callbacks.h @@ -2,6 +2,8 @@ #include <jni.h> +#include "instance_data.h" + namespace callbacks { /*! @@ -10,17 +12,17 @@ namespace callbacks @param env A JNIEnv. */ - void setJNIEnv(void *instance, JNIEnv *env); + void setJNIEnv(GSInstanceData *idata, JNIEnv *env); - void setIOCallbacks(void *instance, jobject stdIn, jobject stdOut, jobject stdErr); + void setIOCallbacks(GSInstanceData *idata, jobject stdIn, jobject stdOut, jobject stdErr); int stdInFunction(void *callerHandle, char *buf, int len); int stdOutFunction(void *callerHandle, const char *str, int len); int stdErrFunction(void *callerHandle, const char *str, int len); - void setPollCallback(void *instance, jobject poll); + void setPollCallback(GSInstanceData *idata, jobject poll); int pollFunction(void *callerHandle); - void setDisplayCallback(void *instance, jobject displayCallback); + void setDisplayCallback(GSInstanceData *idata, jobject displayCallback); namespace display { @@ -49,6 +51,6 @@ namespace callbacks int *x, int *y, int *w, int *h); } - void setCalloutCallback(void *instance, jobject calout); + void setCalloutCallback(GSInstanceData *idata, jobject callout); int calloutFunction(void *instance, void *handle, const char *deviceName, int id, int size, void *data); }
\ No newline at end of file diff --git a/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp b/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp index 9830a00c7..b67c3ecb7 100644 --- a/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp +++ b/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp @@ -55,7 +55,10 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1new_1instance JNIEXPORT void JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1delete_1instance (JNIEnv *env, jclass, jlong instance) { - callbacks::setJNIEnv((void *)instance, env); + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + + callbacks::setJNIEnv(idata, env); gsapi_delete_instance((void *)instance); deleteDataFromInstance((void *)instance); @@ -73,8 +76,8 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1stdio_1with_1ha callbacks::stdOutFunction, callbacks::stdErrFunction, idata); if (code == 0) { - callbacks::setJNIEnv((void *)instance, env); - callbacks::setIOCallbacks((void *)instance, stdIn, stdOut, stdErr); + callbacks::setJNIEnv(idata, env); + callbacks::setIOCallbacks(idata, stdIn, stdOut, stdErr); } return code; } @@ -91,8 +94,8 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1stdio callbacks::stdOutFunction, callbacks::stdErrFunction, idata); if (code == 0) { - callbacks::setJNIEnv((void *)instance, env); - callbacks::setIOCallbacks((void *)instance, stdIn, stdOut, stdErr); + callbacks::setJNIEnv(idata, env); + callbacks::setIOCallbacks(idata, stdIn, stdOut, stdErr); } return code; } @@ -100,11 +103,14 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1stdio JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1poll_1with_1handle (JNIEnv *env, jclass, jlong instance, jobject poll, jlong callerHandle) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + int code = gsapi_set_poll_with_handle((void *)instance, callbacks::pollFunction, (void *)callerHandle); if (code == 0) { - callbacks::setJNIEnv((void *)instance, env); - callbacks::setPollCallback((void *)instance, poll); + callbacks::setJNIEnv(idata, env); + callbacks::setPollCallback(idata, poll); } return code; } @@ -112,11 +118,14 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1poll_1with_1han JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1poll (JNIEnv *env, jclass, jlong instance, jobject poll) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + int code = gsapi_set_poll((void *)instance, callbacks::pollFunction); if (code == 0) { - callbacks::setJNIEnv((void *)instance, env); - callbacks::setPollCallback((void *)instance, poll); + callbacks::setJNIEnv(idata, env); + callbacks::setPollCallback(idata, poll); } return code; } @@ -124,6 +133,9 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1poll JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1display_1callback (JNIEnv *env, jclass, jlong instance, jobject displayCallback) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + display_callback *cb = new display_callback; cb->size = sizeof(display_callback); cb->version_major = DISPLAY_VERSION_MAJOR; @@ -146,8 +158,8 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1display_1callba int code = gsapi_set_display_callback((void *)instance, cb); if (code == 0) { - callbacks::setJNIEnv((void *)instance, env); - callbacks::setDisplayCallback((void *)instance, displayCallback); + callbacks::setJNIEnv(idata, env); + callbacks::setDisplayCallback(idata, displayCallback); } return code; } @@ -155,11 +167,14 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1display_1callba JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1register_1callout (JNIEnv *env, jclass, jlong instance, jobject callout, jlong calloutHandle) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + int code = gsapi_register_callout((void *)instance, callbacks::calloutFunction, (void *)calloutHandle); if (code == 0) { - callbacks::setJNIEnv((void *)instance, env); - callbacks::setCalloutCallback((void *)instance, callout); + callbacks::setJNIEnv(idata, env); + callbacks::setCalloutCallback(idata, callout); } return code; } @@ -179,10 +194,14 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1arg_1encoding JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1default_1device_1list (JNIEnv *env, jclass, jlong instance, jbyteArray list, jint listlen) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + if (list == NULL) return throwNullPointerException(env, "list"); + jboolean isCopy = false; - callbacks::setJNIEnv((void *)instance, env); + callbacks::setJNIEnv(idata, env); int code = gsapi_set_default_device_list((void *)instance, (const char *)env->GetByteArrayElements(list, &isCopy), listlen); return code; @@ -212,10 +231,14 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1get_1default_1device JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1init_1with_1args (JNIEnv *env, jclass, jlong instance, jint argc, jobjectArray argv) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + if (argv == NULL) return throwNullPointerException(env, "argv"); + char **cargv = jbyteArray2DToCharArray(env, argv); - callbacks::setJNIEnv((void *)instance, env); + callbacks::setJNIEnv(idata, env); int code = gsapi_init_with_args((void *)instance, argc, cargv); delete2DByteArray(argc, cargv); return code; @@ -224,8 +247,11 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1init_1with_1args JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1begin (JNIEnv *env, jclass, jlong instance, jint userErrors, jobject pExitCode) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + int exitCode; - callbacks::setJNIEnv((void *)instance, env); + callbacks::setJNIEnv(idata, env); int code = gsapi_run_string_begin((void *)instance, userErrors, &exitCode); if (pExitCode) Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode)); @@ -235,12 +261,16 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1begin JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1continue (JNIEnv *env, jclass, jlong instance, jbyteArray str, jint length, jint userErrors, jobject pExitCode) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + if (str == NULL) return throwNullPointerException(env, "str"); + jboolean copy = false; int exitCode; const char *cstring = (const char *)env->GetByteArrayElements(str, ©); - callbacks::setJNIEnv((void *)instance, env); + callbacks::setJNIEnv(idata, env); int code = gsapi_run_string_continue((void *)instance, cstring, length, userErrors, &exitCode); if (pExitCode) Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode)); @@ -250,8 +280,11 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1continu JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1end (JNIEnv *env, jclass, jlong instance, jint userErrors, jobject pExitCode) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + int exitCode; - callbacks::setJNIEnv((void *)instance, env); + callbacks::setJNIEnv(idata, env); int code = gsapi_run_string_end((void *)instance, userErrors, &exitCode); if (pExitCode) Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode)); @@ -261,12 +294,16 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1end JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1with_1length (JNIEnv *env, jclass, jlong instance, jbyteArray str, jint length, jint userErrors, jobject pExitCode) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + if (str == NULL) return throwNullPointerException(env, "str"); + jboolean copy = false; int exitCode; const char *cstring = (const char *)env->GetByteArrayElements(str, ©); - callbacks::setJNIEnv((void *)instance, env); + callbacks::setJNIEnv(idata, env); int code = gsapi_run_string_with_length((void *)instance, cstring, length, userErrors, &exitCode); if (pExitCode) Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode)); @@ -276,12 +313,16 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1with_1l JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string (JNIEnv *env, jclass, jlong instance, jbyteArray str, jint userErrors, jobject pExitCode) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + if (str == NULL) return throwNullPointerException(env, "str"); + jboolean copy = false; int exitCode; const char *cstring = (const char *)env->GetByteArrayElements(str, ©); - callbacks::setJNIEnv((void *)instance, env); + callbacks::setJNIEnv(idata, env); int code = gsapi_run_string((void *)instance, cstring, userErrors, &exitCode); if (pExitCode) Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode)); @@ -291,12 +332,16 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1file (JNIEnv *env, jclass, jlong instance, jbyteArray fileName, jint userErrors, jobject pExitCode) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + if (fileName == NULL) return throwNullPointerException(env, "fileName"); + jboolean copy = false; int exitCode; const char *cstring = (const char *)env->GetByteArrayElements(fileName, ©); - callbacks::setJNIEnv((void *)instance, env); + callbacks::setJNIEnv(idata, env); int code = gsapi_run_file((void *)instance, cstring, userErrors, &exitCode); if (pExitCode) Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode)); @@ -312,11 +357,11 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1exit JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1param (JNIEnv *env, jclass, jlong instance, jbyteArray param, jobject value, jint paramType) { + GSInstanceData *idata = findDataFromInstance((void *)instance); + assert(idata); + if (!param) - { - throwNullPointerException(env, "param"); - return -1; - } + return throwNullPointerException(env, "param"); gs_set_param_type type = (gs_set_param_type)paramType; bool paramSuccess; @@ -330,7 +375,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1param jboolean copy = false; const char *cstring = (const char *)env->GetByteArrayElements(param, ©); - callbacks::setJNIEnv((void *)instance, env); + callbacks::setJNIEnv(idata, env); int code = gsapi_set_param((void *)instance, cstring, data, type); free(data); diff --git a/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.h b/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.h index 68c61e581..fd7e303aa 100644 --- a/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.h +++ b/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.h @@ -2,6 +2,8 @@ #include <jni.h> /* Header for class com_artifex_gsjava_GSAPI */ +#include "settings.h" + #ifndef _Included_com_artifex_gsjava_GSAPI #define _Included_com_artifex_gsjava_GSAPI #ifdef __cplusplus diff --git a/demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.h b/demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.h index 8dd6a30b2..6c053df8d 100644 --- a/demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.h +++ b/demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.h @@ -2,6 +2,8 @@ #include <jni.h> /* Header for class com_artifex_gsjava_util_NativePointer */ +#include "settings.h" + #ifndef _Included_com_artifex_gsjava_util_NativePointer #define _Included_com_artifex_gsjava_util_NativePointer #ifdef __cplusplus diff --git a/demos/java/jni/gs_jni/gs_jni.vcxproj b/demos/java/jni/gs_jni/gs_jni.vcxproj index 201a59966..56f03d0ab 100644 --- a/demos/java/jni/gs_jni/gs_jni.vcxproj +++ b/demos/java/jni/gs_jni/gs_jni.vcxproj @@ -172,6 +172,7 @@ <ClInclude Include="framework.h" /> <ClInclude Include="instance_data.h" /> <ClInclude Include="jni_util.h" /> + <ClInclude Include="settings.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="callbacks.cpp" /> diff --git a/demos/java/jni/gs_jni/gs_jni.vcxproj.filters b/demos/java/jni/gs_jni/gs_jni.vcxproj.filters index c69db33f9..ce1781b7a 100644 --- a/demos/java/jni/gs_jni/gs_jni.vcxproj.filters +++ b/demos/java/jni/gs_jni/gs_jni.vcxproj.filters @@ -33,6 +33,9 @@ <ClInclude Include="instance_data.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="settings.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="dllmain.cpp"> diff --git a/demos/java/jni/gs_jni/instance_data.cpp b/demos/java/jni/gs_jni/instance_data.cpp index 7543afdc6..8c9d1a05f 100644 --- a/demos/java/jni/gs_jni/instance_data.cpp +++ b/demos/java/jni/gs_jni/instance_data.cpp @@ -1,25 +1,30 @@ #include "instance_data.h" #include <unordered_map> - #include <assert.h> - -static GSInstanceData g_global; // Global instance for faster multithreading +#include <mutex> #if defined(ALLOW_MT) static std::unordered_map<void *, GSInstanceData *> g_inst2Data; // instance -> data -static std::unordered_map<void *, GSInstanceData *> g_hand2Data; // caller handle -> data +static std::mutex g_mtx; + +#else + +static GSInstanceData g_global; // Global instance for faster multithreading #endif GSInstanceData *putInstanceData(GSInstanceData *data) { #if defined(ALLOW_MT) - assert(g_inst2Data.find(data->instance) == g_inst2Data.end() && g_hand2Data.find(data->callerHandle) == g_hand2Data.end()); + g_mtx.lock(); + + assert(g_inst2Data.find(data->instance) == g_inst2Data.end()); g_inst2Data[data->instance] = data; - g_hand2Data[data->callerHandle] = data; + + g_mtx.unlock(); return data; @@ -32,18 +37,14 @@ GSInstanceData *putInstanceData(GSInstanceData *data) GSInstanceData *findDataFromInstance(void *instance) { #if defined(ALLOW_MT) + g_mtx.lock(); + auto it = g_inst2Data.find(instance); - return it == g_inst2Data.end() ? NULL : it->second; -#else - return &g_global; -#endif -} + GSInstanceData *result = it == g_inst2Data.end() ? NULL : it->second; -GSInstanceData *findDataFromHandle(void *callerHandle) -{ -#if defined(ALLOW_MT) - auto it = g_hand2Data.find(callerHandle); - return it == g_hand2Data.end() ? NULL : it->second; + g_mtx.unlock(); + + return result; #else return &g_global; #endif @@ -52,33 +53,12 @@ GSInstanceData *findDataFromHandle(void *callerHandle) void deleteDataFromInstance(void *instance) { #if defined(ALLOW_MT) + g_mtx.lock(); + auto i2dit = g_inst2Data.find(instance); if (i2dit != g_inst2Data.end()) - { - GSInstanceData *idata = i2dit->second; - auto h2dit = g_hand2Data.find(idata->callerHandle); - - assert(h2dit != g_hand2Data.end()); - g_inst2Data.erase(i2dit); - g_hand2Data.erase(h2dit); - } -#endif -} - -void deleteDataFromHandle(void *callerHandle) -{ -#if defined(ALLOW_MT) - auto h2dit = g_hand2Data.find(callerHandle); - if (h2dit != g_hand2Data.end()) - { - GSInstanceData *idata = h2dit->second; - auto i2dit = g_inst2Data.find(idata->instance); - - assert(i2dit != g_inst2Data.end()); - g_hand2Data.erase(i2dit); - g_inst2Data.erase(h2dit); - } + g_mtx.unlock(); #endif -} +}
\ No newline at end of file diff --git a/demos/java/jni/gs_jni/instance_data.h b/demos/java/jni/gs_jni/instance_data.h index 4274dbe24..22770daf4 100644 --- a/demos/java/jni/gs_jni/instance_data.h +++ b/demos/java/jni/gs_jni/instance_data.h @@ -2,6 +2,8 @@ #include <jni.h> +#include "settings.h" + class GSInstanceData { public: @@ -24,6 +26,4 @@ public: GSInstanceData *putInstanceData(GSInstanceData *data); GSInstanceData *findDataFromInstance(void *instance); -GSInstanceData *findDataFromHandle(void *callerHandle); -void deleteDataFromInstance(void *instance); -void deleteDataFromHandle(void *callerHandle);
\ No newline at end of file +void deleteDataFromInstance(void *instance);
\ No newline at end of file diff --git a/demos/java/jni/gs_jni/jni_util.cpp b/demos/java/jni/gs_jni/jni_util.cpp index 74852a95e..dfb570a8b 100644 --- a/demos/java/jni/gs_jni/jni_util.cpp +++ b/demos/java/jni/gs_jni/jni_util.cpp @@ -145,14 +145,14 @@ jint util::getIntField(JNIEnv *env, jobject object, const char *field) return env->GetIntField(object, fieldID); } -int util::callIntMethod(JNIEnv *env, jobject object, const char *method, const char *sig, ...) +jint util::callIntMethod(JNIEnv *env, jobject object, const char *method, const char *sig, ...) { jmethodID methodID = getMethodID(env, object, method, sig); if (methodID == NULL) return 0; va_list args; - int result; + jint result; va_start(args, sig); result = env->CallIntMethodV(object, methodID, args); va_end(args); diff --git a/demos/java/jni/gs_jni/jni_util.h b/demos/java/jni/gs_jni/jni_util.h index 6439712e9..2ea20fd47 100644 --- a/demos/java/jni/gs_jni/jni_util.h +++ b/demos/java/jni/gs_jni/jni_util.h @@ -2,6 +2,8 @@ #include <jni.h> +#include "settings.h" + #define REFERENCE_VALUE_FILED_NAME "value" namespace util @@ -141,7 +143,7 @@ namespace util @param sig The method's signature. @param ... The varargs representing the object's arguments in their respective order. */ - int callIntMethod(JNIEnv *env, jobject object, const char *name, const char *sig, ...); + jint callIntMethod(JNIEnv *env, jobject object, const char *name, const char *sig, ...); void setObjectField(JNIEnv *env, jobject object, const char *field, jobject value); diff --git a/demos/java/mtdemo/Main.java b/demos/java/mtdemo/Main.java index cdc3c9a01..bd3ef2f54 100644 --- a/demos/java/mtdemo/Main.java +++ b/demos/java/mtdemo/Main.java @@ -1,9 +1,11 @@ import com.artifex.gsjava.GSInstance; -import java.util.Scanner; +import java.io.File; public class Main { + public static final String INFILE = "../../../examples/tiger.eps"; + public static void main(String[] args) { GSInstance.setAllowMultithreading(true); @@ -14,19 +16,15 @@ public class Main { } catch (NumberFormatException e) { } } - //Scanner in = new Scanner(System.in); - //in.nextLine(); - Worker[] workers = new Worker[workerCount]; for (int i = 0; i < workers.length; i++) { - workers[i] = new Worker("../../../examples/tiger.eps", "pdfout/out" + i + ".pdf"); + workers[i] = new Worker(INFILE, "pdfout/out" + i + ".pdf"); } System.out.println("Starting workers..."); for (int i = 0; i < workers.length; i++) { workers[i].start(); } - System.out.println("Workers dispatched"); } }
\ No newline at end of file diff --git a/demos/java/mtdemo/README.txt b/demos/java/mtdemo/README.txt new file mode 100644 index 000000000..661a10e66 --- /dev/null +++ b/demos/java/mtdemo/README.txt @@ -0,0 +1,32 @@ +This directory contains files which demo multithreading in Ghostscript +using the Java Language Bindings. The application here simply reads in +the same EPS file and outputs it to multiple PDF files on different +threads. + +What is here? + +* Main.java - Class containing Java main method +* Worker.java - Class which handles concurrently running Ghostscript +* build.bat - Builds the Java program + +Needed in this directory to run: + +* gpdldll64.dll (COMPILED FOR MULTITHREADING - use DGS_THREADSAFE) +* gs_jni.dll +* gsjava.jar + +How to run: + +Windows: + +The application can be started through the command line through the +command: + +java -cp gsjava.jar;. Main + +OR + +java -cp gsjava.jar;. Main [thread count] + +where [thread count] is the number of threads (and files) which will +be ran/written.
\ No newline at end of file diff --git a/demos/java/mtdemo/Worker.java b/demos/java/mtdemo/Worker.java index 2b7b960bd..3da333fd0 100644 --- a/demos/java/mtdemo/Worker.java +++ b/demos/java/mtdemo/Worker.java @@ -7,10 +7,13 @@ import com.artifex.gsjava.callbacks.*; import java.io.IOException; +import java.util.Arrays; + import static com.artifex.gsjava.GSAPI.*; public class Worker implements Runnable { + public static final boolean USE_CUSTOM_STDIO = true; public static final boolean USE_STDOUT = false; private static int ID = 0; @@ -45,20 +48,19 @@ public class Worker implements Runnable { try { gsInstance = createGSInstance(); - //StdIO io = new StdIO(); - //gsInstance.set_stdio(io, null, null); + if (USE_CUSTOM_STDIO) { + StdIO io = new StdIO(); + gsInstance.set_stdio(io, USE_STDOUT ? io : null, io); + } if (!outPDF.exists()) outPDF.createNewFile(); - final int FORMAT = GS_COLORS_RGB | GS_DISPLAY_DEPTH_8 | GS_DISPLAY_BIGENDIAN; String[] args = { "gs", "-sDEVICE=pdfwrite", - //"dFirstPage=1", - //"dDisplayFormat=" + FORMAT, - "-o", outPDF.getAbsolutePath(), - "-f", inPS.getAbsolutePath() + "-o", outPDF.getPath(), + inPS.getPath() }; int code = gsInstance.init_with_args(args); diff --git a/demos/java/mtdemo/runmtd.bat b/demos/java/mtdemo/runmtd.bat new file mode 100644 index 000000000..f23ce990d --- /dev/null +++ b/demos/java/mtdemo/runmtd.bat @@ -0,0 +1,3 @@ +@echo off + +java -cp gsjava.jar;. Main %1
\ No newline at end of file |