mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-05 20:45:49 +01:00
add and start using indexeddb via emscripten APIs
Replace a couple of load/store actions with new APIs that do so asynchronously (using indexeddb underneath, via emscripten APIs.) Required restructuring how app starts. More changes to come. The idea is to replace wordlist storage: this'll keep 'em smaller and not require conversion to string.
This commit is contained in:
parent
55f590ca0b
commit
2a6931fdcf
4 changed files with 164 additions and 44 deletions
|
@ -36,6 +36,9 @@ typedef enum { UNPAUSED,
|
|||
|
||||
typedef XP_Bool (*OnOneProc)(void* closure, const XP_UCHAR* indx);
|
||||
|
||||
typedef void (*OnStoreProc)( void* closure, bool success );
|
||||
typedef void (*OnLoadProc)( void* closure, const char* key, void* data, int len );
|
||||
|
||||
typedef struct _DUtilVtable {
|
||||
XP_U32 (*m_dutil_getCurSeconds)( XW_DUtilCtxt* duc, XWEnv xwe );
|
||||
const XP_UCHAR* (*m_dutil_getUserString)( XW_DUtilCtxt* duc, XWEnv xwe,
|
||||
|
@ -56,6 +59,11 @@ typedef struct _DUtilVtable {
|
|||
const XP_UCHAR* fallbackKey, // PENDING() remove this after a few months.
|
||||
void* data, XP_U32* lenp );
|
||||
|
||||
void (*m_dutil_startStore)( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
|
||||
const void* data, XP_U32 len, OnStoreProc proc, void* closure );
|
||||
void (*m_dutil_startLoad)( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
|
||||
OnLoadProc proc, void* closure );
|
||||
|
||||
#ifdef XWFEATURE_INDEXSTORE
|
||||
void (*m_dutil_storeIndxStream)( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
|
||||
const XP_UCHAR* indx, XWStreamCtxt* data );
|
||||
|
@ -153,6 +161,11 @@ void dutil_super_init( MPFORMAL XW_DUtilCtxt* dutil );
|
|||
#define dutil_removeAllIndx(duc, indx) \
|
||||
(duc)->vtable.m_dutil_removeAllIndx((duc), (indx));
|
||||
|
||||
#define dutil_startStore( duc, xwe, key, data, len, proc, closure ) \
|
||||
(duc)->vtable.m_dutil_startStore((duc), (xwe), (key), (data), (len), (proc), (closure) )
|
||||
#define dutil_startLoad( duc, xwe, key, proc, closure ) \
|
||||
(duc)->vtable.m_dutil_startLoad((duc), (xwe), (key), (proc), (closure) )
|
||||
|
||||
#ifdef XWFEATURE_SMS
|
||||
# define dutil_phoneNumbersSame(duc,e,p1,p2) \
|
||||
(duc)->vtable.m_dutil_phoneNumbersSame( (duc), (e), (p1), (p2) )
|
||||
|
|
|
@ -611,25 +611,14 @@ onDeleteConfirmed( void* closure, bool confirmed )
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
getPlayerName( Globals* globals, char* playerName, size_t buflen )
|
||||
{
|
||||
XP_U32 len = buflen;
|
||||
dutil_loadPtr( globals->dutil, NULL, KEY_PLAYER_NAME, NULL,
|
||||
playerName, &len );
|
||||
XP_LOGFF( "after: len: %d", len );
|
||||
if ( 0 == len ) { /* not found? */
|
||||
strcpy( playerName, "Player 1" );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
onPlayerNamed( void* closure, const char* name )
|
||||
{
|
||||
CAST_GLOB(Globals*, globals, closure);
|
||||
if ( !!name ) {
|
||||
dutil_storePtr( globals->dutil, NULL, KEY_PLAYER_NAME,
|
||||
name, 1 + strlen(name) );
|
||||
strncpy( globals->playerName, name, VSIZE(globals->playerName) );
|
||||
dutil_startStore( globals->dutil, NULL, KEY_PLAYER_NAME,
|
||||
name, 1 + strlen(name), NULL, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -655,9 +644,7 @@ onDeviceButton( void* closure, const char* button )
|
|||
curGS->gameName );
|
||||
call_confirm( globals, msg, onDeleteConfirmed, curGS );
|
||||
} else if ( 0 == strcmp(button, BUTTON_NAME ) ) {
|
||||
char playerName[32];
|
||||
getPlayerName( globals, playerName, sizeof(playerName)-1 );
|
||||
call_get_string( "Set your (local) player name", playerName,
|
||||
call_get_string( "Set your (local) player name", globals->playerName,
|
||||
onPlayerNamed, globals );
|
||||
}
|
||||
}
|
||||
|
@ -783,8 +770,9 @@ initDeviceGlobals( Globals* globals )
|
|||
static void
|
||||
storeCurOpen( GameState* gs )
|
||||
{
|
||||
dutil_storePtr( gs->globals->dutil, NULL, KEY_LAST_GID,
|
||||
&gs->gi.gameID, sizeof(gs->gi.gameID) );
|
||||
dutil_startStore( gs->globals->dutil, NULL, KEY_LAST_GID,
|
||||
&gs->gi.gameID, sizeof(gs->gi.gameID),
|
||||
NULL, NULL );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -830,11 +818,8 @@ newFromInvite( Globals* globals, const NetLaunchInfo* invite )
|
|||
gs->util = wasm_util_make( MPPARM(globals->mpool) &gs->gi,
|
||||
globals->dutil, gs );
|
||||
|
||||
char playerName[32];
|
||||
getPlayerName( globals, playerName, sizeof(playerName) );
|
||||
|
||||
game_makeFromInvite( MPPARM(globals->mpool) NULL, invite,
|
||||
&gs->game, &gs->gi, playerName,
|
||||
&gs->game, &gs->gi, globals->playerName,
|
||||
gs->util, globals->draw,
|
||||
&globals->cp, &globals->procs );
|
||||
if ( invite->gameName[0] ) {
|
||||
|
@ -1052,9 +1037,6 @@ loadAndDraw( Globals* globals, const NetLaunchInfo* invite,
|
|||
if ( !gs ) {
|
||||
DictionaryCtxt* dict = loadAnyDict( globals );
|
||||
if ( !!dict ) {
|
||||
char playerName[32];
|
||||
getPlayerName( globals, playerName, sizeof(playerName) );
|
||||
|
||||
gs = newGameState( globals );
|
||||
gs->gi.serverRole = !!params && !params->isRobotNotRemote
|
||||
? SERVER_ISSERVER : SERVER_STANDALONE;
|
||||
|
@ -1067,7 +1049,7 @@ loadAndDraw( Globals* globals, const NetLaunchInfo* invite,
|
|||
dict_getShortName(dict) );
|
||||
gs->gi.nPlayers = 2;
|
||||
gs->gi.boardSize = 15;
|
||||
gs->gi.players[0].name = copyString( globals->mpool, playerName );
|
||||
gs->gi.players[0].name = copyString( globals->mpool, globals->playerName );
|
||||
gs->gi.players[0].isLocal = XP_TRUE;
|
||||
gs->gi.players[0].robotIQ = 0;
|
||||
|
||||
|
@ -1562,6 +1544,44 @@ inviteFromArgv( Globals* globals, NetLaunchInfo* nlip,
|
|||
return success;
|
||||
}
|
||||
|
||||
typedef struct _GameStartState {
|
||||
Globals* globals;
|
||||
NetLaunchInfo nli;
|
||||
NetLaunchInfo* nlip;
|
||||
char lastKey[16];
|
||||
int nWanted;
|
||||
} GameStartState;
|
||||
|
||||
/* Will get called twice, once with KEY_PLAYER_NAME and once with KEY_LAST_GID */
|
||||
static void
|
||||
onReqsLoaded(void* closure, const char* key, void* data, int dataLen)
|
||||
{
|
||||
GameStartState* gss = (GameStartState*)closure;
|
||||
Globals* globals = gss->globals;
|
||||
XP_LOGFF( "(key: %s, len: %d)", key, dataLen );
|
||||
|
||||
if ( 0 == strcmp( key, KEY_LAST_GID ) ) {
|
||||
int gameID = 0;
|
||||
if ( !!data && dataLen == sizeof(gameID) ) {
|
||||
gameID = *(int*)data;
|
||||
formatGameID( gss->lastKey, sizeof(gss->lastKey), gameID );
|
||||
}
|
||||
XP_LOGFF( "loaded KEY_LAST_GID: %s", gss->lastKey );
|
||||
} else if ( 0 == strcmp( key, KEY_PLAYER_NAME ) ) {
|
||||
if ( !!data && 0 < dataLen && dataLen < VSIZE(globals->playerName) ) {
|
||||
XP_MEMCPY( globals->playerName, data, dataLen );
|
||||
} else {
|
||||
strcat( globals->playerName, "Player 1" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( 0 == --gss->nWanted ) {
|
||||
loadAndDraw( globals, gss->nlip, gss->lastKey, NULL );
|
||||
updateDeviceButtons( globals );
|
||||
XP_FREE( globals->mpool, gss );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
initNoReturn( int argc, const char** argv )
|
||||
{
|
||||
|
@ -1574,10 +1594,12 @@ initNoReturn( int argc, const char** argv )
|
|||
globals._GUARD = GUARD_GLOB;
|
||||
#endif
|
||||
|
||||
NetLaunchInfo nli = {0};
|
||||
NetLaunchInfo* nlip = NULL;
|
||||
if ( inviteFromArgv( &globals, &nli, argc, argv ) ) {
|
||||
nlip = &nli;
|
||||
/* I don't think this ever gets popped off stack, but to be safe.... */
|
||||
GameStartState* gss = XP_CALLOC( globals.mpool, sizeof(*gss) );
|
||||
gss->globals = &globals;
|
||||
|
||||
if ( inviteFromArgv( &globals, &gss->nli, argc, argv ) ) {
|
||||
gss->nlip = &gss->nli;
|
||||
}
|
||||
|
||||
SDL_Init( SDL_INIT_EVENTS );
|
||||
|
@ -1586,24 +1608,16 @@ initNoReturn( int argc, const char** argv )
|
|||
SDL_CreateWindowAndRenderer( WINDOW_WIDTH, WINDOW_HEIGHT, 0,
|
||||
&globals.window, &globals.renderer );
|
||||
|
||||
/* whip the canvas to background */
|
||||
/* wipe the canvas to background */
|
||||
SDL_SetRenderDrawColor( globals.renderer, 155, 155, 155, 255 );
|
||||
SDL_RenderClear( globals.renderer );
|
||||
|
||||
initDeviceGlobals( &globals );
|
||||
|
||||
char lastKey[16] = {0};
|
||||
int gameID = 0;
|
||||
XP_U32 len = sizeof(gameID);
|
||||
dutil_loadPtr( globals.dutil, NULL, KEY_LAST_GID, NULL,
|
||||
(XP_U8*)&gameID, &len );
|
||||
if ( len == sizeof(gameID) ) {
|
||||
formatGameID( lastKey, sizeof(lastKey), gameID );
|
||||
}
|
||||
XP_LOGFF( "loaded KEY_LAST_GID: %s", lastKey );
|
||||
loadAndDraw( &globals, nlip, lastKey, NULL );
|
||||
|
||||
updateDeviceButtons( &globals );
|
||||
/* Load the two bits we need from storage before starting */
|
||||
dutil_startLoad( globals.dutil, NULL, KEY_PLAYER_NAME, onReqsLoaded, gss );
|
||||
dutil_startLoad( globals.dutil, NULL, KEY_LAST_GID, onReqsLoaded, gss );
|
||||
gss->nWanted = 2;
|
||||
|
||||
emscripten_set_main_loop_arg( looper, &globals, -1, 1 );
|
||||
}
|
||||
|
|
|
@ -64,6 +64,8 @@ typedef struct Globals {
|
|||
CommonPrefs cp;
|
||||
DictMgrCtxt* dictMgr;
|
||||
|
||||
char playerName[32];
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
MemPoolCtx* mpool;
|
||||
#endif
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include "wasmasm.h"
|
||||
#include "wasmdict.h"
|
||||
|
||||
#define DB_NAME "kvstore0.1"
|
||||
|
||||
typedef struct _WasmDUtilCtxt {
|
||||
XW_DUtilCtxt super;
|
||||
} WasmDUtilCtxt;
|
||||
|
@ -283,6 +285,93 @@ wasm_dutil_storePtr( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
|
|||
XP_FREE( duc->mpool, out );
|
||||
}
|
||||
|
||||
typedef struct _StoreState {
|
||||
XW_DUtilCtxt* duc;
|
||||
OnStoreProc proc;
|
||||
void* closure;
|
||||
} StoreState;
|
||||
|
||||
static void
|
||||
callStoredAndFree( void* closure, bool success )
|
||||
{
|
||||
if ( !!closure ) {
|
||||
StoreState* ss = (StoreState*)closure;
|
||||
(*ss->proc)(ss->closure, success);
|
||||
XP_FREE( ss->duc->mpool, ss );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
onStoreSuccess( void* closure )
|
||||
{
|
||||
callStoredAndFree( closure, true );
|
||||
}
|
||||
|
||||
static void
|
||||
onStoreError( void* closure )
|
||||
{
|
||||
callStoredAndFree( closure, false );
|
||||
}
|
||||
|
||||
static void
|
||||
wasm_dutil_startStore( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
|
||||
const void* data, XP_U32 len, OnStoreProc proc, void* closure )
|
||||
{
|
||||
XP_LOGFF("(key: %s)", key);
|
||||
StoreState* ss = NULL;
|
||||
if ( !!proc ) {
|
||||
ss = XP_MALLOC( duc->mpool, sizeof(*ss) );
|
||||
ss->duc = duc;
|
||||
ss->proc = proc;
|
||||
ss->closure = closure;
|
||||
}
|
||||
|
||||
emscripten_idb_async_store( DB_NAME, key, (void*)data, len,
|
||||
ss, onStoreSuccess, onStoreError );
|
||||
}
|
||||
|
||||
typedef struct _LoadState {
|
||||
XW_DUtilCtxt* duc;
|
||||
OnLoadProc proc;
|
||||
void* closure;
|
||||
char* key;
|
||||
} LoadState;
|
||||
|
||||
static void
|
||||
callLoadedAndFree(void* closure, void* data, int len )
|
||||
{
|
||||
LoadState* ls = (LoadState*)closure;
|
||||
(*ls->proc)(ls->closure, ls->key, data, len );
|
||||
XP_FREE( ls->duc->mpool, (void*)ls->key );
|
||||
XP_FREE( ls->duc->mpool, ls );
|
||||
}
|
||||
|
||||
static void
|
||||
onLoadSuccess( void* closure, void* data, int len )
|
||||
{
|
||||
callLoadedAndFree( closure, data, len );
|
||||
}
|
||||
|
||||
static void
|
||||
onLoadError( void *closure )
|
||||
{
|
||||
callLoadedAndFree( closure, NULL, 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
wasm_dutil_startLoad( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
|
||||
OnLoadProc proc, void* closure )
|
||||
{
|
||||
LoadState* ls = XP_MALLOC( duc->mpool, sizeof(*ls) );
|
||||
ls->duc = duc;
|
||||
ls->proc = proc;
|
||||
ls->closure = closure;
|
||||
ls->key = NULL;
|
||||
replaceStringIfDifferent( duc->mpool, &ls->key, key );
|
||||
|
||||
emscripten_idb_async_load(DB_NAME, key, ls, onLoadSuccess, onLoadError);
|
||||
}
|
||||
|
||||
static void
|
||||
wasm_dutil_storeIndxStream( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
|
||||
const XP_UCHAR* indx, XWStreamCtxt* data )
|
||||
|
@ -533,6 +622,8 @@ wasm_dutil_make( MPFORMAL VTableMgr* vtMgr, void* closure )
|
|||
SET_PROC(getUserQuantityString);
|
||||
SET_PROC(storePtr);
|
||||
SET_PROC(loadPtr);
|
||||
SET_PROC(startStore);
|
||||
SET_PROC(startLoad);
|
||||
|
||||
#ifdef XWFEATURE_SMS
|
||||
SET_PROC(phoneNumbersSame);
|
||||
|
|
Loading…
Add table
Reference in a new issue