Modified RM_CreateTimer to prevent more that one function being posted at a time

Former-commit-id: f66e5a9c3d6925c3c6d383fbc43fbfbd56721dad
This commit is contained in:
VivekSainiEQ 2021-01-14 21:59:56 +00:00 committed by John Sully
parent cf122aa54d
commit b0f94bd4b5

View File

@ -5579,8 +5579,10 @@ void RM_SetClusterFlags(RedisModuleCtx *ctx, uint64_t flags) {
static rax *Timers; /* The radix tree of all the timers sorted by expire. */ static rax *Timers; /* The radix tree of all the timers sorted by expire. */
long long aeTimer = -1; /* Main event loop (ae.c) timer identifier. */ long long aeTimer = -1; /* Main event loop (ae.c) timer identifier. */
bool aeTimerSet = false;/* Checks whether the main event loop timer is set static bool aeTimerSet = false; /* Checks whether the main event loop timer is set */
or if an aePostFunction is queued up that will set it */ static mstime_t aeTimerPeriod; /* The period of the aeTimer */
static bool aeTimerPending = false; /* Keeps track of if there is a aePostFunction in flight
* that would modify the current main event loop timer */
typedef void (*RedisModuleTimerProc)(RedisModuleCtx *ctx, void *data); typedef void (*RedisModuleTimerProc)(RedisModuleCtx *ctx, void *data);
@ -5669,13 +5671,12 @@ RedisModuleTimerID RM_CreateTimer(RedisModuleCtx *ctx, mstime_t period, RedisMod
expiretime++; expiretime++;
} }
} }
/* We need to install the main event loop timer if it's not already /* We need to install the main event loop timer if it's not already
* installed, or we may need to refresh its period if we just installed * installed, or we may need to refresh its period if we just installed
* a timer that will expire sooner than any other else (i.e. the timer * a timer that will expire sooner than any other else (i.e. the timer
* we just installed is the first timer in the Timers rax). */ * we just installed is the first timer in the Timers rax). */
bool isFirstExpiry = false; bool isFirstExpiry = false;
if (raxSize(Timers) > 0){ if (aeTimerSet){
raxIterator ri; raxIterator ri;
raxStart(&ri, Timers); raxStart(&ri, Timers);
raxSeek(&ri,"^",NULL,0); raxSeek(&ri,"^",NULL,0);
@ -5688,20 +5689,31 @@ RedisModuleTimerID RM_CreateTimer(RedisModuleCtx *ctx, mstime_t period, RedisMod
} }
/* Now that either we know that we either need to refresh the period of the /* Now that either we know that we either need to refresh the period of the
* recently installed timer, or that there is no timer to begin with, we must post * recently installed timer, or that there is no timer to begin with, we must post
* a function call to install the main event timer */ * a function call to install the main event timer. */
if (isFirstExpiry || !aeTimerSet){ if (isFirstExpiry || !aeTimerSet){
/* We set the period for the posted function in a global variable
* That is so if a function has been posted but not executed, and another
* function with a different period were to be posted, we can just update
* the period instead of posting a new function. */
aeTimerPeriod = period;
aeTimerSet = true; aeTimerSet = true;
aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, [period, isFirstExpiry]{ if (!aeTimerPending) {
/* If we deemed that this timer required a reinstall, delete it before proceeding /* We should only have one aePostFunction in flight at a time, aeTimerPending
* to the install */ * keeps track of that. */
if (isFirstExpiry) aeTimerPending = true;
aeDeleteTimeEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el,aeTimer); aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, [isFirstExpiry]{
/* If we have no main timer (the old one was invalidated, or this is the /* If we deemed that this timer required a reinstall, delete it before proceeding
* first module timer we have), install one. */ * to the install */
aeTimer = aeCreateTimeEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el,period,moduleTimerHandler,NULL,NULL); if (isFirstExpiry)
}); aeDeleteTimeEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el,aeTimer);
} /* If we have no main timer (the old one was invalidated, or this is the
* first module timer we have), install one. */
aeTimer = aeCreateTimeEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el,aeTimerPeriod,moduleTimerHandler,NULL,NULL);
aeTimerPending = false;
});
}
}
return key; return key;
} }