gf/g/os/gtimer/gtimer_entry.go

154 lines
4.6 KiB
Go

// Copyright 2019 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
package gtimer
import (
"gitee.com/johng/gf/g/container/gtype"
"time"
)
// 循环任务项
type Entry struct {
job JobFunc // 注册循环任务方法
wheel *wheel // 所属时间轮
singleton *gtype.Bool // 任务是否单例运行
status *gtype.Int // 任务状态(0: ready; 1: running; -1: closed)
times *gtype.Int // 还需运行次数
create int64 // 注册时的时间轮ticks
interval int64 // 设置的运行间隔(时间轮刻度数量)
createMs int64 // 创建时间(毫秒)
updateMs int64 // 更新时间(上一次检查/运行时间, 毫秒)
intervalMs int64 // 间隔时间(毫秒)
}
// 任务执行方法
type JobFunc = func()
// 创建定时任务
func (w *wheel) addEntry(interval time.Duration, job JobFunc, singleton bool, times int) *Entry {
ms := interval.Nanoseconds()/1e6
num := ms/w.intervalMs
if num == 0 {
// 如果安装的任务间隔小于时间轮刻度,
// 那么将会在下一刻度被执行
num = 1
}
nowMs := time.Now().UnixNano()/1e6
ticks := w.ticks.Val()
entry := &Entry {
wheel : w,
singleton : gtype.NewBool(singleton),
status : gtype.NewInt(STATUS_READY),
times : gtype.NewInt(times),
job : job,
create : ticks,
interval : num,
createMs : nowMs,
updateMs : nowMs,
intervalMs : ms,
}
// 安装任务
w.slots[(ticks + num) % w.number].PushBack(entry)
return entry
}
// 递增添加任务
func (w *wheel) reAddEntry(entry *Entry, nowTicks int64, nowMs int64) {
left := entry.interval - (nowTicks - entry.create)
if left <= 0 {
left = entry.interval
entry.create = nowTicks
entry.createMs = nowMs
entry.updateMs = nowMs
}
w.slots[(nowTicks + left) % w.number].PushBack(entry)
}
// 获取任务状态
func (entry *Entry) Status() int {
return entry.status.Val()
}
// 设置任务状态
func (entry *Entry) SetStatus(status int) int {
return entry.status.Set(status)
}
// 关闭当前任务
func (entry *Entry) Close() {
entry.status.Set(STATUS_CLOSED)
}
// 是否单例运行
func (entry *Entry) IsSingleton() bool {
return entry.singleton.Val()
}
// 设置单例运行
func (entry *Entry) SetSingleton(enabled bool) {
entry.singleton.Set(enabled)
}
// 设置任务的运行次数
func (entry *Entry) SetTimes(times int) {
entry.times.Set(times)
}
// 执行任务
func (entry *Entry) Run() {
entry.job()
}
// 检测当前任务是否可运行, 参数为当前时间的纳秒数, 精度更高
func (entry *Entry) check(nowTicks int64, nowMs int64) bool {
// 运行检查
if diff := nowTicks - entry.create; diff > 0 && diff%entry.interval == 0 {
// 是否单例
if entry.IsSingleton() {
if entry.status.Set(STATUS_RUNNING) == STATUS_RUNNING {
return false
}
}
// 次数限制
times := entry.times.Add(-1)
if times <= 0 {
entry.status.Set(STATUS_CLOSED)
if times < 0 {
return false
}
}
// 是否不限制运行次数
if times < 2000000000 && times > 1000000000 {
times = gDEFAULT_TIMES
entry.times.Set(gDEFAULT_TIMES)
}
// 分层转换
if entry.wheel.level > 0 {
if diffMs := nowMs - entry.updateMs; diffMs < entry.intervalMs {
if leftMs := entry.intervalMs - diffMs; leftMs > entry.wheel.wheels.intervalMs {
delay := time.Duration(leftMs)*time.Millisecond
// 往底层添加
entry.wheel.wheels.addEntry(delay, entry.job, false, 1)
// 延迟重新添加
if times > 0 {
entry.wheel.wheels.DelayAddTimes(
delay,
time.Duration(entry.intervalMs)*time.Millisecond,
times,
entry.job,
)
}
entry.status.Set(STATUS_CLOSED)
return false
}
}
}
return true
}
return false
}