一文搞懂GoLang定时器实现原理( 二 )

runtime/time.go的addtimerLocked
// Add a timer to the heap and start or kick timerproc if the new timer is// earlier than any of the others.// Timers are locked.// Returns whether all is well: false if the data structure is corrupt// due to user-level races.func (tb *timersBucket) addtimerLocked(t *timer) bool {   // when must never be negative; otherwise timerproc will overflow   // during its delta calculation and never expire other runtime timers.   if t.when < 0 {      t.when = 1<<63 - 1   }   t.i = len(tb.t)   tb.t = Append(tb.t, t)   if !siftupTimer(tb.t, t.i) {      return false   }   if t.i == 0 {      // siftup moved to top: new earliest deadline.      if tb.sleeping && tb.sleepUntil > t.when {         tb.sleeping = false         notewakeup(&tb.waitnote)    }      if tb.rescheduling {         tb.rescheduling = false         goready(tb.gp, 0)    }      if !tb.created {         tb.created = true         go timerproc(tb)    }   }   return true}runtime/time.go的timerproc
func timerproc(tb *timersBucket) {    tb.gp = getg()    for {        lock(&tb.lock)        tb.sleeping = false        now := nanotime()        delta := int64(-1)        for {            if len(tb.t) == 0 { //无timer的情况                delta = -1                break          }            t := tb.t[0] //拿到堆顶的timer            delta = t.when - now            if delta > 0 { // 所有timer的时间都没有到期                break          }            if t.period > 0 { // t[0] 是ticker类型 , 调整其到期时间并调整timer堆结构                // leave in heap but adjust next time to fire                t.when += t.period * (1 + -delta/t.period)                siftdownTimer(tb.t, 0)          } else {                //Timer类型的定时器是单次的 , 所以这里需要将其从堆里面删除                // remove from heap                last := len(tb.t) - 1                if last > 0 {                    tb.t[0] = tb.t[last]                    tb.t[0].i = 0              }                tb.t[last] = nil                tb.t = tb.t[:last]                if last > 0 {                    siftdownTimer(tb.t, 0)              }                t.i = -1 // mark as removed          }            f := t.f            arg := t.arg            seq := t.seq            unlock(&tb.lock)            if raceenabled {                raceacquire(unsafe.Pointer(t))          }            f(arg, seq) //sendTimer被调用的位置 ---------------------------------------            lock(&tb.lock)      }        if delta < 0 || faketime > 0 {            // No timers left - put goroutine to sleep.            tb.rescheduling = true            goparkunlock(&tb.lock, "timer goroutine (idle)", traceEvGoBlock, 1)            continue      }        // At least one timer pending. Sleep until then.        tb.sleeping = true        tb.sleepUntil = now + delta        noteclear(&tb.waitnote)        unlock(&tb.lock)        notetsleepg(&tb.waitnote, delta)  }}


推荐阅读