summaryrefslogtreecommitdiff
path: root/demos
diff options
context:
space:
mode:
authorEthan Vrhel <ethanvrhel@gmail.com>2021-10-30 14:26:24 -0700
committerEthan Vrhel <ethanvrhel@gmail.com>2021-10-30 14:26:24 -0700
commitee0bbe7e6314c08ff14b60fbf23816da81167318 (patch)
treefa531fb8e05eec0d18b249a1d79b729ed8bda5c2 /demos
parent9f68f20f94c252c99b497599e9320c52c0cc5d4c (diff)
downloadghostpdl-ee0bbe7e6314c08ff14b60fbf23816da81167318.tar.gz
Fixed multi threading issues in gs_jni
Diffstat (limited to 'demos')
-rw-r--r--demos/java/jni/gs_jni/callbacks.cpp163
-rw-r--r--demos/java/jni/gs_jni/callbacks.h12
-rw-r--r--demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp97
-rw-r--r--demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.h2
-rw-r--r--demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.h2
-rw-r--r--demos/java/jni/gs_jni/gs_jni.vcxproj1
-rw-r--r--demos/java/jni/gs_jni/gs_jni.vcxproj.filters3
-rw-r--r--demos/java/jni/gs_jni/instance_data.cpp62
-rw-r--r--demos/java/jni/gs_jni/instance_data.h6
-rw-r--r--demos/java/jni/gs_jni/jni_util.cpp4
-rw-r--r--demos/java/jni/gs_jni/jni_util.h4
-rw-r--r--demos/java/mtdemo/Main.java10
-rw-r--r--demos/java/mtdemo/README.txt32
-rw-r--r--demos/java/mtdemo/Worker.java16
-rw-r--r--demos/java/mtdemo/runmtd.bat3
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, &copy);
- 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, &copy);
- 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, &copy);
- 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, &copy);
- 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, &copy);
- 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