This is a creation in Article, where the information may have evolved or changed.
Timer module is very important in the development of server, a high-performance timer module can greatly improve the efficiency of engine operation. Use Golang and heap to implement a common timer module, code from: Https://github.com/xiaonanln/goTimer
You can also view the documentation: Http://godoc.org/github.com/xiaonanln/goTimer, the complete code below, with appropriate annotations and analysis.
From the performance test results, the heap-based timer module is not much more efficient than the time-wheel (Timewheel) implementation, but it is much simpler in logic.
Source Code plus Comment:
Package Timerimport ("Container/heap"//Golang provides the heap library "FMT" "OS" "Runtime/debug" "Sync" "Time") const (Min_timer_ INTERVAL = 1 * time. Millisecond///cycle timer minimum interval) var (nextaddseq uint = 1//used to generate a unique incrementing ordinal for each timer object)//Timer object type timer struct {firetime time. Time//trigger times interval. Duration//Interval (for loop timer) callback Callbackfunc//callback function repeat bool//whether the loop cancelled BOOL//has canceled addseq UINT//sequence number} Canceling a timer, this timer will not be triggered by func (T *timer) cancel () {t.cancelled = true}//to determine if the timer has canceled func (T *timer) IsActive () bool {return! t.cancelled}//use a heap to manage the timer type _timerheap struct {timers []*timer}//Golang requires that the heap implement the following functions, meaning that the meanings of these functions are self-explanatory func ( H *_timerheap) Len () int {return Len (h.timers)}//uses the trigger time and needs to compare the timer to func (H *_timerheap) Less (i, J int) bool {//log. Println (H.timers[i].firetime, h.timers[j].firetime) t1, t2: = H.timers[i].firetime, H.timers[j].firetimeif t1. Before (T2) {return true}if t1. After (T2) {return false}//T1 = = t2, making sure Timer with same deadline was fired according to their add ORderreturn H.timers[i].addseq < H.timers[j].addseq}func (h *_timerheap) Swap (i, J int) {var tmp *timertmp = h.timers[i] H.timers[i] = H.timers[j]h.timers[j] = Tmp}func (H *_timerheap) Push (x interface{}) {h.timers = append (h.timers, x. (*Timer ))}func (H *_timerheap) Pop () (Ret interface{}) {L: = Len (h.timers) h.timers, ret = h.timers[:l-1], h.timers[l-1]return}// The type definition of the timer callback function is type Callbackfunc func () var (timerheap _timerheap//Timer heap Object Timerheaplock sync. Mutex//A global Lock) func init () {heap. Init (&TIMERHEAP)//Initialize timer heap}//set a one-time callback, this callback will be triggered after D, and call the callback function func Addcallback (d times. Duration, callback Callbackfunc) *timer {t: = &timer{firetime:time. Now (). ADD (d), interval:d,callback:callback,repeat:false,}timerheaplock.lock ()//use lock to circumvent race conditions T.addseq = Nextaddseq NextAddSeq + = 1heap. Push (&timerheap, T) timerheaplock.unlock () return t}//sets a timed-triggered callback that will be triggered the first time after D time, and then repeated every d time, and call the callback function Func AddTimer (d time. Duration, callback Callbackfunc) *timer {if D < min_timer_interval {d = min_timer_interval}t: = &timer{firetime:time. Now (). ADD (d), interval:d,callback:callback,repeat:true,//set to loop Timer}timerheaplock.lock () T.addseq = NEXTADDSEQ//Set ADDSEQ When Lockednextaddseq + = 1heap. Push (&timerheap, T) timerheaplock.unlock () return t}//to the Timer module once tick//// The general upper module needs to call the tick function at a certain time interval in the goroutine of a main thread to ensure that the timer triggers on time, and/or that all timer callbacks are run in this goroutine. Func Tick () {Now: = time. Now () Timerheaplock.lock () for {if Timerheap.len () <= 0 {//without any timers, return immediately to break}nextfiretime: = Timerheap.timers[0]. Firetimeif Nextfiretime.after (now) {//No timer to time, return break}t: = heap. Pop (&TIMERHEAP). (*timer) If t.cancelled {//Ignores canceled timers continue}if!t.repeat {t.cancelled = true}<strong>//must first be unlocked before invoking the timer's callback function, Otherwise it may lead to deadlock!!! </strong>timerheaplock.unlock () runcallback (t.callback)//Run callback function and capture Panictimerheaplock.lock () if t.repeat {// If it is a loop timer, put the timer back in the heap//add timer to Heapt.firetime = T.firetime.add (t.interval) if!t.firetime.after (now) { T.firetime = Now. AdD (t.interval)}t.addseq = nextaddseqnextaddseq + = 1heap. Push (&timerheap, T)}}timerheaplock.unlock ()}//creates a goroutine to timer module timing Tickfunc startticks (tickinterval time. Duration) {go selftickroutine (tickinterval)}func selftickroutine (tickinterval time. Duration) {for {time. The Sleep (tickinterval) Tick ()}}//runs the timer's callback function and captures the panic, converting panic to error output func Runcallback (callback Callbackfunc) {defer func ( {err: = recover () if err! = Nil {fmt. fprintf (OS. Stderr, "Callback%v paniced:%v\n", Callback, Err) Debug. Printstack ()}} () Callback ()}