mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-15 08:47:56 +01:00
167 lines
4.5 KiB
C
167 lines
4.5 KiB
C
/* -*-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;
|
|
MUTEX_INIT( &tms->mutex, XP_TRUE );
|
|
}
|
|
|
|
void
|
|
tmr_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|
{
|
|
TimerMgrState* timersState = (TimerMgrState*)dutil->timersState;
|
|
XP_ASSERT( !!timersState );
|
|
clearPendings( dutil, xwe );
|
|
MUTEX_DESTROY( &timersState->mutex );
|
|
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* XP_UNUSED_DBG(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 )
|
|
{
|
|
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
|