share mpool and vtable in jni calls

A number of jni calls were "stateless", which meant they allocated their
own vtmgr and mpool instances each time invoked. Instead invoke them
with the global jni closure and add to it vtmgr (already has mpool) and
use these instead of allocating/freeing each time. To make sure no race
conditions are introduced (mpool, though debug-only, is probably not
thread-safe), guard these new uses with an in-use flag. If that fires
I'll need a mutex or something.
This commit is contained in:
Eric House 2018-06-27 21:17:44 -07:00
parent d2ab796fac
commit 9cdd5a7b72
2 changed files with 82 additions and 51 deletions

View file

@ -134,23 +134,30 @@ public class XwJNI {
public static native boolean timerFired( GamePtr gamePtr, int why,
int when, int handle );
// Stateless methods
public static native byte[] gi_to_stream( CurGameInfo gi );
public static native void gi_from_stream( CurGameInfo gi, byte[] stream );
public static byte[] gi_to_stream( CurGameInfo gi )
{
return gi_to_stream( getJNI().m_ptr, gi );
}
public static void gi_from_stream( CurGameInfo gi, byte[] stream )
{
gi_from_stream( getJNI().m_ptr, gi, stream );
}
public static byte[] nliToStream( NetLaunchInfo nli )
{
nli.freezeAddrs();
return nli_to_stream( nli );
return nli_to_stream( getJNI().m_ptr, nli );
}
private static native byte[] nli_to_stream( NetLaunchInfo nli );
public static NetLaunchInfo nliFromStream( byte[] stream )
{
NetLaunchInfo nli = new NetLaunchInfo();
nli_from_stream( nli, stream );
nli_from_stream( getJNI().m_ptr, nli, stream );
nli.unfreezeAddrs();
return nli;
}
private static native void nli_from_stream( NetLaunchInfo nli, byte[] stream );
public static native void comms_getInitialAddr( CommsAddrRec addr,
String relayHost,
int relayPort );
@ -470,7 +477,13 @@ public class XwJNI {
// Private methods -- called only here
private static native int initGlobals();
private static native void cleanGlobals( int globals );
private static native void cleanGlobals( int jniState );
private static native byte[] gi_to_stream( int jniState, CurGameInfo gi );
private static native void gi_from_stream( int jniState, CurGameInfo gi,
byte[] stream );
private static native byte[] nli_to_stream( int jniState, NetLaunchInfo nli );
private static native void nli_from_stream( int jniState, NetLaunchInfo nli,
byte[] stream );
private static native int initJNI( int jniState, int seed, String tag );
private static native void envDone( int globals );
private static native void dict_ref( int dictPtr );

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "find-and-gradle.sh installXw4Debug"; -*- */
/*
* Copyright © 2009 - 2014 by Eric House (xwords@eehouse.org). All rights
* Copyright © 2009 - 2018 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
@ -60,9 +60,30 @@ struct _EnvThreadInfo {
typedef struct _JNIGlobalState {
EnvThreadInfo ti;
DictMgrCtxt* dictMgr;
VTableMgr* vtMgr;
XP_Bool mpoolInUse;
MPSLOT
} JNIGlobalState;
#ifdef MEM_DEBUG
static MemPoolCtx*
getMPool( JNIGlobalState* state )
{
XP_ASSERT( !state->mpoolInUse );
state->mpoolInUse = XP_TRUE;
return state->mpool;
}
static void
releaseMPool( JNIGlobalState* state )
{
XP_ASSERT( state->mpoolInUse );
state->mpoolInUse = XP_FALSE;
}
#else
# define releaseMPool(s)
#endif
#define LOG_MAPPING
// #define LOG_MAPPING_ALL
@ -157,7 +178,7 @@ static void
map_init( MPFORMAL EnvThreadInfo* ti, JNIEnv* env )
{
pthread_mutex_init( &ti->mtxThreads, NULL );
MPASSIGN(ti->mpool, mpool);
MPASSIGN( ti->mpool, mpool );
map_thread( ti, env );
}
@ -263,6 +284,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_initGlobals
JNIGlobalState* state = (JNIGlobalState*)XP_CALLOC( mpool, sizeof(*state) );
map_init( MPPARM(mpool) &state->ti, env );
state->dictMgr = dmgr_make( MPPARM_NOCOMMA( mpool ) );
state->vtMgr = make_vtablemgr( MPPARM_NOCOMMA(mpool) );
MPASSIGN( state->mpool, mpool );
// LOG_RETURNF( "%p", state );
return (jint)state;
@ -276,10 +298,12 @@ Java_org_eehouse_android_xw4_jni_XwJNI_cleanGlobals
if ( 0 != ptr ) {
JNIGlobalState* state = (JNIGlobalState*)ptr;
XP_ASSERT( ENVFORME(&state->ti) == env );
dmgr_destroy( state->dictMgr );
#ifdef MEM_DEBUG
MemPoolCtx* mpool = state->mpool;
MemPoolCtx* mpool = getMPool( state );
#endif
XP_ASSERT( ENVFORME(&state->ti) == env );
vtmgr_destroy( MPPARM(mpool) state->vtMgr );
dmgr_destroy( state->dictMgr );
map_destroy( &state->ti );
XP_FREE( mpool, state );
mpool_destroy( mpool );
@ -525,15 +549,15 @@ streamFromJStream( MPFORMAL JNIEnv* env, VTableMgr* vtMgr, jbyteArray jstream )
****************************************************/
JNIEXPORT jbyteArray JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_gi_1to_1stream
(JNIEnv* env, jclass C, jobject jgi )
( JNIEnv* env, jclass C, jint jniGlobalPtr, jobject jgi )
{
jbyteArray result;
JNIGlobalState* state = (JNIGlobalState*)jniGlobalPtr;
#ifdef MEM_DEBUG
MemPoolCtx* mpool = mpool_make( NULL );
MemPoolCtx* mpool = getMPool( state );
#endif
CurGameInfo* gi = makeGI( MPPARM(mpool) env, jgi );
VTableMgr* vtMgr = make_vtablemgr( MPPARM_NOCOMMA(mpool) );
XWStreamCtxt* stream = mem_stream_make( MPPARM(mpool) vtMgr,
XWStreamCtxt* stream = mem_stream_make( MPPARM(mpool) state->vtMgr,
NULL, 0, NULL );
game_saveToStream( NULL, gi, stream, 0 );
@ -541,28 +565,24 @@ Java_org_eehouse_android_xw4_jni_XwJNI_gi_1to_1stream
result = streamToBArray( env, stream );
stream_destroy( stream );
vtmgr_destroy( MPPARM(mpool) vtMgr );
#ifdef MEM_DEBUG
mpool_destroy( mpool );
#endif
releaseMPool( state );
return result;
}
JNIEXPORT void JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_gi_1from_1stream
( JNIEnv* env, jclass C, jobject jgi, jbyteArray jstream )
( JNIEnv* env, jclass C, jint jniGlobalPtr, jobject jgi, jbyteArray jstream )
{
JNIGlobalState* state = (JNIGlobalState*)jniGlobalPtr;
#ifdef MEM_DEBUG
MemPoolCtx* mpool = mpool_make( NULL );
MemPoolCtx* mpool = getMPool( state );
#endif
VTableMgr* vtMgr = make_vtablemgr( MPPARM_NOCOMMA(mpool) );
XWStreamCtxt* stream = streamFromJStream( MPPARM(mpool) env, vtMgr, jstream );
XWStreamCtxt* stream = streamFromJStream( MPPARM(mpool) env,
state->vtMgr, jstream );
CurGameInfo gi;
XP_MEMSET( &gi, 0, sizeof(gi) );
if ( game_makeFromStream( MPPARM(mpool) stream, NULL,
if ( game_makeFromStream( MPPARM(mpool) stream, NULL,
&gi, NULL, NULL, NULL, NULL, NULL, NULL ) ) {
setJGI( env, jgi, &gi );
} else {
@ -572,50 +592,45 @@ Java_org_eehouse_android_xw4_jni_XwJNI_gi_1from_1stream
gi_disposePlayerInfo( MPPARM(mpool) &gi );
stream_destroy( stream );
vtmgr_destroy( MPPARM(mpool) vtMgr );
#ifdef MEM_DEBUG
mpool_destroy( mpool );
#endif
releaseMPool( state );
}
JNIEXPORT jbyteArray JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_nli_1to_1stream
( JNIEnv* env, jclass C, jobject njli )
( JNIEnv* env, jclass C, jint jniGlobalPtr, jobject njli )
{
LOG_FUNC();
jbyteArray result;
JNIGlobalState* state = (JNIGlobalState*)jniGlobalPtr;
#ifdef MEM_DEBUG
MemPoolCtx* mpool = mpool_make( NULL );
MemPoolCtx* mpool = getMPool( state );
#endif
jbyteArray result;
NetLaunchInfo nli = {0};
loadNLI( env, &nli, njli );
/* CurGameInfo* gi = makeGI( MPPARM(mpool) env, jgi ); */
VTableMgr* vtMgr = make_vtablemgr( MPPARM_NOCOMMA(mpool) );
XWStreamCtxt* stream = mem_stream_make( MPPARM(mpool) vtMgr,
XWStreamCtxt* stream = mem_stream_make( MPPARM(mpool) state->vtMgr,
NULL, 0, NULL );
nli_saveToStream( &nli, stream );
result = streamToBArray( env, stream );
stream_destroy( stream );
vtmgr_destroy( MPPARM(mpool) vtMgr );
#ifdef MEM_DEBUG
mpool_destroy( mpool );
#endif
releaseMPool( state );
return result;
}
JNIEXPORT void JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_nli_1from_1stream
( JNIEnv* env, jclass C, jobject jnli, jbyteArray jstream )
( JNIEnv* env, jclass C, jint jniGlobalPtr, jobject jnli, jbyteArray jstream )
{
LOG_FUNC();
JNIGlobalState* state = (JNIGlobalState*)jniGlobalPtr;
#ifdef MEM_DEBUG
MemPoolCtx* mpool = mpool_make( NULL );
MemPoolCtx* mpool = getMPool( state );
#endif
VTableMgr* vtMgr = make_vtablemgr( MPPARM_NOCOMMA(mpool) );
XWStreamCtxt* stream = streamFromJStream( MPPARM(mpool) env, vtMgr, jstream );
XWStreamCtxt* stream = streamFromJStream( MPPARM(mpool) env,
state->vtMgr, jstream );
NetLaunchInfo nli = {0};
if ( nli_makeFromStream( &nli, stream ) ) {
@ -625,10 +640,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_nli_1from_1stream
}
stream_destroy( stream );
vtmgr_destroy( MPPARM(mpool) vtMgr );
#ifdef MEM_DEBUG
mpool_destroy( mpool );
#endif
releaseMPool( state );
}
JNIEXPORT void JNICALL
@ -689,8 +701,13 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1getInfo
jboolean result = false;
JNIGlobalState* state = (JNIGlobalState*)jniGlobalPtr;
map_thread( &state->ti, env );
JNIUtilCtxt* jniutil = makeJNIUtil( MPPARM(state->mpool) env, &state->ti, jniu );
DictionaryCtxt* dict = makeDict( MPPARM(state->mpool) env, state->dictMgr,
#ifdef MEM_DEBUG
MemPoolCtx* mpool = getMPool( state );
#endif
JNIUtilCtxt* jniutil = makeJNIUtil( MPPARM(mpool) env, &state->ti, jniu );
DictionaryCtxt* dict = makeDict( MPPARM(mpool) env, state->dictMgr,
jniutil, jname, jDictBytes, jpath,
NULL, check );
if ( NULL != dict ) {
@ -706,6 +723,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1getInfo
}
destroyJNIUtil( env, &jniutil );
releaseMPool( state );
return result;
}