MCPcopy Create free account
hub / github.com/Snapchat/KeyDB / RM_CreateTimer

Function RM_CreateTimer

src/module.cpp:6509–6568  ·  view source on GitHub ↗

Create a new timer that will fire after `period` milliseconds, and will call * the specified function using `data` as argument. The returned timer ID can be * used to get information from the timer or to stop it before it fires. * Note that for the common use case of a repeating timer (Re-registration * of the timer inside the RedisModuleTimerProc callback) it matters when * this API is calle

Source from the content-addressed store, hash-verified

6507 * (If the time it takes to execute 'callback' is negligible the two
6508 * statements above mean the same) */
6509RedisModuleTimerID RM_CreateTimer(RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data) {
6510 static uint64_t pending_key;
6511 static mstime_t pending_period = -1;
6512
6513 RedisModuleTimer *timer = (RedisModuleTimer*)zmalloc(sizeof(*timer), MALLOC_LOCAL);
6514 timer->module = ctx->module;
6515 timer->callback = callback;
6516 timer->data = data;
6517 timer->dbid = ctx->client ? ctx->client->db->id : 0;
6518 uint64_t expiretime = ustime()+period*1000;
6519 uint64_t key;
6520
6521 while(1) {
6522 key = htonu64(expiretime);
6523 if (raxFind(Timers, (unsigned char*)&key,sizeof(key)) == raxNotFound) {
6524 raxInsert(Timers,(unsigned char*)&key,sizeof(key),timer,NULL);
6525 break;
6526 } else {
6527 expiretime++;
6528 }
6529 }
6530
6531 bool fNeedPost = (pending_period < 0); // If pending_period is already set, then a PostFunction is in flight and we don't need to set a new one
6532 if (pending_period < 0 || period < pending_period) {
6533 pending_period = period;
6534 pending_key = key;
6535 }
6536
6537 /* We need to install the main event loop timer if it's not already
6538 * installed, or we may need to refresh its period if we just installed
6539 * a timer that will expire sooner than any other else (i.e. the timer
6540 * we just installed is the first timer in the Timers rax). */
6541 if (fNeedPost) {
6542 aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, []{
6543 if (aeTimer != -1) {
6544 raxIterator ri;
6545 raxStart(&ri,Timers);
6546 raxSeek(&ri,"^",NULL,0);
6547 raxNext(&ri);
6548 if (memcmp(ri.key,&pending_key,sizeof(key)) == 0) {
6549 /* This is the first key, we need to re-install the timer according
6550 * to the just added event. */
6551 aeDeleteTimeEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el,aeTimer);
6552 aeTimer = -1;
6553 }
6554 raxStop(&ri);
6555 }
6556
6557 /* If we have no main timer (the old one was invalidated, or this is the
6558 * first module timer we have), install one. */
6559 if (aeTimer == -1) {
6560 aeTimer = aeCreateTimeEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el,pending_period,moduleTimerHandler,NULL,NULL);
6561 }
6562
6563 pending_period = -1;
6564 });
6565 }
6566

Callers

nothing calls this directly

Calls 11

zmallocFunction · 0.85
raxFindFunction · 0.85
raxInsertFunction · 0.85
aePostFunctionFunction · 0.85
raxStartFunction · 0.85
raxSeekFunction · 0.85
raxNextFunction · 0.85
aeDeleteTimeEventFunction · 0.85
raxStopFunction · 0.85
aeCreateTimeEventFunction · 0.85
ustimeFunction · 0.70

Tested by

no test coverage detected