From b6d40b6e516b293855f5d616d8bad56e81240abd Mon Sep 17 00:00:00 2001 From: perry.werneck@gmail.com Date: Mon, 23 Jul 2012 12:54:29 +0000 Subject: [PATCH] Android: Serializando acesso à JNI --- android/jni/globals.h | 34 +++++++++++++++++++++------------- android/jni/main.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++++++++-------------------- android/jni/misc.cpp | 1 + android/jni/text.cpp | 4 ++-- android/src/br/com/bb/pw3270/lib3270.java | 1 + 5 files changed, 73 insertions(+), 35 deletions(-) diff --git a/android/jni/globals.h b/android/jni/globals.h index 9eb9722..c79d028 100644 --- a/android/jni/globals.h +++ b/android/jni/globals.h @@ -46,28 +46,36 @@ #define PW3270_JNI_END pw3270_env = NULL; pw3270_obj = NULL; */ - #define PW3270_JNI_BEGIN pw3270_env = env; pw3270_obj = obj; \ - __android_log_print(ANDROID_LOG_VERBOSE, PACKAGE_NAME, "%s.begin env=%p obj=%p",__FUNCTION__,env,obj); + #define PW3270_JNI_BEGIN __android_log_print(ANDROID_LOG_VERBOSE, PACKAGE_NAME, "%s.lock env=%p obj=%p",__FUNCTION__,env,obj); \ + pw3270_jni_lock(env,obj); - #define PW3270_JNI_END __android_log_print(ANDROID_LOG_VERBOSE, PACKAGE_NAME, "%s.end env=%p obj=%p",__FUNCTION__,pw3270_env,pw3270_obj); \ - pw3270_env = NULL; pw3270_obj = NULL; + #define PW3270_JNI_END __android_log_print(ANDROID_LOG_VERBOSE, PACKAGE_NAME, "%s.unlock env=%p obj=%p",__FUNCTION__,pw3270_jni_active->env,pw3270_jni_active->obj); \ + pw3270_jni_unlock(); - #define PW3270_JNI_ENV pw3270_env - #define PW3270_JNI_OBJ pw3270_obj + #define PW3270_JNI_ENV pw3270_jni_active->env + #define PW3270_JNI_OBJ pw3270_jni_active->obj #define PW3270_SESSION lib3270_get_default_session_handle() - #define pw3270_jni_call_void(name, sig, ...) pw3270_env->CallVoidMethod(pw3270_obj,lib3270_getmethodID(name,sig), __VA_ARGS__) - #define pw3270_jni_call_int(name, sig, ...) pw3270_env->CallIntMethod(pw3270_obj,lib3270_getmethodID(name,sig), __VA_ARGS__) - #define pw3270_jni_new_string(str) pw3270_env->NewStringUTF(str) - #define pw3270_jni_new_byte_array(len) pw3270_env->NewByteArray(len) + #define pw3270_jni_call_void(name, sig, ...) pw3270_jni_active->env->CallVoidMethod(pw3270_jni_active->obj,lib3270_getmethodID(name,sig), __VA_ARGS__) + #define pw3270_jni_call_int(name, sig, ...) pw3270_jni_active->env->CallIntMethod(pw3270_jni_active->obj,lib3270_getmethodID(name,sig), __VA_ARGS__) + #define pw3270_jni_new_string(str) pw3270_jni_active->env->NewStringUTF(str) + #define pw3270_jni_new_byte_array(len) pw3270_jni_active->env->NewByteArray(len) + + typedef struct _pw3270_jni + { + struct _pw3270_jni * parent; + JNIEnv * env; + jobject obj; + } PW3270_JNI; /*--[ Globals ]--------------------------------------------------------------------------------------*/ - extern JNIEnv * pw3270_env; - extern jobject pw3270_obj; + extern PW3270_JNI *pw3270_jni_active; - jmethodID lib3270_getmethodID(const char *name, const char *sig); + void pw3270_jni_lock(JNIEnv *env, jobject obj); + void pw3270_jni_unlock(); + jmethodID lib3270_getmethodID(const char *name, const char *sig); diff --git a/android/jni/main.cpp b/android/jni/main.cpp index 7773838..df23f69 100644 --- a/android/jni/main.cpp +++ b/android/jni/main.cpp @@ -28,6 +28,7 @@ #include "globals.h" #include + #include #include #include #include @@ -45,29 +46,28 @@ /*--[ Globals ]--------------------------------------------------------------------------------------*/ - const char * java_class_name = "br/com/bb/pw3270/lib3270"; - JNIEnv * pw3270_env = NULL; - jobject pw3270_obj = NULL; - + const char * java_class_name = "br/com/bb/pw3270/lib3270"; + PW3270_JNI * pw3270_jni_active = NULL; + static pthread_mutex_t mutex; /*--[ Implement ]------------------------------------------------------------------------------------*/ jmethodID lib3270_getmethodID(const char *name, const char *sig) { - if(!pw3270_env) + if(!pw3270_jni_active) { __android_log_print(ANDROID_LOG_ERROR, PACKAGE_NAME, "%s(%s,%s) called outside jni environment",__FUNCTION__,name,sig); return NULL; } - return pw3270_env->GetMethodID(pw3270_env->GetObjectClass(pw3270_obj), name, sig ); + return PW3270_JNI_ENV->GetMethodID(PW3270_JNI_ENV->GetObjectClass(PW3270_JNI_OBJ), name, sig ); } static void post_message(int msgid, int arg1 = 0, int arg2 = 0) { - trace("%s: pw3270_env=%p pw3270_obj=%p",__FUNCTION__,pw3270_env,pw3270_obj); + trace("%s: pw3270_env=%p pw3270_obj=%p",__FUNCTION__,PW3270_JNI_ENV,PW3270_JNI_OBJ); - if(pw3270_env) + if(pw3270_jni_active) pw3270_jni_call_void("postMessage", "(III)V",(jint) msgid, (jint) arg1, (jint) arg2); } @@ -135,7 +135,7 @@ static int write_buffer(H3270 *session, unsigned const char *buf, int len) { jbyteArray buffer = pw3270_jni_new_byte_array(len); - pw3270_env->SetByteArrayRegion(buffer, 0, len, (jbyte*) buf); + PW3270_JNI_ENV->SetByteArrayRegion(buffer, 0, len, (jbyte*) buf); rc = pw3270_jni_call_int("send_data", "([BI)I", buffer, (jint) len ); } @@ -259,6 +259,8 @@ JNIEXPORT jint JNICALL Java_br_com_bb_pw3270_lib3270_init(JNIEnv *env, jclass ob { H3270 * session = lib3270_session_new(""); + pthread_mutex_init(&mutex,NULL); + PW3270_JNI_BEGIN __android_log_print(ANDROID_LOG_DEBUG, PACKAGE_NAME, "Initializing session %p",session); @@ -280,18 +282,10 @@ JNIEXPORT jint JNICALL Java_br_com_bb_pw3270_lib3270_init(JNIEnv *env, jclass ob return 0; } -/* -JNIEXPORT jint JNICALL Java_br_com_bb_pw3270_lib3270_processEvents(JNIEnv *env, jobject obj) +JNIEXPORT jint JNICALL Java_br_com_bb_pw3270_lib3270_deinit(JNIEnv *env, jclass obj) { - PW3270_JNI_BEGIN - - lib3270_main_iterate(session,1); - - PW3270_JNI_END - - return 0; + pthread_mutex_destroy(&mutex); } -*/ JNIEXPORT jboolean JNICALL Java_br_com_bb_pw3270_lib3270_isConnected(JNIEnv *env, jobject obj) { @@ -354,8 +348,42 @@ JNIEXPORT void JNICALL Java_br_com_bb_pw3270_lib3270_procRecvdata(JNIEnv *env, j trace("Liberando %d bytes",(size_t) sz); - pw3270_env->ReleaseByteArrayElements(buffer, (signed char *) netrbuf, 0); + PW3270_JNI_ENV->ReleaseByteArrayElements(buffer, (signed char *) netrbuf, 0); PW3270_JNI_END } + +void pw3270_jni_lock(JNIEnv *env, jobject obj) +{ + PW3270_JNI *datablock = (PW3270_JNI *) lib3270_malloc(sizeof(PW3270_JNI)); + + datablock->parent = pw3270_jni_active; + datablock->env = env; + datablock->obj = obj; + + if(!pw3270_jni_active || pw3270_jni_active->env != env) + { + // Environment change, lock + trace("%s: Environment has changed",__FUNCTION__); + pthread_mutex_lock(&mutex); + } + + pw3270_jni_active = datablock; +} + +void pw3270_jni_unlock(void) +{ + PW3270_JNI *datablock = pw3270_jni_active; + pw3270_jni_active = datablock->parent; + + if(!pw3270_jni_active || pw3270_jni_active->env != datablock->env) + { + // Environment change, unlock + trace("%s: Environment has changed",__FUNCTION__); + pthread_mutex_unlock(&mutex); + } + + lib3270_free(datablock); +} + diff --git a/android/jni/misc.cpp b/android/jni/misc.cpp index 1aa5025..bea9a00 100644 --- a/android/jni/misc.cpp +++ b/android/jni/misc.cpp @@ -57,3 +57,4 @@ JNIEXPORT void JNICALL Java_br_com_bb_pw3270_lib3270_setToggle(JNIEnv *env, jobj PW3270_JNI_END } + diff --git a/android/jni/text.cpp b/android/jni/text.cpp index 57fa920..f4d2233 100644 --- a/android/jni/text.cpp +++ b/android/jni/text.cpp @@ -35,8 +35,8 @@ static jbyteArray retString(const char *txt) { size_t len = strlen(txt); - jbyteArray ret = pw3270_env->NewByteArray(len); - pw3270_env->SetByteArrayRegion(ret, 0, len, (jbyte*) txt); + jbyteArray ret = PW3270_JNI_ENV->NewByteArray(len); + PW3270_JNI_ENV->SetByteArrayRegion(ret, 0, len, (jbyte*) txt); return ret; } diff --git a/android/src/br/com/bb/pw3270/lib3270.java b/android/src/br/com/bb/pw3270/lib3270.java index 1eaffa6..94f7c9b 100644 --- a/android/src/br/com/bb/pw3270/lib3270.java +++ b/android/src/br/com/bb/pw3270/lib3270.java @@ -399,6 +399,7 @@ public class lib3270 /*---[ Native calls ]----------------------------------------------------*/ static private native int init(); + static private native int deinit(); private native int processEvents(); // private native int do_connect(); -- libgit2 0.21.2