mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-14 20:47:54 +01:00
add generic timers (with dutil component for scheduling)
This commit is contained in:
parent
ad651c6cba
commit
f406757fb2
13 changed files with 324 additions and 58 deletions
|
@ -99,6 +99,7 @@ COMMON5 = \
|
|||
$(COMMONOBJDIR)/knownplyr.o \
|
||||
$(COMMONOBJDIR)/dllist.o \
|
||||
$(COMMONOBJDIR)/stats.o \
|
||||
$(COMMONOBJDIR)/timers.o \
|
||||
$(COMMONOBJDIR)/md5.o \
|
||||
|
||||
CJSON = \
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "strutils.h"
|
||||
#include "nli.h"
|
||||
#include "dbgutil.h"
|
||||
#include "timers.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
# define MAGIC_INITED 0x8283413F
|
||||
|
@ -1036,6 +1037,15 @@ dvc_getPhoniesFor( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR* code,
|
|||
dll_map( &pdc->head->links, getWordsProc, NULL, &gws );
|
||||
}
|
||||
|
||||
#ifdef DUTIL_TIMERS
|
||||
void
|
||||
dvc_onTimerFired( XW_DUtilCtxt* dutil, XWEnv xwe, TimerKey key )
|
||||
{
|
||||
XP_LOGFF( "(key: %d)", key );
|
||||
tmr_fired( dutil, xwe, key );
|
||||
}
|
||||
#endif
|
||||
|
||||
static ForEachAct
|
||||
findPhonyProc2( const DLHead* elem, void* closure )
|
||||
{
|
||||
|
|
|
@ -77,6 +77,10 @@ void dvc_getIsoCodes( XW_DUtilCtxt* dutil, XWEnv env, WordCollector proc,
|
|||
void dvc_getPhoniesFor( XW_DUtilCtxt* dutil, XWEnv env, const XP_UCHAR* code,
|
||||
WordCollector proc, void* closure );
|
||||
|
||||
#ifdef DUTIL_TIMERS
|
||||
void dvc_onTimerFired( XW_DUtilCtxt* dutil, XWEnv env, TimerKey key );
|
||||
#endif
|
||||
|
||||
/* All platforms need to call this shortly after setting up their XW_DUtilCtxt */
|
||||
void dvc_init( XW_DUtilCtxt* dutil, XWEnv xwe );
|
||||
void dvc_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe );
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "knownplyr.h"
|
||||
#include "device.h"
|
||||
#include "stats.h"
|
||||
#include "timers.h"
|
||||
|
||||
static void
|
||||
super_dutil_storeStream( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* keys[],
|
||||
|
@ -66,12 +67,14 @@ dutil_super_init( MPFORMAL XW_DUtilCtxt* dutil )
|
|||
SET_VTABLE_ENTRY( &dutil->vtable, dutil_loadStream, super );
|
||||
SET_VTABLE_ENTRY( &dutil->vtable, dutil_storeStream, super );
|
||||
|
||||
tmr_init( dutil );
|
||||
sts_init( dutil );
|
||||
}
|
||||
|
||||
void
|
||||
dutil_super_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe )
|
||||
{
|
||||
tmr_cleanup( dutil, xwe );
|
||||
kplr_cleanup( dutil );
|
||||
sts_cleanup( dutil, xwe );
|
||||
dvc_cleanup( dutil, xwe );
|
||||
|
|
|
@ -44,7 +44,7 @@ typedef struct _Md5SumBuf {
|
|||
#define KEY_WILDCARD "*"
|
||||
|
||||
#ifdef DUTIL_TIMERS
|
||||
typedef void (*DUtilTimerProc)( XWEnv xwe, void* closure, size_t closureSize );
|
||||
typedef XP_U32 TimerKey;
|
||||
#endif
|
||||
typedef struct _DUtilVtable {
|
||||
XP_U32 (*m_dutil_getCurSeconds)( XW_DUtilCtxt* duc, XWEnv xwe );
|
||||
|
@ -84,9 +84,8 @@ typedef struct _DUtilVtable {
|
|||
#endif
|
||||
|
||||
#ifdef DUTIL_TIMERS
|
||||
void (*m_dutil_setTimer)( XW_DUtilCtxt* duc, XWEnv xwe, XP_U16 when, DUtilTimerProc proc,
|
||||
void* closure, size_t closureSize );
|
||||
void (*m_dutil_clearTimer)( XW_DUtilCtxt* duc, XWEnv xwe, DUtilTimerProc proc );
|
||||
void (*m_dutil_setTimer)( XW_DUtilCtxt* duc, XWEnv xwe, XP_U32 when, TimerKey key );
|
||||
void (*m_dutil_clearTimer)( XW_DUtilCtxt* duc, XWEnv xwe, TimerKey key );
|
||||
#endif
|
||||
void (*m_dutil_md5sum)( XW_DUtilCtxt* duc, XWEnv xwe, const XP_U8* ptr,
|
||||
XP_U32 len, Md5SumBuf* sb );
|
||||
|
@ -118,6 +117,7 @@ struct XW_DUtilCtxt {
|
|||
void* closure;
|
||||
void* devCtxt; /* owned by device.c */
|
||||
void* statsState; /* owned by stats.c */
|
||||
void* timersState; /* owned by timers.c */
|
||||
#ifdef XWFEATURE_KNOWNPLAYERS /* owned by knownplyr.c */
|
||||
void* kpCtxt;
|
||||
pthread_mutex_t kpMutex;
|
||||
|
@ -168,10 +168,10 @@ void dutil_super_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe );
|
|||
#endif
|
||||
|
||||
#ifdef DUTIL_TIMERS
|
||||
# define dutil_setTimer( duc, xwe, when, proc, closure, siz ) \
|
||||
(duc)->vtable.m_dutil_setTimer((duc), (xwe), (when), (proc), (closure), (siz))
|
||||
# define dutil_clearTimer( duc, xwe, proc ) \
|
||||
(duc)->vtable.m_dutil_clearTimer((duc), (xwe), (proc) )
|
||||
# define dutil_setTimer( duc, xwe, when, key ) \
|
||||
(duc)->vtable.m_dutil_setTimer((duc), (xwe), (when), (key))
|
||||
# define dutil_clearTimer( duc, xwe, key ) \
|
||||
(duc)->vtable.m_dutil_clearTimer((duc), (xwe), (key) )
|
||||
#endif
|
||||
|
||||
# define dutil_md5sum( duc, e, p, l, b ) \
|
||||
|
|
|
@ -306,14 +306,16 @@ mpool_free( MemPoolCtx* mpool, void* ptr, const char* file,
|
|||
MemPoolEntry* entry = findEntryFor( mpool, ptr, &prev );
|
||||
|
||||
if ( !entry ) {
|
||||
XP_LOGFF( "findEntryFor failed; pool %p, line %d in %s", mpool, lineNo, file );
|
||||
XP_LOGFF( "findEntryFor failed; pool %p, line %d in %s", mpool,
|
||||
lineNo, file );
|
||||
XP_ASSERT( 0 );
|
||||
} else {
|
||||
|
||||
#ifdef MPOOL_DEBUG
|
||||
XP_LOGFF( "(ptr=%p):size=%d,index=%d,func=%s,file=%s,lineNo=%d); called from %s",
|
||||
entry->ptr, entry->size, entry->index, entry->func, entry->fileName,
|
||||
entry->lineNo, func );
|
||||
XP_LOGFF( "(ptr=%p):size=%d,index=%d,func=%s,file=%s,lineNo=%d); "
|
||||
"called from %s",
|
||||
entry->ptr, entry->size, entry->index, entry->func,
|
||||
entry->fileName, entry->lineNo, func );
|
||||
#else
|
||||
XP_USE(func); /* shut up, compiler */
|
||||
#endif
|
||||
|
|
|
@ -22,15 +22,19 @@
|
|||
#include "device.h"
|
||||
#include "xwstream.h"
|
||||
#include "strutils.h"
|
||||
#include "dbgutil.h"
|
||||
#include "timers.h"
|
||||
|
||||
typedef struct StatsState {
|
||||
XP_U32* statsVals;
|
||||
MutexState mutex;
|
||||
XP_Bool timerSet;
|
||||
} StatsState;
|
||||
|
||||
static const XP_UCHAR* STATtoStr(STAT stat);
|
||||
static XP_U32* loadCounts( XW_DUtilCtxt* dutil, XWEnv xwe );
|
||||
static void storeCounts( XW_DUtilCtxt* dutil, XWEnv xwe );
|
||||
static void setStoreTimer( XW_DUtilCtxt* dutil, XWEnv xwe );
|
||||
|
||||
void
|
||||
sts_init( XW_DUtilCtxt* dutil )
|
||||
|
@ -41,10 +45,9 @@ sts_init( XW_DUtilCtxt* dutil )
|
|||
}
|
||||
|
||||
void
|
||||
sts_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe )
|
||||
sts_cleanup( XW_DUtilCtxt* dutil, XWEnv XP_UNUSED(xwe) )
|
||||
{
|
||||
StatsState* ss = dutil->statsState;
|
||||
storeCounts( dutil, xwe );
|
||||
XP_ASSERT( !!ss );
|
||||
XP_FREEP( dutil->mpool, &ss->statsVals );
|
||||
XP_FREEP( dutil->mpool, &ss );
|
||||
|
@ -62,8 +65,7 @@ sts_increment( XW_DUtilCtxt* dutil, XWEnv xwe, STAT stat )
|
|||
}
|
||||
++ss->statsVals[stat];
|
||||
|
||||
XP_LOGFF( "bad: storing after every change" );
|
||||
storeCounts( dutil, xwe );
|
||||
setStoreTimer( dutil, xwe );
|
||||
END_WITH_MUTEX();
|
||||
}
|
||||
}
|
||||
|
@ -83,20 +85,13 @@ sts_export( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|||
XP_U32 val = ss->statsVals[ii];
|
||||
if ( 0 != val ) {
|
||||
const XP_UCHAR* nam = STATtoStr(ii);
|
||||
cJSON_AddNumberToObject(result, nam, val);
|
||||
cJSON_AddNumberToObject( result, nam, val );
|
||||
}
|
||||
}
|
||||
END_WITH_MUTEX();
|
||||
return result;
|
||||
}
|
||||
|
||||
/* void */
|
||||
/* sts_increment( XW_DUtilCtxt* dutil, XWEnv XP_UNUSED(xwe), STS_KEY key ) */
|
||||
/* { */
|
||||
/* StatsState* ss = dutil->statsState; */
|
||||
/* ++ss->stats[key]; */
|
||||
/* } */
|
||||
|
||||
void
|
||||
sts_clearAll( XW_DUtilCtxt* dutil, XWEnv xwe )
|
||||
{
|
||||
|
@ -108,9 +103,8 @@ sts_clearAll( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|||
|
||||
ss->statsVals
|
||||
= XP_CALLOC( dutil->mpool, sizeof(*ss->statsVals) * STAT_NSTATS );
|
||||
END_WITH_MUTEX();
|
||||
|
||||
storeCounts( dutil, xwe );
|
||||
END_WITH_MUTEX();
|
||||
}
|
||||
|
||||
static const XP_UCHAR*
|
||||
|
@ -146,7 +140,6 @@ storeCounts( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|||
XWStreamCtxt* stream = mkStream( dutil );
|
||||
stream_putU8( stream, 0 ); /* version */
|
||||
|
||||
WITH_MUTEX( &ss->mutex );
|
||||
if ( !!ss->statsVals ) {
|
||||
for ( int ii = 0; ii < STAT_NSTATS; ++ii ) {
|
||||
XP_U32 val = ss->statsVals[ii];
|
||||
|
@ -156,7 +149,6 @@ storeCounts( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|||
}
|
||||
}
|
||||
}
|
||||
END_WITH_MUTEX();
|
||||
|
||||
const XP_UCHAR* keys[] = { STATS_KEY, NULL };
|
||||
dutil_storeStream( dutil, xwe, keys, stream );
|
||||
|
@ -184,3 +176,38 @@ loadCounts( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|||
stream_destroy( stream );
|
||||
return statsVals;
|
||||
}
|
||||
|
||||
#ifdef DUTIL_TIMERS
|
||||
static void
|
||||
onStoreTimer( void* closure, XWEnv xwe, XP_Bool fired )
|
||||
{
|
||||
XP_LOGFF( "(fired: %s)", boolToStr(fired) );
|
||||
XW_DUtilCtxt* dutil = (XW_DUtilCtxt*)closure;
|
||||
StatsState* ss = dutil->statsState;
|
||||
XP_ASSERT( !!ss );
|
||||
|
||||
WITH_MUTEX( &ss->mutex );
|
||||
storeCounts( dutil, xwe );
|
||||
ss->timerSet = XP_FALSE;
|
||||
END_WITH_MUTEX();
|
||||
LOG_RETURN_VOID();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
setStoreTimer( XW_DUtilCtxt* dutil, XWEnv xwe )
|
||||
{
|
||||
#ifdef DUTIL_TIMERS
|
||||
StatsState* ss = dutil->statsState;
|
||||
XP_ASSERT( !!ss );
|
||||
if ( !ss->timerSet ) {
|
||||
ss->timerSet = XP_TRUE;
|
||||
XP_U32 inWhenMS = 5 * 1000;
|
||||
TimerKey key = tmr_set( dutil, xwe, inWhenMS, onStoreTimer, dutil );
|
||||
XP_LOGFF( "tmr_set() => %d", key );
|
||||
}
|
||||
#else
|
||||
XP_USE(dutil);
|
||||
XP_USE(xwe);
|
||||
#endif
|
||||
}
|
||||
|
|
166
xwords4/common/timers.c
Normal file
166
xwords4/common/timers.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
||||
/*
|
||||
* Copyright 2024 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "timers.h"
|
||||
#include "xwmutex.h"
|
||||
#include "dllist.h"
|
||||
|
||||
#ifdef DUTIL_TIMERS
|
||||
typedef struct _TimerState {
|
||||
DLHead links;
|
||||
TimerProc proc;
|
||||
void* closure;
|
||||
TimerKey key;
|
||||
XP_U32 inWhen;
|
||||
} TimerState;
|
||||
|
||||
typedef struct _TimerMgrState {
|
||||
XW_DUtilCtxt* dutil;
|
||||
MutexState mutex;
|
||||
XP_U32 nextKey;
|
||||
TimerState* timers;
|
||||
} TimerMgrState;
|
||||
|
||||
static void clearPendings( XW_DUtilCtxt* dutil, XWEnv xwe );
|
||||
|
||||
void
|
||||
tmr_init( XW_DUtilCtxt* dutil )
|
||||
{
|
||||
LOG_FUNC();
|
||||
XP_ASSERT( !dutil->timersState );
|
||||
TimerMgrState* tms = XP_CALLOC( dutil->mpool, sizeof(*tms) );
|
||||
tms->dutil = dutil;
|
||||
dutil->timersState = tms;
|
||||
initMutex( &tms->mutex, XP_TRUE );
|
||||
}
|
||||
|
||||
void
|
||||
tmr_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe )
|
||||
{
|
||||
TimerMgrState* timersState = (TimerMgrState*)dutil->timersState;
|
||||
XP_ASSERT( !!timersState );
|
||||
clearPendings( dutil, xwe );
|
||||
XP_FREEP( dutil->mpool, &dutil->timersState );
|
||||
}
|
||||
|
||||
TimerKey
|
||||
tmr_set( XW_DUtilCtxt* dutil, XWEnv xwe, XP_U32 inWhen,
|
||||
TimerProc proc, void* closure )
|
||||
{
|
||||
TimerKey key;
|
||||
TimerMgrState* timersState = (TimerMgrState*)dutil->timersState;
|
||||
XP_ASSERT( !!timersState );
|
||||
|
||||
TimerState* ts = XP_CALLOC( dutil->mpool, sizeof(*ts) );
|
||||
XP_LOGFF( "allocated timer %p", ts );
|
||||
ts->proc = proc;
|
||||
ts->closure = closure;
|
||||
ts->inWhen = inWhen;
|
||||
|
||||
WITH_MUTEX( &timersState->mutex );
|
||||
key = ts->key = ++timersState->nextKey;
|
||||
timersState->timers = (TimerState*)
|
||||
dll_insert( &timersState->timers->links, &ts->links, NULL );
|
||||
END_WITH_MUTEX();
|
||||
|
||||
dutil_setTimer( dutil, xwe, inWhen, ts->key );
|
||||
return key;
|
||||
}
|
||||
|
||||
static void
|
||||
timerFired( XW_DUtilCtxt* dutil, XWEnv xwe, TimerState* timer, XP_Bool fired )
|
||||
{
|
||||
XP_LOGFF( "(timer=%p); key=%d", timer, timer->key );
|
||||
(*timer->proc)( timer->closure, xwe, fired );
|
||||
XP_FREE( dutil->mpool, timer );
|
||||
}
|
||||
|
||||
typedef struct _FindByKeyState {
|
||||
TimerKey key;
|
||||
TimerState* found;
|
||||
} FindByKeyState;
|
||||
|
||||
static ForEachAct
|
||||
findByKeyProc( const DLHead* elem, void* closure )
|
||||
{
|
||||
ForEachAct result = FEA_OK;
|
||||
FindByKeyState* fbksp = (FindByKeyState*)closure;
|
||||
TimerState* ts = (TimerState*)elem;
|
||||
if ( ts->key == fbksp->key ) {
|
||||
fbksp->found = ts;
|
||||
result = FEA_REMOVE | FEA_EXIT;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
tmr_fired( XW_DUtilCtxt* dutil, XWEnv xwe, TimerKey key )
|
||||
{
|
||||
XP_LOGFF( "(key=%d)", key );
|
||||
TimerMgrState* timersState = (TimerMgrState*)dutil->timersState;
|
||||
XP_ASSERT( !!timersState );
|
||||
|
||||
FindByKeyState fbks = { .key = key };
|
||||
|
||||
WITH_MUTEX( &timersState->mutex );
|
||||
timersState->timers = (TimerState*)
|
||||
dll_map( &timersState->timers->links, findByKeyProc, NULL, &fbks );
|
||||
END_WITH_MUTEX();
|
||||
|
||||
if ( !!fbks.found ) {
|
||||
timerFired( dutil, xwe, fbks.found, XP_TRUE );
|
||||
} else {
|
||||
XP_LOGFF( "no timer found for key %d", key );
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _FireAndDisposeState {
|
||||
XW_DUtilCtxt* dutil;
|
||||
XWEnv xwe;
|
||||
} FireAndDisposeState;
|
||||
|
||||
static void
|
||||
fireAndDispose( DLHead* elem, void* closure )
|
||||
{
|
||||
TimerState* ts = (TimerState*)elem;
|
||||
FireAndDisposeState* fadsp = (FireAndDisposeState*)closure;
|
||||
dutil_clearTimer( fadsp->dutil, fadsp->xwe, ts->key );
|
||||
timerFired( fadsp->dutil, fadsp->xwe, ts, XP_FALSE ); /* disposes ts */
|
||||
}
|
||||
|
||||
static void
|
||||
clearPendings( XW_DUtilCtxt* dutil, XWEnv xwe )
|
||||
{
|
||||
TimerMgrState* timersState = (TimerMgrState*)dutil->timersState;
|
||||
TimerState* timers;
|
||||
|
||||
/* Grab the list so we can run over it without a mutex */
|
||||
WITH_MUTEX( &timersState->mutex );
|
||||
timers = timersState->timers;
|
||||
timersState->timers = NULL;
|
||||
END_WITH_MUTEX();
|
||||
|
||||
FireAndDisposeState fads = {
|
||||
.xwe = xwe,
|
||||
.dutil = dutil,
|
||||
};
|
||||
dll_removeAll( &timers->links, fireAndDispose, &fads );
|
||||
}
|
||||
|
||||
#endif
|
40
xwords4/common/timers.h
Normal file
40
xwords4/common/timers.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
||||
/*
|
||||
* Copyright 2024 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _TIMERS_H_
|
||||
#define _TIMERS_H_
|
||||
|
||||
# ifdef DUTIL_TIMERS
|
||||
|
||||
# include "dutil.h"
|
||||
|
||||
void tmr_init( XW_DUtilCtxt* dutil );
|
||||
void tmr_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe );
|
||||
|
||||
/* Pass false for fired if we're clearing unfired timers, e.g. on shutdown */
|
||||
typedef void (*TimerProc)(void* closure, XWEnv xwe, XP_Bool fired);
|
||||
TimerKey tmr_set( XW_DUtilCtxt* dutil, XWEnv xwe, XP_U32 inWhenMS,
|
||||
TimerProc proc, void* closure );
|
||||
void tmr_fired( XW_DUtilCtxt* dutil, XWEnv xwe, TimerKey key );
|
||||
|
||||
# else
|
||||
# define tmr_init( dutil )
|
||||
# define tmr_cleanup( dutil, xwe )
|
||||
# endif
|
||||
#endif
|
|
@ -33,4 +33,14 @@ initMutex( MutexState* mutex, XP_Bool recursive )
|
|||
pthread_mutex_init( &mutex->mutex, &attr );
|
||||
ret = pthread_mutexattr_destroy(&attr);
|
||||
XP_ASSERT(0 == ret);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* if ( recursive ) { */
|
||||
/* XP_LOGFF( "testing recursive call..." ); */
|
||||
/* WITH_MUTEX( mutex ); */
|
||||
/* WITH_MUTEX( mutex ); */
|
||||
/* END_WITH_MUTEX(); */
|
||||
/* END_WITH_MUTEX(); */
|
||||
/* } */
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -28,10 +28,18 @@ typedef struct _MutexState {
|
|||
pthread_mutex_t mutex;
|
||||
} MutexState;
|
||||
|
||||
#if 0
|
||||
# define MUTEX_LOG(...) XP_LOGFF(__VA_ARGS__)
|
||||
#else
|
||||
# define MUTEX_LOG(...)
|
||||
#endif
|
||||
|
||||
#define WITH_MUTEX_LOCK_DEBUG(STATEP) { \
|
||||
MutexState* _state = (STATEP); \
|
||||
time_t startTime = time(NULL); \
|
||||
MUTEX_LOG( "blocking for mutex %p", _state ); \
|
||||
pthread_mutex_lock(&_state->mutex); \
|
||||
MUTEX_LOG( "got mutex %p", _state ); \
|
||||
time_t gotItTime = time(NULL); \
|
||||
time_t _elapsed = gotItTime-startTime; \
|
||||
if ( 0 < _elapsed ) { \
|
||||
|
@ -45,6 +53,7 @@ typedef struct _MutexState {
|
|||
XP_LOGFF("held mutex for %lds", _elapsed); \
|
||||
} \
|
||||
pthread_mutex_unlock(&_state->mutex); \
|
||||
MUTEX_LOG( "released mutex %p", _state ); \
|
||||
} \
|
||||
|
||||
#define WITH_MUTEX_LOCK_RELEASE(COMMS) { \
|
||||
|
|
|
@ -315,11 +315,11 @@ linux_dutil_getRegValues( XW_DUtilCtxt* duc, XWEnv xwe )
|
|||
return results;
|
||||
}
|
||||
|
||||
#ifdef DUTIL_TIMERS
|
||||
|
||||
typedef struct _TimerClosure {
|
||||
XW_DUtilCtxt* duc;
|
||||
DUtilTimerProc proc;
|
||||
void* closure;
|
||||
size_t closureSize;
|
||||
TimerKey key;
|
||||
guint src;
|
||||
} TimerClosure;
|
||||
|
||||
|
@ -327,35 +327,23 @@ static gint
|
|||
timer_proc( gpointer data )
|
||||
{
|
||||
TimerClosure* tc = (TimerClosure*)data;
|
||||
XP_LOGFF( "calling timer proc" );
|
||||
(*tc->proc)( NULL_XWE, tc->closure, tc->closureSize );
|
||||
XP_LOGFF( "timer proc done" );
|
||||
XP_FREEP( tc->duc->mpool, &tc->closure );
|
||||
|
||||
LinDUtilCtxt* lduc = (LinDUtilCtxt*)tc->duc;
|
||||
GSList** timers = &lduc->timers;
|
||||
*timers = g_slist_remove( *timers, tc );
|
||||
|
||||
XP_LOGFF( "after firing, length %d", g_slist_length(*timers) );
|
||||
|
||||
XP_FREEP( tc->duc->mpool, &tc );
|
||||
return 0;
|
||||
XP_LOGFF( "calling dvc_onTimerFired()" );
|
||||
dvc_onTimerFired( tc->duc, NULL_XWE, tc->key );
|
||||
g_free( tc );
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
#ifdef DUTIL_TIMERS
|
||||
static void
|
||||
linux_dutil_setTimer( XW_DUtilCtxt* duc, XWEnv xwe, XP_U16 when,
|
||||
DUtilTimerProc proc, void* closure, size_t closureSize )
|
||||
linux_dutil_setTimer( XW_DUtilCtxt* duc, XWEnv xwe, XP_U32 inWhenMS, TimerKey key )
|
||||
{
|
||||
XP_USE(xwe); /* I assume I'll need this on the Android side */
|
||||
|
||||
TimerClosure* tc = XP_MALLOC(duc->mpool, sizeof(*tc));
|
||||
TimerClosure* tc = g_malloc(sizeof(*tc));
|
||||
tc->duc = duc;
|
||||
tc->closureSize = closureSize;
|
||||
tc->closure = XP_MALLOC( duc->mpool, closureSize );
|
||||
XP_MEMCPY( tc->closure, closure, closureSize );
|
||||
tc->proc = proc;
|
||||
tc->src = g_timeout_add( when, timer_proc, tc );
|
||||
tc->key = key;
|
||||
|
||||
XP_LOGFF( "key: %d, inWhenMS: %d", key, inWhenMS );
|
||||
tc->src = g_timeout_add( inWhenMS, timer_proc, tc );
|
||||
|
||||
LinDUtilCtxt* lduc = (LinDUtilCtxt*)duc;
|
||||
GSList** timers = &lduc->timers;
|
||||
|
@ -365,14 +353,15 @@ linux_dutil_setTimer( XW_DUtilCtxt* duc, XWEnv xwe, XP_U16 when,
|
|||
}
|
||||
|
||||
static gint
|
||||
findByProc( gconstpointer elemData, gconstpointer proc )
|
||||
findByProc( gconstpointer elemData, gconstpointer keyp )
|
||||
{
|
||||
TimerClosure* tc = (TimerClosure*)elemData;
|
||||
return tc->proc == proc ? 0 : 1;
|
||||
TimerKey* key = (TimerKey*)keyp;
|
||||
return tc->key == *key ? 0 : 1; /* return 0 on success */
|
||||
}
|
||||
|
||||
static void
|
||||
linux_dutil_clearTimer( XW_DUtilCtxt* duc, XWEnv xwe, DUtilTimerProc proc )
|
||||
linux_dutil_clearTimer( XW_DUtilCtxt* duc, XWEnv xwe, TimerKey key )
|
||||
{
|
||||
/* Will probably want to store the TimerClosure instances above in a list
|
||||
that can be searched here for its proc value, then its src field used
|
||||
|
@ -384,11 +373,15 @@ linux_dutil_clearTimer( XW_DUtilCtxt* duc, XWEnv xwe, DUtilTimerProc proc )
|
|||
LinDUtilCtxt* lduc = (LinDUtilCtxt*)duc;
|
||||
GSList** timers = &lduc->timers;
|
||||
while ( !!*timers ) {
|
||||
GSList* elem = g_slist_find_custom( *timers, proc, findByProc );
|
||||
GSList* elem = g_slist_find_custom( *timers, &key, findByProc );
|
||||
if ( !elem ) {
|
||||
break;
|
||||
}
|
||||
TimerClosure* tc = (TimerClosure*)elem->data;
|
||||
*timers = g_slist_remove( *timers, elem );
|
||||
|
||||
g_source_remove( tc->src );
|
||||
g_free( tc );
|
||||
++count;
|
||||
}
|
||||
XP_LOGFF( "removed %d timers", count );
|
||||
|
|
|
@ -399,7 +399,8 @@ mqttc_cleanup( LaunchParams* params )
|
|||
storage->mosq = NULL;
|
||||
mosquitto_lib_cleanup();
|
||||
|
||||
XP_LOGFF( "quitting with %d undelievered messages", g_slist_length(storage->queue) );
|
||||
XP_LOGFF( "quitting with %d undelivered messages",
|
||||
g_slist_length(storage->queue) );
|
||||
|
||||
XP_ASSERT( params->mqttConStorage == storage ); /* cheat */
|
||||
XP_FREEP( params->mpool, &storage );
|
||||
|
|
Loading…
Add table
Reference in a new issue