github.com/zhongdalu/gf@v1.0.0/g/os/gtimer/gtimer_timer.go (about) 1 // Copyright 2019 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/zhongdalu/gf. 6 7 package gtimer 8 9 import ( 10 "github.com/zhongdalu/gf/g/container/glist" 11 "github.com/zhongdalu/gf/g/container/gtype" 12 "time" 13 ) 14 15 // 定时器/分层时间轮 16 type Timer struct { 17 status *gtype.Int // 定时器状态 18 wheels []*wheel // 分层时间轮对象 19 length int // 分层层数 20 number int // 每一层Slot Number 21 intervalMs int64 // 最小时间刻度(毫秒) 22 } 23 24 // 单层时间轮 25 type wheel struct { 26 timer *Timer // 所属定时器 27 level int // 所属分层索引号 28 slots []*glist.List // 所有的循环任务项, 按照Slot Number进行分组 29 number int64 // Slot Number=len(slots) 30 ticks *gtype.Int64 // 当前时间轮已转动的刻度数量 31 totalMs int64 // 整个时间轮的时间长度(毫秒)=number*interval 32 createMs int64 // 创建时间(毫秒) 33 intervalMs int64 // 时间间隔(slot时间长度, 毫秒) 34 } 35 36 // 创建分层时间轮 37 func New(slot int, interval time.Duration, level ...int) *Timer { 38 length := gDEFAULT_WHEEL_LEVEL 39 if len(level) > 0 { 40 length = level[0] 41 } 42 t := &Timer{ 43 status: gtype.NewInt(STATUS_RUNNING), 44 wheels: make([]*wheel, length), 45 length: length, 46 number: slot, 47 intervalMs: interval.Nanoseconds() / 1e6, 48 } 49 for i := 0; i < length; i++ { 50 if i > 0 { 51 n := time.Duration(t.wheels[i-1].totalMs) * time.Millisecond 52 w := t.newWheel(i, slot, n) 53 t.wheels[i] = w 54 t.wheels[i-1].addEntry(n, w.proceed, false, gDEFAULT_TIMES, STATUS_READY) 55 } else { 56 t.wheels[i] = t.newWheel(i, slot, interval) 57 } 58 } 59 t.wheels[0].start() 60 return t 61 } 62 63 // 创建自定义的循环任务管理对象 64 func (t *Timer) newWheel(level int, slot int, interval time.Duration) *wheel { 65 w := &wheel{ 66 timer: t, 67 level: level, 68 slots: make([]*glist.List, slot), 69 number: int64(slot), 70 ticks: gtype.NewInt64(), 71 totalMs: int64(slot) * interval.Nanoseconds() / 1e6, 72 createMs: time.Now().UnixNano() / 1e6, 73 intervalMs: interval.Nanoseconds() / 1e6, 74 } 75 for i := int64(0); i < w.number; i++ { 76 w.slots[i] = glist.New() 77 } 78 return w 79 } 80 81 // 添加循环任务 82 func (t *Timer) Add(interval time.Duration, job JobFunc) *Entry { 83 return t.doAddEntry(interval, job, false, gDEFAULT_TIMES, STATUS_READY) 84 } 85 86 // 添加定时任务 87 func (t *Timer) AddEntry(interval time.Duration, job JobFunc, singleton bool, times int, status int) *Entry { 88 return t.doAddEntry(interval, job, singleton, times, status) 89 } 90 91 // 添加单例运行循环任务 92 func (t *Timer) AddSingleton(interval time.Duration, job JobFunc) *Entry { 93 return t.doAddEntry(interval, job, true, gDEFAULT_TIMES, STATUS_READY) 94 } 95 96 // 添加只运行一次的循环任务 97 func (t *Timer) AddOnce(interval time.Duration, job JobFunc) *Entry { 98 return t.doAddEntry(interval, job, true, 1, STATUS_READY) 99 } 100 101 // 添加运行指定次数的循环任务。 102 func (t *Timer) AddTimes(interval time.Duration, times int, job JobFunc) *Entry { 103 return t.doAddEntry(interval, job, true, times, STATUS_READY) 104 } 105 106 // 延迟添加循环任务。 107 func (t *Timer) DelayAdd(delay time.Duration, interval time.Duration, job JobFunc) { 108 t.AddOnce(delay, func() { 109 t.Add(interval, job) 110 }) 111 } 112 113 // 延迟添加循环任务, 支持完整的参数。 114 func (t *Timer) DelayAddEntry(delay time.Duration, interval time.Duration, job JobFunc, singleton bool, times int, status int) { 115 t.AddOnce(delay, func() { 116 t.AddEntry(interval, job, singleton, times, status) 117 }) 118 } 119 120 // 延迟添加单例循环任务 121 func (t *Timer) DelayAddSingleton(delay time.Duration, interval time.Duration, job JobFunc) { 122 t.AddOnce(delay, func() { 123 t.AddSingleton(interval, job) 124 }) 125 } 126 127 // 延迟添加只运行一次的循环任务 128 func (t *Timer) DelayAddOnce(delay time.Duration, interval time.Duration, job JobFunc) { 129 t.AddOnce(delay, func() { 130 t.AddOnce(interval, job) 131 }) 132 } 133 134 // 延迟添加只运行一次的循环任务 135 func (t *Timer) DelayAddTimes(delay time.Duration, interval time.Duration, times int, job JobFunc) { 136 t.AddOnce(delay, func() { 137 t.AddTimes(interval, times, job) 138 }) 139 } 140 141 // 启动定时器 142 func (t *Timer) Start() { 143 t.status.Set(STATUS_RUNNING) 144 } 145 146 // 定制定时器 147 func (t *Timer) Stop() { 148 t.status.Set(STATUS_STOPPED) 149 } 150 151 // 关闭定时器 152 func (t *Timer) Close() { 153 t.status.Set(STATUS_CLOSED) 154 } 155 156 // 添加定时任务 157 func (t *Timer) doAddEntry(interval time.Duration, job JobFunc, singleton bool, times int, status int) *Entry { 158 return t.wheels[t.getLevelByIntervalMs(interval.Nanoseconds()/1e6)].addEntry(interval, job, singleton, times, status) 159 } 160 161 // 添加定时任务,给定父级Entry, 间隔参数参数为毫秒数. 162 func (t *Timer) doAddEntryByParent(interval int64, parent *Entry) *Entry { 163 return t.wheels[t.getLevelByIntervalMs(interval)].addEntryByParent(interval, parent) 164 } 165 166 // 根据intervalMs计算添加的分层索引 167 func (t *Timer) getLevelByIntervalMs(intervalMs int64) int { 168 pos, cmp := t.binSearchIndex(intervalMs) 169 switch cmp { 170 // intervalMs与最后匹配值相等, 不添加到匹配得层,而是向下一层添加 171 case 0: 172 fallthrough 173 // intervalMs比最后匹配值小 174 case -1: 175 i := pos 176 for ; i > 0; i-- { 177 if intervalMs > t.wheels[i].intervalMs && intervalMs <= t.wheels[i].totalMs { 178 return i 179 } 180 } 181 return i 182 183 // intervalMs比最后匹配值大 184 case 1: 185 i := pos 186 for ; i < t.length-1; i++ { 187 if intervalMs > t.wheels[i].intervalMs && intervalMs <= t.wheels[i].totalMs { 188 return i 189 } 190 } 191 return i 192 } 193 return 0 194 } 195 196 // 二分查找当前任务可以添加的时间轮对象索引. 197 func (t *Timer) binSearchIndex(n int64) (index int, result int) { 198 min := 0 199 max := t.length - 1 200 mid := 0 201 cmp := -2 202 for min <= max { 203 mid = int((min + max) / 2) 204 switch { 205 case t.wheels[mid].intervalMs == n: 206 cmp = 0 207 case t.wheels[mid].intervalMs > n: 208 cmp = -1 209 case t.wheels[mid].intervalMs < n: 210 cmp = 1 211 } 212 switch cmp { 213 case -1: 214 max = mid - 1 215 case 1: 216 min = mid + 1 217 case 0: 218 return mid, cmp 219 } 220 } 221 return mid, cmp 222 }