remove task O(1), and none block tickerHandler() (#72)

* remove task O(1), and none block tickerHandler()

* remove task O(1), and none block tickerHandler()
This commit is contained in:
SsnAgo
2022-07-20 14:05:44 +08:00
committed by GitHub
parent ab0754e2a5
commit 4fd56dae08

View File

@@ -6,13 +6,18 @@ import (
"time" "time"
) )
type location struct {
slot int
etask *list.Element
}
// TimeWheel can execute job after waiting given duration // TimeWheel can execute job after waiting given duration
type TimeWheel struct { type TimeWheel struct {
interval time.Duration interval time.Duration
ticker *time.Ticker ticker *time.Ticker
slots []*list.List slots []*list.List
timer map[string]int timer map[string]*location
currentPos int currentPos int
slotNum int slotNum int
addTaskChannel chan task addTaskChannel chan task
@@ -35,7 +40,7 @@ func New(interval time.Duration, slotNum int) *TimeWheel {
tw := &TimeWheel{ tw := &TimeWheel{
interval: interval, interval: interval,
slots: make([]*list.List, slotNum), slots: make([]*list.List, slotNum),
timer: make(map[string]int), timer: make(map[string]*location),
currentPos: 0, currentPos: 0,
slotNum: slotNum, slotNum: slotNum,
addTaskChannel: make(chan task), addTaskChannel: make(chan task),
@@ -99,12 +104,12 @@ func (tw *TimeWheel) start() {
func (tw *TimeWheel) tickHandler() { func (tw *TimeWheel) tickHandler() {
l := tw.slots[tw.currentPos] l := tw.slots[tw.currentPos]
tw.scanAndRunTask(l)
if tw.currentPos == tw.slotNum-1 { if tw.currentPos == tw.slotNum-1 {
tw.currentPos = 0 tw.currentPos = 0
} else { } else {
tw.currentPos++ tw.currentPos++
} }
go tw.scanAndRunTask(l)
} }
func (tw *TimeWheel) scanAndRunTask(l *list.List) { func (tw *TimeWheel) scanAndRunTask(l *list.List) {
@@ -138,11 +143,18 @@ func (tw *TimeWheel) addTask(task *task) {
pos, circle := tw.getPositionAndCircle(task.delay) pos, circle := tw.getPositionAndCircle(task.delay)
task.circle = circle task.circle = circle
tw.slots[pos].PushBack(task) e := tw.slots[pos].PushBack(task)
loc := &location{
if task.key != "" { slot: pos,
tw.timer[task.key] = pos etask: e,
} }
if task.key != "" {
_, ok := tw.timer[task.key]
if ok {
tw.removeTask(task.key)
}
}
tw.timer[task.key] = loc
} }
func (tw *TimeWheel) getPositionAndCircle(d time.Duration) (pos int, circle int) { func (tw *TimeWheel) getPositionAndCircle(d time.Duration) (pos int, circle int) {
@@ -155,18 +167,11 @@ func (tw *TimeWheel) getPositionAndCircle(d time.Duration) (pos int, circle int)
} }
func (tw *TimeWheel) removeTask(key string) { func (tw *TimeWheel) removeTask(key string) {
position, ok := tw.timer[key] pos, ok := tw.timer[key]
if !ok { if !ok {
return return
} }
l := tw.slots[position] l := tw.slots[pos.slot]
for e := l.Front(); e != nil; { l.Remove(pos.etask)
task := e.Value.(*task) delete(tw.timer, key)
if task.key == key {
delete(tw.timer, task.key)
l.Remove(e)
}
e = e.Next()
}
} }