diff --git a/xwords4/android/XWords4/jni/andglobals.h b/xwords4/android/XWords4/jni/andglobals.h index 2fdb74420..19efedbee 100644 --- a/xwords4/android/XWords4/jni/andglobals.h +++ b/xwords4/android/XWords4/jni/andglobals.h @@ -24,6 +24,8 @@ #include "dictnry.h" #include "game.h" +typedef struct _JNIState JNIState; + typedef struct _AndGlobals { VTableMgr* vtMgr; CurGameInfo* gi; @@ -31,7 +33,12 @@ typedef struct _AndGlobals { XW_UtilCtxt* util; struct JNIUtilCtxt* jniutil; TransportProcs* xportProcs; - struct JNIState* state; + JNIState* state; } AndGlobals; +typedef struct _EnvThreadInfo EnvThreadInfo; + +JNIEnv* envForMe( EnvThreadInfo* ti, const char* caller ); +#define ENVFORME( ti ) envForMe( (ti), __func__ ) + #endif diff --git a/xwords4/android/XWords4/jni/drawwrapper.c b/xwords4/android/XWords4/jni/drawwrapper.c index f13e324b5..6790f188c 100644 --- a/xwords4/android/XWords4/jni/drawwrapper.c +++ b/xwords4/android/XWords4/jni/drawwrapper.c @@ -37,7 +37,7 @@ enum { typedef struct _AndDraw { DrawCtxVTable* vtable; - JNIEnv** env; + EnvThreadInfo* ti; jobject jdraw; /* global ref; free it! */ XP_LangCode curLang; jobject jCache[JCACHE_COUNT]; @@ -48,7 +48,7 @@ typedef struct _AndDraw { static jobject makeJRect( AndDraw* draw, int indx, const XP_Rect* rect ) { - JNIEnv* env = *draw->env; + JNIEnv* env = ENVFORME( draw->ti ); jobject robj = draw->jCache[indx]; int right = rect->left + rect->width; int bottom = rect->top + rect->height; @@ -87,7 +87,7 @@ static jobject makeJRects( AndDraw* draw, int indx, XP_U16 nPlayers, const XP_Rect rects[] ) { XP_U16 ii; - JNIEnv* env = *draw->env; + JNIEnv* env = ENVFORME( draw->ti ); jobject jrects = draw->jCache[indx]; if ( !jrects ) { jclass rclass = (*env)->FindClass( env, "android/graphics/Rect"); @@ -122,7 +122,7 @@ static jobject makeDSIs( AndDraw* draw, int indx, XP_U16 nPlayers, const DrawScoreInfo dsis[] ) { XP_U16 ii; - JNIEnv* env = *draw->env; + JNIEnv* env = ENVFORME( draw->ti ); jobject dsiobjs = draw->jCache[indx]; if ( !dsiobjs ) { @@ -164,7 +164,7 @@ makeDSIs( AndDraw* draw, int indx, XP_U16 nPlayers, const DrawScoreInfo dsis[] ) static jobject makeDSI( AndDraw* draw, int indx, const DrawScoreInfo* dsi ) { - JNIEnv* env = *draw->env; + JNIEnv* env = ENVFORME( draw->ti ); jobject dsiobj = draw->jCache[indx]; if ( !dsiobj ) { @@ -193,7 +193,7 @@ makeDSI( AndDraw* draw, int indx, const DrawScoreInfo* dsi ) #define DRAW_CBK_HEADER(nam,sig) \ AndDraw* draw = (AndDraw*)dctx; \ - JNIEnv* env = *draw->env; \ + JNIEnv* env = ENVFORME( draw->ti ); \ XP_ASSERT( !!draw->jdraw ); \ jmethodID mid = getMethodID( env, draw->jdraw, nam, sig ); @@ -600,15 +600,15 @@ draw_doNothing( DrawCtx* dctx, ... ) } /* draw_doNothing */ DrawCtx* -makeDraw( MPFORMAL JNIEnv** envp, jobject jdraw ) +makeDraw( MPFORMAL EnvThreadInfo* ti, jobject jdraw ) { AndDraw* draw = (AndDraw*)XP_CALLOC( mpool, sizeof(*draw) ); - JNIEnv* env = *envp; + JNIEnv* env = ENVFORME( ti ); draw->vtable = XP_MALLOC( mpool, sizeof(*draw->vtable) ); if ( NULL != jdraw ) { draw->jdraw = (*env)->NewGlobalRef( env, jdraw ); } - draw->env = envp; + draw->ti = ti; MPASSIGN( draw->mpool, mpool ); int ii; @@ -659,7 +659,7 @@ destroyDraw( DrawCtx** dctx ) { if ( !!*dctx ) { AndDraw* draw = (AndDraw*)*dctx; - JNIEnv* env = *draw->env; + JNIEnv* env = ENVFORME( draw->ti ); if ( NULL != draw->jdraw ) { (*env)->DeleteGlobalRef( env, draw->jdraw ); } diff --git a/xwords4/android/XWords4/jni/drawwrapper.h b/xwords4/android/XWords4/jni/drawwrapper.h index ca02dce09..c6d52474b 100644 --- a/xwords4/android/XWords4/jni/drawwrapper.h +++ b/xwords4/android/XWords4/jni/drawwrapper.h @@ -25,7 +25,9 @@ #include "draw.h" -DrawCtx* makeDraw( MPFORMAL JNIEnv** env, jobject j_draw ); +#include "andglobals.h" + +DrawCtx* makeDraw( MPFORMAL EnvThreadInfo* ti, jobject j_draw ); void destroyDraw( DrawCtx** dctx ); diff --git a/xwords4/android/XWords4/jni/jniutlswrapper.c b/xwords4/android/XWords4/jni/jniutlswrapper.c index 5fa50cae3..b8896cadc 100644 --- a/xwords4/android/XWords4/jni/jniutlswrapper.c +++ b/xwords4/android/XWords4/jni/jniutlswrapper.c @@ -24,17 +24,17 @@ struct JNIUtilCtxt { - JNIEnv** envp; + EnvThreadInfo* ti; jobject jjniutil; MPSLOT; }; JNIUtilCtxt* -makeJNIUtil( MPFORMAL JNIEnv** envp, jobject jniutls ) +makeJNIUtil( MPFORMAL EnvThreadInfo* ti, jobject jniutls ) { JNIUtilCtxt* ctxt = (JNIUtilCtxt*)XP_CALLOC( mpool, sizeof( *ctxt ) ); - JNIEnv* env = *envp; - ctxt->envp = envp; + ctxt->ti = ti; + JNIEnv* env = ENVFORME( ti ); ctxt->jjniutil = (*env)->NewGlobalRef( env, jniutls ); MPASSIGN( ctxt->mpool, mpool ); return ctxt; @@ -45,7 +45,7 @@ destroyJNIUtil( JNIUtilCtxt** ctxtp ) { JNIUtilCtxt* ctxt = *ctxtp; if ( !!ctxt ) { - JNIEnv* env = *ctxt->envp; + JNIEnv* env = ENVFORME( ctxt->ti ); (*env)->DeleteGlobalRef( env, ctxt->jjniutil ); XP_FREE( ctxt->mpool, ctxt ); *ctxtp = NULL; @@ -59,7 +59,7 @@ and_util_makeJBitmap( JNIUtilCtxt* jniutil, int nCols, int nRows, const jboolean* colors ) { jobject bitmap; - JNIEnv* env = *jniutil->envp; + JNIEnv* env = ENVFORME( jniutil->ti ); jmethodID mid = getMethodID( env, jniutil->jjniutil, "makeBitmap", "(II[Z)Landroid/graphics/drawable/BitmapDrawable;" ); @@ -79,7 +79,7 @@ and_util_splitFaces( JNIUtilCtxt* jniutil, const XP_U8* bytes, jsize len, XP_Bool isUTF8 ) { jobject strarray = NULL; - JNIEnv* env = *jniutil->envp; + JNIEnv* env = ENVFORME( jniutil->ti ); jmethodID mid = getMethodID( env, jniutil->jjniutil, "splitFaces", "([BZ)[[Ljava/lang/String;" ); @@ -96,7 +96,7 @@ jstring and_util_getMD5SumForDict( JNIUtilCtxt* jniutil, const XP_UCHAR* name, const XP_U8* bytes, jsize len ) { - JNIEnv* env = *jniutil->envp; + JNIEnv* env = ENVFORME( jniutil->ti ); jmethodID mid = getMethodID( env, jniutil->jjniutil, "getMD5SumFor", "(Ljava/lang/String;[B)Ljava/lang/String;" ); jstring jname = (*env)->NewStringUTF( env, name ); @@ -112,7 +112,7 @@ and_util_getMD5SumForDict( JNIUtilCtxt* jniutil, const XP_UCHAR* name, jstring and_util_getMD5SumForBytes( JNIUtilCtxt* jniutil, const XP_U8* bytes, jsize len ) { - JNIEnv* env = *jniutil->envp; + JNIEnv* env = ENVFORME( jniutil->ti ); jmethodID mid = getMethodID( env, jniutil->jjniutil, "getMD5SumFor", "([B)Ljava/lang/String;" ); diff --git a/xwords4/android/XWords4/jni/jniutlswrapper.h b/xwords4/android/XWords4/jni/jniutlswrapper.h index a918ba3ba..66892f3b2 100644 --- a/xwords4/android/XWords4/jni/jniutlswrapper.h +++ b/xwords4/android/XWords4/jni/jniutlswrapper.h @@ -28,7 +28,7 @@ typedef struct JNIUtilCtxt JNIUtilCtxt; -JNIUtilCtxt* makeJNIUtil( MPFORMAL JNIEnv** env, jobject jniutls ); +JNIUtilCtxt* makeJNIUtil( MPFORMAL EnvThreadInfo* ti, jobject jniutls ); void destroyJNIUtil( JNIUtilCtxt** jniu ); jobject and_util_makeJBitmap( JNIUtilCtxt* jniu, int nCols, int nRows, diff --git a/xwords4/android/XWords4/jni/utilwrapper.c b/xwords4/android/XWords4/jni/utilwrapper.c index 230a591d2..63e8475ff 100644 --- a/xwords4/android/XWords4/jni/utilwrapper.c +++ b/xwords4/android/XWords4/jni/utilwrapper.c @@ -35,7 +35,7 @@ typedef struct _TimerStorage { typedef struct _AndUtil { XW_UtilCtxt util; - JNIEnv** env; + EnvThreadInfo* ti; jobject jutil; /* global ref to object implementing XW_UtilCtxt */ TimerStorage timerStorage[NUM_TIMERS_PLUS_ONE]; XP_UCHAR* userStrings[N_AND_USER_STRINGS]; @@ -70,7 +70,7 @@ and_util_makeStreamFromAddr( XW_UtilCtxt* uc, XP_PlayerAddr channelNo ) #define UTIL_CBK_HEADER(nam,sig) \ AndUtil* util = (AndUtil*)uc; \ - JNIEnv* env = *util->env; \ + JNIEnv* env = ENVFORME( util->ti ); \ if ( NULL != util->jutil ) { \ jmethodID mid = getMethodID( env, util->jutil, nam, sig ) @@ -376,7 +376,7 @@ XP_U32 and_util_getCurSeconds( XW_UtilCtxt* uc ) { AndUtil* andutil = (AndUtil*)uc; - XP_U32 curSeconds = getCurSeconds( *andutil->env ); + XP_U32 curSeconds = getCurSeconds( ENVFORME( andutil->ti ) ); /* struct timeval tv; */ /* gettimeofday( &tv, NULL ); */ /* XP_LOGF( "%s: %d vs %d", __func__, (int)tv.tv_sec, (int)curSeconds ); */ @@ -394,7 +394,7 @@ and_util_makeEmptyDict( XW_UtilCtxt* uc ) AndUtil* andutil = (AndUtil*)uc; DictionaryCtxt* result = and_dictionary_make_empty( MPPARM( ((AndUtil*)uc)->util.mpool ) - *andutil->env, globals->jniutil ); + ENVFORME( andutil->ti ), globals->jniutil ); return dict_ref( result ); #endif } @@ -637,7 +637,7 @@ static XP_UCHAR* and_util_md5sum( XW_UtilCtxt* uc, const XP_U8* ptr, XP_U16 len ) { AndUtil* util = (AndUtil*)uc; - JNIEnv* env = *util->env; + JNIEnv* env = ENVFORME( util->ti ); AndGlobals* globals = (AndGlobals*)uc->closure; struct JNIUtilCtxt* jniutil = globals->jniutil; jstring jsum = and_util_getMD5SumForBytes( jniutil, ptr, len ); @@ -649,13 +649,13 @@ and_util_md5sum( XW_UtilCtxt* uc, const XP_U8* ptr, XP_U16 len ) XW_UtilCtxt* -makeUtil( MPFORMAL JNIEnv** envp, jobject jutil, CurGameInfo* gi, +makeUtil( MPFORMAL EnvThreadInfo* ti, jobject jutil, CurGameInfo* gi, AndGlobals* closure ) { AndUtil* util = (AndUtil*)XP_CALLOC( mpool, sizeof(*util) ); UtilVtable* vtable = (UtilVtable*)XP_CALLOC( mpool, sizeof(*vtable) ); - util->env = envp; - JNIEnv* env = *envp; + util->ti = ti; + JNIEnv* env = ENVFORME( util->ti ); if ( NULL != jutil ) { util->jutil = (*env)->NewGlobalRef( env, jutil ); } @@ -743,7 +743,7 @@ void destroyUtil( XW_UtilCtxt** utilc ) { AndUtil* util = (AndUtil*)*utilc; - JNIEnv *env = *util->env; + JNIEnv* env = ENVFORME( util->ti ); int ii; for ( ii = 0; ii < VSIZE(util->userStrings); ++ii ) { diff --git a/xwords4/android/XWords4/jni/utilwrapper.h b/xwords4/android/XWords4/jni/utilwrapper.h index 6c9d3cd23..44a21acc3 100644 --- a/xwords4/android/XWords4/jni/utilwrapper.h +++ b/xwords4/android/XWords4/jni/utilwrapper.h @@ -27,7 +27,7 @@ #include "util.h" #include "andglobals.h" -XW_UtilCtxt* makeUtil( MPFORMAL JNIEnv** env, jobject j_util, +XW_UtilCtxt* makeUtil( MPFORMAL EnvThreadInfo* ti, jobject j_util, CurGameInfo* gi, AndGlobals* globals ); void destroyUtil( XW_UtilCtxt** util ); diff --git a/xwords4/android/XWords4/jni/xportwrapper.c b/xwords4/android/XWords4/jni/xportwrapper.c index c821245a1..8c984b007 100644 --- a/xwords4/android/XWords4/jni/xportwrapper.c +++ b/xwords4/android/XWords4/jni/xportwrapper.c @@ -24,7 +24,7 @@ typedef struct _AndTransportProcs { TransportProcs tp; - JNIEnv** envp; + EnvThreadInfo* ti; jobject jxport; MPSLOT } AndTransportProcs; @@ -56,7 +56,7 @@ and_xport_getFlags( void* closure ) jint result = 0; AndTransportProcs* aprocs = (AndTransportProcs*)closure; if ( NULL != aprocs->jxport ) { - JNIEnv* env = *aprocs->envp; + JNIEnv* env = ENVFORME( aprocs->ti ); const char* sig = "()I"; jmethodID mid = getMethodID( env, aprocs->jxport, "getFlags", sig ); @@ -73,7 +73,7 @@ and_xport_send( const XP_U8* buf, XP_U16 len, const CommsAddrRec* addr, LOG_FUNC(); AndTransportProcs* aprocs = (AndTransportProcs*)closure; if ( NULL != aprocs->jxport ) { - JNIEnv* env = *aprocs->envp; + JNIEnv* env = ENVFORME( aprocs->ti ); const char* sig = "([BL" PKG_PATH("jni/CommsAddrRec") ";I)I"; jmethodID mid = getMethodID( env, aprocs->jxport, "transportSend", sig ); @@ -94,7 +94,7 @@ and_xport_relayStatus( void* closure, CommsRelayState newState ) { AndTransportProcs* aprocs = (AndTransportProcs*)closure; if ( NULL != aprocs->jxport ) { - JNIEnv* env = *aprocs->envp; + JNIEnv* env = ENVFORME( aprocs->ti ); const char* sig = "(L" PKG_PATH("jni/TransportProcs$CommsRelayState") ";)V"; jmethodID mid = getMethodID( env, aprocs->jxport, "relayStatus", sig ); @@ -111,7 +111,7 @@ and_xport_relayConnd( void* closure, XP_UCHAR* const room, XP_Bool reconnect, { AndTransportProcs* aprocs = (AndTransportProcs*)closure; if ( NULL != aprocs->jxport ) { - JNIEnv* env = *aprocs->envp; + JNIEnv* env = ENVFORME( aprocs->ti ); const char* sig = "(Ljava/lang/String;IZI)V"; jmethodID mid = getMethodID( env, aprocs->jxport, "relayConnd", sig ); @@ -129,7 +129,7 @@ and_xport_sendNoConn( const XP_U8* buf, XP_U16 len, jboolean result = false; AndTransportProcs* aprocs = (AndTransportProcs*)closure; if ( NULL != aprocs && NULL != aprocs->jxport ) { - JNIEnv* env = *aprocs->envp; + JNIEnv* env = ENVFORME( aprocs->ti ); const char* sig = "([BLjava/lang/String;)Z"; jmethodID mid = getMethodID( env, aprocs->jxport, @@ -148,7 +148,7 @@ and_xport_relayError( void* closure, XWREASON relayErr ) { AndTransportProcs* aprocs = (AndTransportProcs*)closure; if ( NULL != aprocs->jxport ) { - JNIEnv* env = *aprocs->envp; + JNIEnv* env = ENVFORME( aprocs->ti ); jmethodID mid; const char* sig = "(L" PKG_PATH("jni/TransportProcs$XWRELAY_ERROR") ";)V"; @@ -163,16 +163,16 @@ and_xport_relayError( void* closure, XWREASON relayErr ) } TransportProcs* -makeXportProcs( MPFORMAL JNIEnv** envp, jobject jxport ) +makeXportProcs( MPFORMAL EnvThreadInfo* ti, jobject jxport ) { AndTransportProcs* aprocs = NULL; - JNIEnv* env = *envp; + JNIEnv* env = ENVFORME( ti ); aprocs = (AndTransportProcs*)XP_CALLOC( mpool, sizeof(*aprocs) ); if ( NULL != jxport ) { aprocs->jxport = (*env)->NewGlobalRef( env, jxport ); } - aprocs->envp = envp; + aprocs->ti = ti; MPASSIGN( aprocs->mpool, mpool ); #ifdef COMMS_XPORT_FLAGSPROC @@ -192,7 +192,7 @@ void destroyXportProcs( TransportProcs** xport ) { AndTransportProcs* aprocs = (AndTransportProcs*)*xport; - JNIEnv* env = *aprocs->envp; + JNIEnv* env = ENVFORME( aprocs->ti ); if ( NULL != aprocs->jxport ) { (*env)->DeleteGlobalRef( env, aprocs->jxport ); } diff --git a/xwords4/android/XWords4/jni/xportwrapper.h b/xwords4/android/XWords4/jni/xportwrapper.h index 626952e14..24cc95f05 100644 --- a/xwords4/android/XWords4/jni/xportwrapper.h +++ b/xwords4/android/XWords4/jni/xportwrapper.h @@ -23,9 +23,12 @@ #include +#include "andglobals.h" + #include "comms.h" -TransportProcs* makeXportProcs( MPFORMAL JNIEnv** env, jobject jxport ); +TransportProcs* makeXportProcs( MPFORMAL EnvThreadInfo* ti, jobject jxport ); + void destroyXportProcs( TransportProcs** xport ); #endif diff --git a/xwords4/android/XWords4/jni/xwjni.c b/xwords4/android/XWords4/jni/xwjni.c index 20841d256..780ace080 100644 --- a/xwords4/android/XWords4/jni/xwjni.c +++ b/xwords4/android/XWords4/jni/xwjni.c @@ -19,6 +19,7 @@ */ #include #include +#include #include #include @@ -37,16 +38,97 @@ #include "xportwrapper.h" #include "anddict.h" #include "andutils.h" +#include "andglobals.h" #include "jniutlswrapper.h" #include "paths.h" +typedef struct _EnvThreadEntry { + JNIEnv* env; + pthread_t owner; +} EnvThreadEntry; + +#define MAX_ENV_THREADS 10 + +struct _EnvThreadInfo { + pthread_mutex_t mtxThreads; + EnvThreadEntry entries[MAX_ENV_THREADS]; + XP_U16 nMaps; +}; + /* Globals for the whole game */ typedef struct _JNIGlobalState { - JNIEnv* env; + EnvThreadInfo ti; DictMgrCtxt* dictMgr; MPSLOT } JNIGlobalState; +static void +map_init( EnvThreadInfo* ti ) +{ + pthread_mutex_init( &ti->mtxThreads, NULL ); +} + +static void +map_destroy( EnvThreadInfo* ti ) +{ + // XP_ASSERT( 0 == ti->nMaps ); + XP_LOGF( "%s: had %d threads max", __func__, ti->nMaps ); + pthread_mutex_destroy( &ti->mtxThreads ); +} + +static void +map_thread( EnvThreadInfo* ti, JNIEnv* env, const char* proc ) +{ + pthread_t self = pthread_self(); + + pthread_mutex_lock( &ti->mtxThreads ); + + XP_Bool found = false; + for ( int ii = 0; !found && ii < ti->nMaps; ++ii ) { + EnvThreadEntry* entry = &ti->entries[ii]; + found = self == entry->owner; + if ( found ) { + if ( env != entry->env ) { + /* this DOES happen!!! */ + XP_LOGF( "%s: replacing env %p with env %p for thread %x", + __func__, entry->env, env, (int)self ); + entry->env = env; + } + } + } + + if ( !found ) { + EnvThreadEntry* entry = &ti->entries[ti->nMaps++]; + entry->owner = self; + entry->env = env; + XP_LOGF( "%s: mapped env %p to thread %x", __func__, env, (int)self ); + XP_ASSERT( ti->nMaps < MAX_ENV_THREADS ); + } + + pthread_mutex_unlock( &ti->mtxThreads ); +} + +JNIEnv* +envForMe( EnvThreadInfo* ti, const char* caller ) +{ + JNIEnv* result = NULL; + pthread_t self = pthread_self(); + pthread_mutex_lock( &ti->mtxThreads ); + for ( int ii = 0; ii < ti->nMaps; ++ii ) { + if ( self == ti->entries[ii].owner ) { + result = ti->entries[ii].env; + break; + } + } + pthread_mutex_unlock( &ti->mtxThreads ); + if( !result ) { + XP_LOGF( "no env for %s (thread %x in %d entries)", caller, + (int)self, ti->nMaps ); + XP_ASSERT(0); + } + return result; +} + JNIEXPORT jint JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_initGlobals ( JNIEnv* env, jclass C ) @@ -55,7 +137,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_initGlobals MemPoolCtx* mpool = mpool_make(); #endif JNIGlobalState* state = (JNIGlobalState*)XP_CALLOC( mpool, sizeof(*state) ); - state->env = env; + map_init( &state->ti ); state->dictMgr = dmgr_make( MPPARM_NOCOMMA( mpool ) ); MPASSIGN( state->mpool, mpool ); LOG_RETURNF( "%p", state ); @@ -69,11 +151,12 @@ Java_org_eehouse_android_xw4_jni_XwJNI_cleanGlobals LOG_FUNC(); if ( 0 != ptr ) { JNIGlobalState* state = (JNIGlobalState*)ptr; - XP_ASSERT( state->env == env ); + XP_ASSERT( ENVFORME(&state->ti) == env ); dmgr_destroy( state->dictMgr ); #ifdef MEM_DEBUG MemPoolCtx* mpool = state->mpool; #endif + map_destroy( &state->ti ); XP_FREE( mpool, state ); mpool_destroy( mpool ); } @@ -386,9 +469,10 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1getInfo { jboolean result = false; JNIGlobalState* state = (JNIGlobalState*)jniGlobalPtr; - JNIUtilCtxt* jniutil = makeJNIUtil( MPPARM(state->mpool) &env, jniu ); + JNIUtilCtxt* jniutil = makeJNIUtil( MPPARM(state->mpool) &state->ti, jniu ); DictionaryCtxt* dict = makeDict( MPPARM(state->mpool) env, state->dictMgr, - jniutil, jname, jDictBytes, jpath, NULL, check ); + jniutil, jname, jDictBytes, jpath, + NULL, check ); if ( NULL != dict ) { if ( NULL != jinfo ) { XP_LangCode code = dict_getLangCode( dict ); @@ -435,9 +519,8 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1getTileValue return dict_getTileValue( (DictionaryCtxt*)dictPtr, tile ); } -typedef struct _JNIState { +struct _JNIState { XWGame game; - JNIEnv* env; JNIGlobalState* globalJNI; AndGlobals globals; XP_U16 curSaveCount; @@ -446,38 +529,22 @@ typedef struct _JNIState { const char* envSetterFunc; #endif MPSLOT -} JNIState; - -#ifdef DEBUG -# define CHECK_ENV() \ - if ( state->env != 0 && state->env != env ) { \ - XP_LOGF( "ERROR: %s trying to set env when %s still has it", \ - __func__, state->envSetterFunc ); \ - XP_ASSERT( state->env == 0 || state->env == env ); \ - } \ - state->envSetterFunc = __func__; \ - -#else -# define CHECK_ENV() -#endif +}; #define XWJNI_START() { \ XP_ASSERT( 0 != gamePtr ); \ JNIState* state = (JNIState*)gamePtr; \ MPSLOT; \ MPASSIGN( mpool, state->mpool); \ - /* if reentrant must be from same thread */ \ - CHECK_ENV(); \ - JNIEnv* _oldEnv = state->env; \ - state->env = env; + XP_ASSERT( !!state->globalJNI ); \ + map_thread( &state->globalJNI->ti, env, __func__ ); \ #define XWJNI_START_GLOBALS() \ XWJNI_START() \ AndGlobals* globals = &state->globals; \ -#define XWJNI_END() \ - state->env = _oldEnv; \ - } +#define XWJNI_END() \ + } \ JNIEXPORT jint JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_initJNI @@ -493,7 +560,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_initJNI JNIState* state = (JNIState*)XP_CALLOC( mpool, sizeof(*state) ); state->globalJNI = (JNIGlobalState*)jniGlobalPtr; AndGlobals* globals = &state->globals; - globals->state = (struct JNIState*)state; + globals->state = (JNIState*)state; MPASSIGN( state->mpool, mpool ); globals->vtMgr = make_vtablemgr(MPPARM_NOCOMMA(mpool)); @@ -511,17 +578,18 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeNewGame jstring j_lang ) { XWJNI_START_GLOBALS(); + EnvThreadInfo* ti = &state->globalJNI->ti; CurGameInfo* gi = makeGI( MPPARM(mpool) env, j_gi ); globals->gi = gi; - globals->util = makeUtil( MPPARM(mpool) &state->env, j_util, gi, + globals->util = makeUtil( MPPARM(mpool) ti, j_util, gi, globals ); - globals->jniutil = makeJNIUtil( MPPARM(mpool) &state->env, jniu ); + globals->jniutil = makeJNIUtil( MPPARM(mpool) ti, jniu ); DrawCtx* dctx = NULL; if ( !!j_draw ) { - dctx = makeDraw( MPPARM(mpool) &state->env, j_draw ); + dctx = makeDraw( MPPARM(mpool) ti, j_draw ); } globals->dctx = dctx; - globals->xportProcs = makeXportProcs( MPPARM(mpool) &state->env, j_procs ); + globals->xportProcs = makeXportProcs( MPPARM(mpool) ti, j_procs ); CommonPrefs cp; loadCommonPrefs( env, &cp, j_cp ); @@ -559,8 +627,6 @@ JNIEXPORT void JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_game_1dispose destroyGI( MPPARM(mpool) &globals->gi ); - JNIEnv* oldEnv = state->env; - state->env = env; game_dispose( &state->game ); destroyDraw( &globals->dctx ); @@ -569,7 +635,6 @@ JNIEXPORT void JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_game_1dispose destroyJNIUtil( &globals->jniutil ); vtmgr_destroy( MPPARM(mpool) globals->vtMgr ); - state->env = oldEnv; XP_FREE( mpool, state ); mpool_destroy( mpool ); } /* game_dispose */ @@ -585,18 +650,18 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeFromStream DictionaryCtxt* dict; PlayerDicts dicts; XWJNI_START_GLOBALS(); + EnvThreadInfo* ti = &state->globalJNI->ti; globals->gi = (CurGameInfo*)XP_CALLOC( mpool, sizeof(*globals->gi) ); - globals->util = makeUtil( MPPARM(mpool) &state->env, - jutil, globals->gi, globals ); - globals->jniutil = makeJNIUtil( MPPARM(mpool) &state->env, jniu ); + globals->util = makeUtil( MPPARM(mpool) ti, jutil, globals->gi, globals); + globals->jniutil = makeJNIUtil( MPPARM(mpool) ti, jniu ); makeDicts( MPPARM(state->globalJNI->mpool) env, state->globalJNI->dictMgr, globals->jniutil, &dict, &dicts, jdictNames, jdicts, jpaths, jlang ); if ( !!jdraw ) { - globals->dctx = makeDraw( MPPARM(mpool) &state->env, jdraw ); + globals->dctx = makeDraw( MPPARM(mpool) ti, jdraw ); } - globals->xportProcs = makeXportProcs( MPPARM(mpool) &state->env, jprocs ); + globals->xportProcs = makeXportProcs( MPPARM(mpool) ti, jprocs ); XWStreamCtxt* stream = streamFromJStream( MPPARM(mpool) env, globals->vtMgr, jstream ); @@ -673,7 +738,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1setDraw { XWJNI_START_GLOBALS(); - DrawCtx* newDraw = makeDraw( MPPARM(mpool) &state->env, jdraw ); + DrawCtx* newDraw = makeDraw( MPPARM(mpool) &state->globalJNI->ti, jdraw ); board_setDraw( state->game.board, newDraw ); destroyDraw( &globals->dctx ); @@ -1664,7 +1729,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1iter_1init JNIGlobalState* state = (JNIGlobalState*)jniGlobalPtr; DictIterData* data = XP_CALLOC( state->mpool, sizeof(*data) ); data->env = env; - JNIUtilCtxt* jniutil = makeJNIUtil( MPPARM(state->mpool) &data->env, jniu ); + JNIUtilCtxt* jniutil = makeJNIUtil( MPPARM(state->mpool) &state->ti, jniu ); DictionaryCtxt* dict = makeDict( MPPARM(state->mpool) env, state->dictMgr, jniutil, jname, jDictBytes, jpath, NULL, false );