Skip to content

Commit 6e95125

Browse files
committed
update timer
1 parent c1d4554 commit 6e95125

File tree

1 file changed

+69
-7
lines changed

1 file changed

+69
-7
lines changed

timer.md

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ type timersBucket struct {
139139

140140
### 四叉小顶堆性质
141141

142-
四叉堆高度上比二叉堆要矮一些。直接孩子节点一定比父节点大,同一层的相邻四个节点是按从小到大排列的,但如果不相邻,那么就不遵循这样的关系,所以,下面这种情况是符合四叉小顶堆的性质的:
142+
四叉堆高度上比二叉堆要矮一些。一个节点的所有(最多有4个)孩子节点都比这个节点要大。一个节点的(只有一个)父节点一定比当前节点小。下面是填好值之后的一个典型的四叉堆:
143143

144144
```
145145
┌─────┐
@@ -152,7 +152,7 @@ type timersBucket struct {
152152
153153
┌─────┬─────┬─────┬─────┐
154154
│ │ │ │ │
155-
1 │ 2 │ 711
155+
3 │ 2 │ 210
156156
└─────┴─────┴─────┴─────┘
157157
│ │ │ │
158158
│ │ │ │
@@ -164,13 +164,13 @@ type timersBucket struct {
164164
▼ │ │ ▼
165165
┌─────┬─────┬─────┬─────┐ │ │ ┌─────┬─────┬─────┬─────┐
166166
│ │ │ │ │ ▼ ▼ │ │ │ │ │
167-
1315 17 20 │ ┌─────┬─────┬─────┬─────┐ ┌─────┬─────┬─────┬─────┐ │ 12 │ 13 │ 1516
167+
204 5 13 │ ┌─────┬─────┬─────┬─────┐ ┌─────┬─────┬─────┬─────┐ │ 99 │ 13 │ 1112
168168
└─────┴─────┴─────┴─────┘ │ │ │ │ │ │ │ │ │ │ └─────┴─────┴─────┴─────┘
169-
│ 12 │ 14 │ 15 │ 16 │ │ 89 │ 11 12
169+
│ 12 │ 14 │ 15 │ 16 │ │ 310 │ 3 3
170170
└─────┴─────┴─────┴─────┘ └─────┴─────┴─────┴─────┘
171171
```
172172

173-
当然,二叉小顶堆同一层的大小关系也是不确定的。只是四叉堆在同一层还有这种特殊的相邻的情况
173+
和二叉堆一样,对于一个节点的要求只有和其父节点以及子节点之间的大小关系。相邻节点之间没有任何关系
174174

175175
### 时间堆插入
176176

@@ -379,8 +379,13 @@ func timerproc(tb *timersBucket) {
379379

380380
```go
381381
func siftupTimer(t []*timer, i int) {
382+
// 先暂存当前刚插入到数组尾部的节点
382383
when := t[i].when
383384
tmp := t[i]
385+
386+
// 从当前插入节点的父节点开始
387+
// 如果最新插入的那个节点的触发时间要比父节点的触发时间更早
388+
// 那么就把这个父节点下移
384389
for i > 0 {
385390
p := (i - 1) / 4 // parent
386391
if when >= t[p].when {
@@ -390,6 +395,9 @@ func siftupTimer(t []*timer, i int) {
390395
t[i].i = i
391396
i = p
392397
}
398+
399+
// 如果发生过移动,用最新插入的节点
400+
// 覆盖掉最后一个下移的父节点
393401
if tmp != t[i] {
394402
t[i] = tmp
395403
t[i].i = i
@@ -405,8 +413,8 @@ func siftdownTimer(t []*timer, i int) {
405413
when := t[i].when
406414
tmp := t[i]
407415
for {
408-
c := i*4 + 1 // left child
409-
c3 := c + 2 // mid child
416+
c := i*4 + 1 // 最左孩子节点
417+
c3 := c + 2 // 第三个孩子节点
410418
if c >= n {
411419
break
412420
}
@@ -440,6 +448,60 @@ func siftdownTimer(t []*timer, i int) {
440448
}
441449
```
442450

451+
这段代码实在是称不上优雅,其实就是在所有孩子节点中先找出最小的那一个,如果最小的比当前要下移的节点还要大,那么就 break。反之,则将最小的节点上移,然后再判断这个最小节点的 4 个子节点是否都比要下移的节点大。以此类推。用图来模拟一下这个过程:
452+
453+
```
454+
│ ┌───┐
455+
│ │ 5 │
456+
│ └───┘
457+
│ │
458+
│ ┌─────┘
459+
│ ▼
460+
│ ┌───┬───┳━━━┳───┐
461+
│ │ 7 │ 3 │ 2 ┃ 6 │
462+
│ └───┴───┻━━━┻───┘
463+
┌───────────────────┐ │ │
464+
│ siftdownTimer │ │ └──────────┐
465+
└───────────────────┘ │ ▼
466+
.─────────. │ ┌───┬───┬───┳━━━┓
467+
( before ) │ │ 4 │ 5 │ 9 │ 3 ┃
468+
`─────────' │ └───┴───┴───┻━━━┛
469+
│ │
470+
│ └─────────────┐
471+
│ ▼
472+
│ ┌───┬───┬───┳━━━┓
473+
│ │ 6 │ 6 │ 6 │ 4 ┃
474+
│ └───┴───┴───┻━━━┛
475+
476+
477+
478+
479+
480+
│ ┌───┐
481+
│ │ 2 │
482+
│ └───┘
483+
│ │
484+
│ ┌─────┘
485+
│ ▼
486+
│ ┌───┬───┳━━━┳───┐
487+
│ │ 7 │ 3 │ 3 ┃ 6 │
488+
│ └───┴───┻━━━┻───┘
489+
┌───────────────────┐ │ │
490+
│ siftdownTimer │ │ └──────────┐
491+
└───────────────────┘ │ ▼
492+
.─────────. │ ┌───┬───┬───┳━━━┓
493+
( after ) │ │ 4 │ 5 │ 9 │ 4 ┃
494+
`─────────' │ └───┴───┴───┻━━━┛
495+
│ │
496+
│ └─────────────┐
497+
│ ▼
498+
│ ┌───┬───┬───┳━━━┓
499+
│ │ 6 │ 6 │ 6 │ 5 ┃
500+
│ └───┴───┴───┻━━━┛
501+
502+
503+
```
504+
443505
### time.After
444506

445507
```go

0 commit comments

Comments
 (0)