Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c5d0848

Browse files
committedJun 23, 2018
finish timer
1 parent 1f2897b commit c5d0848

File tree

2 files changed

+87
-2
lines changed

2 files changed

+87
-2
lines changed
 

‎readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
3. [ ] Interface
1010
4. [ ] Select
1111
5. [ ] Slice
12-
6. [ ] Timer
12+
6. [x] Timer
1313
7. [ ] Defer
1414
8. [ ] Lock
1515
9. [ ] Netpoll

‎timer.md

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,10 +687,95 @@ func startTimer(*runtimeTimer)
687687

688688
```go
689689
// startTimer adds t to the timer heap.
690+
// 把 t 添加到 timer 堆
690691
//go:linkname startTimer time.startTimer
691692
func startTimer(t *timer) {
692693
addtimer(t)
693694
}
694695
```
695696

696-
#### timer.Ticker 流程
697+
addtimer 后面的流程之前已经看过了。
698+
699+
#### timer.Tick 流程
700+
701+
```go
702+
func Tick(d Duration) <-chan Time {
703+
if d <= 0 {
704+
return nil
705+
}
706+
return NewTicker(d).C
707+
}
708+
```
709+
710+
```go
711+
// NewTicker 会返回一个 Ticker 对象,其 channel 每隔 period 时间
712+
// 会收到一个时间值
713+
// 如果 receiver 接收慢了,Ticker 会把不需要的 tick drop 掉
714+
// d 必须比 0 大,否则 panic
715+
// Stop ticker 才能释放相关的资源
716+
func NewTicker(d Duration) *Ticker {
717+
if d <= 0 {
718+
panic(errors.New("non-positive interval for NewTicker"))
719+
}
720+
c := make(chan Time, 1)
721+
t := &Ticker{
722+
C: c,
723+
r: runtimeTimer{
724+
when: when(d),
725+
period: int64(d),
726+
f: sendTime,
727+
arg: c,
728+
},
729+
}
730+
startTimer(&t.r)
731+
return t
732+
}
733+
```
734+
735+
可以看到, Ticker 和 Timer 的 r 成员就只差在 period 这一个字段上,每隔一个 period 就往 channel 里发数据的就是 Ticker,而 fire and disappear 的就是 Timer。
736+
737+
#### Stop 流程
738+
739+
```go
740+
func (t *Ticker) Stop() {
741+
stopTimer(&t.r)
742+
}
743+
744+
func (t *Timer) Stop() bool {
745+
if t.r.f == nil {
746+
panic("time: Stop called on uninitialized Timer")
747+
}
748+
return stopTimer(&t.r)
749+
}
750+
```
751+
752+
Timer 和 Ticker 都是调用的 stopTimer。
753+
754+
```go
755+
func stopTimer(t *timer) bool {
756+
return deltimer(t)
757+
}
758+
```
759+
760+
deltimer 在上面也看到过了。
761+
762+
#### Reset 流程
763+
764+
```go
765+
func (t *Timer) Reset(d Duration) bool {
766+
if t.r.f == nil {
767+
panic("time: Reset called on uninitialized Timer")
768+
}
769+
w := when(d)
770+
active := stopTimer(&t.r)
771+
t.r.when = w
772+
startTimer(&t.r)
773+
return active
774+
}
775+
```
776+
777+
都是见过的函数,没啥特别的。
778+
779+
## 最后
780+
781+
本篇内容主要是讲 Go 的定时器实现,工业界的定时器实现并不只有一种。如果你还想知道其它系统,比如 nginx 里是怎么实现定时器的,可以参考[这一篇](https://www.jianshu.com/p/427dfe8ad3c0)

0 commit comments

Comments
 (0)
Please sign in to comment.