-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwheel.go
More file actions
74 lines (63 loc) · 1.27 KB
/
wheel.go
File metadata and controls
74 lines (63 loc) · 1.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Copyright 2017 Granitic. All rights reserved.
// Use of this source code is governed by an Apache 2.0 license that can be found in the LICENSE file at the root of this project.
package timer
import (
"errors"
)
type Wheel struct {
slot []*Slot
pos int
mask int
bit uint
}
func popcount(x uint64) uint {
const (
m1 = 0x5555555555555555
m2 = 0x3333333333333333
m4 = 0x0f0f0f0f0f0f0f0f
h01 = 0x0101010101010101
)
x -= (x >> 1) & m1
x = (x & m2) + ((x >> 2) & m2)
x = (x + (x >> 4)) & m4
return uint((x * h01) >> 56)
}
func NewWheel(length int) *Wheel {
if 0 != (length & (length - 1)) {
panic(errors.New("NewWheel length"))
}
return &Wheel{
slot: make([]*Slot, length),
mask: length - 1,
bit: popcount(uint64(length - 1)),
}
}
func (w *Wheel) Push(i int, tm *Timer) {
w.Slot(w.pos + i).Push(tm)
}
func (w *Wheel) Pop(i int) *Timer {
if slot := w.slot[(w.pos+i)&w.mask]; nil == slot {
return slot.Pop()
}
return nil
}
func (w *Wheel) Clear(i int) *Slot {
i &= w.mask
slot := w.slot[i]
w.slot[i] = nil
return slot
}
func (w *Wheel) Slot(i int) *Slot {
i &= w.mask
slot := w.slot[i]
if nil == slot {
slot = NewSlot()
w.slot[i] = slot
}
return slot
}
func (w *Wheel) Step() (int, *Slot) {
w.pos++
i := w.pos & w.mask
return i, w.slot[i]
}