在执行调度循环 runtime.schedule 时,或者系统监控sysmon时,会检查是否有timer就绪。
每次把堆顶timer的when和当前时间作比较,when<nowtime则执行timer里的f,并删除当前timer,如果是ticker,则计算下一次触发的时间,加入到堆中
timer存放在P中:
type p struct {
timersLock mutex // timers 字段的锁,scheduler 会在不同的 P 上访问timers
timers []*timer // 4叉小顶堆
adjustTimers uint32 // 在 P 堆中 timerModifiedEarlier timers 的数量
(...)
}
p被销毁时,要将timer转移走,p里没有timer时,会从其他p里偷一半的timer
--------------------------------------------------------------------------------
timer 和 ticker 数据结构
type Ticker struct {
C <-chan Time
r runtimeTimer
}
type Timer struct {
C <-chan Time
r runtimeTimer
}
type runtimeTimer struct {
pp uintptr // timer 所在的 P 的指针
when int64
period int64
f func(interface{}, uintptr)
arg interface{}
seq uintptr
nextwhen int64
status uint32
}
创建timer
func After(d Duration) <-chan Time {
return NewTimer(d).C
}
func NewTimer(d Duration) *Timer {
c := make(chan Time, 1)
t := &Timer{
C: c,
r: runtimeTimer{
when: when(d),
f: sendTime, // 发送当前时间
arg: c,
},
}
startTimer(&t.r) // 调用 addtimer(),插入到堆中
return t
}
创建ticker
func Tick(d Duration) <-chan Time {
if d <= 0 { return nil }
return NewTicker(d).C
}
func NewTicker(d Duration) *Ticker {
if d <= 0 { panic(errors.New("non-positive interval for NewTicker")) }
c := make(chan Time, 1)
t := &Ticker{
C: c,
r: runtimeTimer{
when: when(d),
period: int64(d), // 多了period,其他和timer一样
f: sendTime,
arg: c,
},
}
startTimer(&t.r) // 调用 addtimer(),插入到堆中
return t
}
stop
func (t *Ticker) Stop() { // Stop后才会释放相关的资源
stopTimer(&t.r) // 调用 deltimer(),从堆中删除
}
func (t *Timer) Stop() bool {
if t.r.f == nil { panic("time: Stop called on uninitialized Timer") }
return stopTimer(&t.r) // 调用 deltimer(),从堆中删除
}
reset
func (t *Timer) Reset(d Duration) bool {
w := when(d)
active := stopTimer(&t.r) // 调用 deltimer(),从堆中删除
resetTimer(&t.r, w) // 调整时间
return active
}
func sendTime(c interface{}, seq uintptr) {
select {
case c.(chan Time) <- Now():
default:
}
}