The Redis timer is self-fulfilling, not very complex. Let's talk about concrete implementation.
The storage and maintenance of the timer is a common one-way linked list structure, the specific node is defined as:
1 /*Time Timer structure Body*/2typedefstructaetimeevent3 {4 Long LongId/*the number of the timer*/5 LongWhen_sec;/*seconds*/6 LongWhen_ms;/*milliseconds*/7Aetimeproc *timeproc;/*time arrives processing function*/8Aeeventfinalizerproc *finalizerproc;/*Remove cleanup function*/9 void*clientdata;/*Out-of- band data*/Ten structAetimeevent *next;/*The storage of timers is linked to the list structure*/ One} aetimeevent;
The location of the root node of the timer record is in the event manager, and the rest is the normal operation function.
1 /*Add timer events, parameters are time controller, timing time, processing function, function parameter, cleanup function*/2 Long LongAecreatetimeevent (Aeeventloop *eventloop,Long Longmilliseconds,3Aetimeproc *proc,void*Clientdata,4Aeeventfinalizerproc *Finalizerproc)5 {6 /*Build ID*/7 Long Longid = eventloop->timeeventnextid++;8Aetimeevent *te;9 TenTe = Zmalloc (sizeof(*te)); One if(Te = = NULL)returnAe_err; ATe->id =ID; - /*Adjust Time*/ -Aeaddmillisecondstonow (milliseconds,&te->when_sec,&te->When_ms); theTe->timeproc =proc; -Te->finalizerproc =Finalizerproc; -Te->clientdata =Clientdata; - /*Join the time list, all the time nodes are inserted in the head, no order*/ +Te->next = eventloop->Timeeventhead; -Eventloop->timeeventhead =te; + returnID; A}
1 /*Delete the time node, provide the ID of the point in time, and return an error if not found*/2 intAedeletetimeevent (Aeeventloop *eventloop,Long LongID)3 {4Aetimeevent *te, *prev =NULL;5 6Te = eventloop->Timeeventhead;7 /*loops through a node, calls a cleanup function, and frees memory*/8 while(TE)9 {Ten if(Te->id = =ID) One { A if(prev = =NULL) -Eventloop->timeeventhead = te->Next; - Else thePrev->next = te->Next; - if(te->Finalizerproc) -Te->finalizerproc (EventLoop, te->clientdata); - zfree (TE); + returnAe_ok; - } +Prev =te; ATe = te->Next; at } - returnAe_err;/*NO event with the specified ID found*/ -}
1 /*Find the node with the shortest activation time*/2 StaticAetimeevent *aesearchnearesttimer (Aeeventloop *EventLoop)3 {4Aetimeevent *te = eventloop->Timeeventhead;5Aetimeevent *nearest =NULL;6 7 while(TE)8 {9 if(!nearest | | te->when_sec < NEAREST->WHEN_SEC | | (te->when_sec = = Nearest->when_sec && Te->when_ms < nearest->When_ms))TenNearest =te; OneTe = te->Next; A } - returnnearest; -}
1 /*The process time event handles a timer event, which causes the entire card to die if there is time to set the end*/2 Static intProcesstimeevents (Aeeventloop *EventLoop)3 {4 intprocessed =0;5Aetimeevent *te;6 Long LongMaxid;7time_t now =Time (NULL);8 9 if(Now < Eventloop->lasttime)/*Why the current time is less than the last activation time, reset the system time, the current time is less than the last insertion time*/Ten { OneTe = eventloop->Timeeventhead; A while(TE) - { -Te->when_sec =0; theTe = te->Next; - } - } -Eventloop->lasttime = Now;/*Update last Action time*/ + -Te = eventloop->Timeeventhead; +Maxid = eventloop->timeeventnextid-1; A /*time processing, from the list of links to check, find the time of arrival timer call handler function, and then re-traverse, when a timer*/ at while(TE) - { - Longnow_sec, Now_ms; - Long LongID; - - if(Te->id >Maxid) in { -Te = te->Next; to Continue; + } -Aegettime (&now_sec, &Now_ms); the if(Now_sec > Te->when_sec | | (now_sec = = te->when_sec && Now_ms >= te->When_ms)) *{/*When the node time arrives, call the time-processing function, depending on the function's return to decide whether to delete the timing node*/ $ intretval;Panax Notoginseng -id = te->ID; theretval = Te->timeproc (EventLoop, ID, te->clientdata); +processed++; A the /*depending on the return value of the function to determine whether registration is still required, the return value is the next activation time*/ + if(RetVal! =Ae_nomore) - { $ /*A return value of 1 is required to re-register the function, the return value is the time of the next activation*/ $Aeaddmillisecondstonow (retval,&te->when_sec,&te->When_ms); - } - Else the { - /*Remove Timer*/Wuyi aedeletetimeevent (EventLoop, id); the } - /*timer function After processing to prevent missing nodes, re-traverse from the head, this place to note that if the timing time is too short, this place will cause a dead loop, and constantly handle the timer event*/ WuTe = eventloop->Timeeventhead; - } About Else $ { -Te = te->Next; - } - } A returnprocessed; +}
Redis Event Management (ii)