diff --git a/g/container/gpool/gpool.go b/g/container/gpool/gpool.go index 3990cd821..2cb24ca92 100644 --- a/g/container/gpool/gpool.go +++ b/g/container/gpool/gpool.go @@ -12,7 +12,7 @@ import ( "gitee.com/johng/gf/g/container/glist" "gitee.com/johng/gf/g/container/gtype" "gitee.com/johng/gf/g/os/gtime" - "gitee.com/johng/gf/g/os/gwheel" + "gitee.com/johng/gf/g/os/gtimer" "time" ) @@ -44,7 +44,7 @@ func New(expire int, newFunc...func() (interface{}, error)) *Pool { if len(newFunc) > 0 { r.NewFunc = newFunc[0] } - gwheel.AddSingleton(time.Second, r.checkExpire) + gtimer.AddSingleton(time.Second, r.checkExpire) return r } @@ -102,7 +102,7 @@ func (p *Pool) Close() { // 超时检测循环 func (p *Pool) checkExpire() { if p.closed.Val() { - gwheel.Exit() + gtimer.Exit() } for { if r := p.list.PopFront(); r != nil { diff --git a/g/os/gcache/gcache_cache.go b/g/os/gcache/gcache_cache.go index e32e9f7fe..c3d67d17f 100644 --- a/g/os/gcache/gcache_cache.go +++ b/g/os/gcache/gcache_cache.go @@ -7,7 +7,7 @@ package gcache import ( - "gitee.com/johng/gf/g/os/gwheel" + "gitee.com/johng/gf/g/os/gtimer" "sync/atomic" "time" "unsafe" @@ -24,7 +24,7 @@ func New(lruCap...int) *Cache { c := &Cache { memCache : newMemCache(lruCap...), } - gwheel.AddSingleton(time.Second, c.syncEventAndClearExpired) + gtimer.AddSingleton(time.Second, c.syncEventAndClearExpired) return c } diff --git a/g/os/gcache/gcache_mem_cache.go b/g/os/gcache/gcache_mem_cache.go index 79831407f..0d9c76dcb 100644 --- a/g/os/gcache/gcache_mem_cache.go +++ b/g/os/gcache/gcache_mem_cache.go @@ -11,7 +11,7 @@ import ( "gitee.com/johng/gf/g/container/gset" "gitee.com/johng/gf/g/container/gtype" "gitee.com/johng/gf/g/os/gtime" - "gitee.com/johng/gf/g/os/gwheel" + "gitee.com/johng/gf/g/os/gtimer" "gitee.com/johng/gf/g/util/gconv" "math" "sync" @@ -292,7 +292,7 @@ func (c *memCache) syncEventAndClearExpired() { oldExpireTime := int64(0) newExpireTime := int64(0) if c.closed.Val() { - gwheel.Exit() + gtimer.Exit() return } // ======================== diff --git a/g/os/gcache/gcache_mem_cache_lru.go b/g/os/gcache/gcache_mem_cache_lru.go index e33c57674..9da2d6dd9 100644 --- a/g/os/gcache/gcache_mem_cache_lru.go +++ b/g/os/gcache/gcache_mem_cache_lru.go @@ -11,7 +11,7 @@ import ( "gitee.com/johng/gf/g/container/glist" "gitee.com/johng/gf/g/container/gmap" "gitee.com/johng/gf/g/container/gtype" - "gitee.com/johng/gf/g/os/gwheel" + "gitee.com/johng/gf/g/os/gtimer" "time" ) @@ -33,7 +33,7 @@ func newMemCacheLru(cache *memCache) *memCacheLru { rawList : glist.New(), closed : gtype.NewBool(), } - gwheel.AddSingleton(time.Second, lru.SyncAndClear) + gtimer.AddSingleton(time.Second, lru.SyncAndClear) return lru } @@ -80,7 +80,7 @@ func (lru *memCacheLru) Print() { // 异步执行协程,将queue中的数据同步到list中 func (lru *memCacheLru) SyncAndClear() { if lru.closed.Val() { - gwheel.Exit() + gtimer.Exit() return } // 数据同步 diff --git a/g/os/gcron/gcron_cron.go b/g/os/gcron/gcron_cron.go index 7ebf81926..6257b6285 100644 --- a/g/os/gcron/gcron_cron.go +++ b/g/os/gcron/gcron_cron.go @@ -12,7 +12,7 @@ import ( "gitee.com/johng/gf/g/container/garray" "gitee.com/johng/gf/g/container/gmap" "gitee.com/johng/gf/g/container/gtype" - "gitee.com/johng/gf/g/os/gwheel" + "gitee.com/johng/gf/g/os/gtimer" "strconv" "time" ) @@ -77,7 +77,7 @@ func (c *Cron) AddOnce(pattern string, job func(), name ... string) (*Entry, err // 延迟添加定时任务,delay参数单位为秒 func (c *Cron) DelayAdd(delay int, pattern string, job func(), name ... string) { - gwheel.AddOnce(time.Duration(delay)*time.Second, func() { + gtimer.AddOnce(time.Duration(delay)*time.Second, func() { if _, err := c.Add(pattern, job, name ...); err != nil { panic(err) } @@ -86,7 +86,7 @@ func (c *Cron) DelayAdd(delay int, pattern string, job func(), name ... string) // 延迟添加单例定时任务,delay参数单位为秒 func (c *Cron) DelayAddSingleton(delay int, pattern string, job func(), name ... string) { - gwheel.AddOnce(time.Duration(delay)*time.Second, func() { + gtimer.AddOnce(time.Duration(delay)*time.Second, func() { if _, err := c.AddSingleton(pattern, job, name ...); err != nil { panic(err) } @@ -95,7 +95,7 @@ func (c *Cron) DelayAddSingleton(delay int, pattern string, job func(), name ... // 延迟添加只运行一次的定时任务,delay参数单位为秒 func (c *Cron) DelayAddOnce(delay int, pattern string, job func(), name ... string) { - gwheel.AddOnce(time.Duration(delay)*time.Second, func() { + gtimer.AddOnce(time.Duration(delay)*time.Second, func() { if _, err := c.AddOnce(pattern, job, name ...); err != nil { panic(err) } diff --git a/g/os/gcron/gcron_jobloop.go b/g/os/gcron/gcron_jobloop.go index 2e397aea1..d076bdfaa 100644 --- a/g/os/gcron/gcron_jobloop.go +++ b/g/os/gcron/gcron_jobloop.go @@ -7,15 +7,15 @@ package gcron import ( - "gitee.com/johng/gf/g/os/gwheel" + "gitee.com/johng/gf/g/os/gtimer" "time" ) // 延迟添加定时任务,delay参数单位为秒 func (c *Cron) startLoop() { - gwheel.Add(time.Second, func() { + gtimer.Add(time.Second, func() { if c.status.Val() == STATUS_CLOSED { - gwheel.Exit() + gtimer.Exit() } if c.status.Val() == STATUS_RUNNING { go c.checkEntries(time.Now()) diff --git a/g/os/gcron/gcron_bench_test.go b/g/os/gcron/gcron_z_bench_test.go similarity index 100% rename from g/os/gcron/gcron_bench_test.go rename to g/os/gcron/gcron_z_bench_test.go diff --git a/g/os/gmlock/gmlock_locker.go b/g/os/gmlock/gmlock_locker.go index 9f77fbb46..1cecba49e 100644 --- a/g/os/gmlock/gmlock_locker.go +++ b/g/os/gmlock/gmlock_locker.go @@ -8,7 +8,7 @@ package gmlock import ( "gitee.com/johng/gf/g/container/gmap" - "gitee.com/johng/gf/g/os/gwheel" + "gitee.com/johng/gf/g/os/gtimer" "time" ) @@ -79,7 +79,7 @@ func (l *Locker) doLock(key string, expire int, try bool) bool { if ok && expire > 0 { // 异步goroutine计时处理 wid := mu.wid.Val() - gwheel.AddOnce(time.Duration(expire)*time.Second, func() { + gtimer.AddOnce(time.Duration(expire)*time.Second, func() { if wid == mu.wid.Val() { mu.Unlock() } @@ -99,7 +99,7 @@ func (l *Locker) doRLock(key string, expire int, try bool) bool { } if ok && expire > 0 { rid := mu.rid.Val() - gwheel.AddOnce(time.Duration(expire)*time.Second, func() { + gtimer.AddOnce(time.Duration(expire)*time.Second, func() { if rid == mu.rid.Val() { mu.RUnlock() } diff --git a/g/os/gwheel/gwheel.go b/g/os/gtimer/gtimer.go similarity index 73% rename from g/os/gwheel/gwheel.go rename to g/os/gtimer/gtimer.go index 0290de409..e34fbfb86 100644 --- a/g/os/gwheel/gwheel.go +++ b/g/os/gtimer/gtimer.go @@ -4,11 +4,11 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://gitee.com/johng/gf. -// Package gwheel provides Timing Wheel for interval jobs running and management/时间轮. +// Package gtimer implements Levelled Timing Wheel for interval/delayed jobs running and management/任务定时器(分层时间轮). // 高效的时间轮任务管理模块,用于管理间隔/延迟运行任务。 // 与gcron模块的区别是,时间轮模块只管理间隔执行任务,并且更注重执行效率(纳秒级别)。 // 需要注意执行时间间隔的准确性问题: https://github.com/golang/go/issues/14410 -package gwheel +package gtimer import ( "math" @@ -22,53 +22,53 @@ const ( gPANIC_EXIT = "exit" gDEFAULT_TIMES = math.MaxInt32 gDEFAULT_SLOT_NUMBER = 10 - gDEFAULT_WHEEL_INTERVAL = 30*time.Millisecond - gDEFAULT_WHEEL_LEVEL = 5 + gDEFAULT_WHEEL_INTERVAL = 50*time.Millisecond + gDEFAULT_WHEEL_LEVEL = 6 ) var ( // 默认的wheel管理对象 - defaultWheels = New(gDEFAULT_SLOT_NUMBER, gDEFAULT_WHEEL_INTERVAL, gDEFAULT_WHEEL_LEVEL) + defaultTimer = New(gDEFAULT_SLOT_NUMBER, gDEFAULT_WHEEL_INTERVAL, gDEFAULT_WHEEL_LEVEL) ) // 添加执行方法,可以给定名字,以便于后续执行删除 func Add(interval time.Duration, job JobFunc) *Entry { - return defaultWheels.Add(interval, job) + return defaultTimer.Add(interval, job) } // 添加单例运行循环任务 func AddSingleton(interval time.Duration, job JobFunc) *Entry { - return defaultWheels.AddSingleton(interval, job) + return defaultTimer.AddSingleton(interval, job) } // 添加只运行一次的循环任务 func AddOnce(interval time.Duration, job JobFunc) *Entry { - return defaultWheels.AddOnce(interval, job) + return defaultTimer.AddOnce(interval, job) } // 添加运行指定次数的循环任务 func AddTimes(interval time.Duration, times int, job JobFunc) *Entry { - return defaultWheels.AddTimes(interval, times, job) + return defaultTimer.AddTimes(interval, times, job) } // 延迟添加循环任务,delay参数单位为秒 func DelayAdd(delay time.Duration, interval time.Duration, job JobFunc) { - defaultWheels.DelayAdd(delay, interval, job) + defaultTimer.DelayAdd(delay, interval, job) } // 延迟添加单例循环任务,delay参数单位为秒 func DelayAddSingleton(delay time.Duration, interval time.Duration, job JobFunc) { - defaultWheels.DelayAddSingleton(delay, interval, job) + defaultTimer.DelayAddSingleton(delay, interval, job) } // 延迟添加只运行一次的循环任务,delay参数单位为秒 func DelayAddOnce(delay time.Duration, interval time.Duration, job JobFunc) { - defaultWheels.DelayAddOnce(delay, interval, job) + defaultTimer.DelayAddOnce(delay, interval, job) } // 延迟添加运行指定次数的循环任务,delay参数单位为秒 func DelayAddTimes(delay time.Duration, interval time.Duration, times int, job JobFunc) { - defaultWheels.DelayAddTimes(delay, interval, times, job) + defaultTimer.DelayAddTimes(delay, interval, times, job) } // 在Job方法中调用,停止当前运行的任务 diff --git a/g/os/gwheel/gwheel_entry.go b/g/os/gtimer/gtimer_entry.go similarity index 89% rename from g/os/gwheel/gwheel_entry.go rename to g/os/gtimer/gtimer_entry.go index 0fb11318f..a7e3c765a 100644 --- a/g/os/gwheel/gwheel_entry.go +++ b/g/os/gtimer/gtimer_entry.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://gitee.com/johng/gf. -package gwheel +package gtimer import ( "gitee.com/johng/gf/g/container/gtype" @@ -13,7 +13,6 @@ import ( // 循环任务项 type Entry struct { - id int64 // ID job JobFunc // 注册循环任务方法 wheel *wheel // 所属时间轮 singleton *gtype.Bool // 任务是否单例运行 @@ -29,7 +28,7 @@ type Entry struct { // 任务执行方法 type JobFunc = func() -// 创建循环任务(失败返回nil) +// 创建定时任务 func (w *wheel) addEntry(interval time.Duration, job JobFunc, singleton bool, times int) *Entry { ms := interval.Nanoseconds()/1e6 num := ms/w.intervalMs @@ -41,7 +40,6 @@ func (w *wheel) addEntry(interval time.Duration, job JobFunc, singleton bool, ti nowMs := time.Now().UnixNano()/1e6 ticks := w.ticks.Val() entry := &Entry { - id : time.Now().UnixNano(), wheel : w, singleton : gtype.NewBool(singleton), status : gtype.NewInt(STATUS_READY), @@ -58,6 +56,18 @@ func (w *wheel) addEntry(interval time.Duration, job JobFunc, singleton bool, ti 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() @@ -95,9 +105,6 @@ func (entry *Entry) Run() { // 检测当前任务是否可运行, 参数为当前时间的纳秒数, 精度更高 func (entry *Entry) check(nowTicks int64, nowMs int64) bool { - //if entry.intervalMs == 1400 { - // fmt.Println(nowTicks, entry.create, entry.interval, time.Now()) - //} // 运行检查 if diff := nowTicks - entry.create; diff > 0 && diff%entry.interval == 0 { // 是否单例 @@ -121,9 +128,8 @@ func (entry *Entry) check(nowTicks int64, nowMs int64) bool { } // 分层转换 if entry.wheel.level > 0 { - if diffMs := nowMs - entry.updateMs; diffMs < entry.intervalMs { + if diffMs := nowMs - entry.updateMs; diffMs < entry.intervalMs { if leftMs := entry.intervalMs - diffMs; leftMs > entry.wheel.wheels.intervalMs { - entry.status.Set(STATUS_CLOSED) delay := time.Duration(leftMs)*time.Millisecond // 往底层添加 entry.wheel.wheels.addEntry(delay, entry.job, false, 1) @@ -136,6 +142,7 @@ func (entry *Entry) check(nowTicks int64, nowMs int64) bool { entry.job, ) } + entry.status.Set(STATUS_CLOSED) return false } } diff --git a/g/os/gwheel/gwheel_loop.go b/g/os/gtimer/gtimer_loop.go similarity index 80% rename from g/os/gwheel/gwheel_loop.go rename to g/os/gtimer/gtimer_loop.go index 74f9d90b9..d21613606 100644 --- a/g/os/gwheel/gwheel_loop.go +++ b/g/os/gtimer/gtimer_loop.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://gitee.com/johng/gf. -package gwheel +package gtimer import ( "gitee.com/johng/gf/g/container/glist" @@ -34,13 +34,14 @@ func (w *wheel) proceed() { l := w.slots[int(n%w.number)] if l.Len() > 0 { go func(l *glist.List, nowTicks int64) { + entry := (*Entry)(nil) nowMs := time.Now().UnixNano()/1e6 for i := l.Len(); i > 0; i-- { - v := l.PopFront() - if v == nil { + if v := l.PopFront(); v == nil { break + } else { + entry = v.(*Entry) } - entry := v.(*Entry) if entry.Status() == STATUS_CLOSED { continue } @@ -65,14 +66,7 @@ func (w *wheel) proceed() { } // 是否继续添运行 if entry.status.Val() != STATUS_CLOSED { - 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) + w.reAddEntry(entry, nowTicks, nowMs) } } }(l, n) diff --git a/g/os/gtimer/gtimer_timer.go b/g/os/gtimer/gtimer_timer.go new file mode 100644 index 000000000..3fcae6e4e --- /dev/null +++ b/g/os/gtimer/gtimer_timer.go @@ -0,0 +1,174 @@ +// 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/glist" + "gitee.com/johng/gf/g/container/gtype" + "time" +) + +// 定时器/分层时间轮 +type Timer struct { + wheels []*wheel // 分层 + length int // 层数 + number int // 每一层Slot Number + intervalMs int64 // 最小时间刻度(毫秒) +} + +// 创建分层时间轮 +func New(slot int, interval time.Duration, level...int) *Timer { + length := gDEFAULT_WHEEL_LEVEL + if len(level) > 0 { + length = level[0] + } + t := &Timer { + wheels : make([]*wheel, length), + length : length, + number : slot, + intervalMs : interval.Nanoseconds()/1e6, + } + for i := 0; i < length; i++ { + if i > 0 { + n := time.Duration(t.wheels[i - 1].totalMs)*time.Millisecond + w := t.newWheel(i, slot, n) + t.wheels[i] = w + t.wheels[i - 1].addEntry(n, w.proceed, false, gDEFAULT_TIMES) + } else { + t.wheels[i] = t.newWheel(i, slot, interval) + } + } + t.wheels[0].start() + return t +} + +// 创建自定义的循环任务管理对象 +func (t *Timer) newWheel(level int, slot int, interval time.Duration) *wheel { + w := &wheel { + wheels : t, + level : level, + slots : make([]*glist.List, slot), + number : int64(slot), + closed : make(chan struct{}, 1), + ticks : gtype.NewInt64(), + totalMs : int64(slot)*interval.Nanoseconds()/1e6, + createMs : time.Now().UnixNano()/1e6, + intervalMs : interval.Nanoseconds()/1e6, + } + for i := int64(0); i < w.number; i++ { + w.slots[i] = glist.New() + } + return w +} + +// 添加循环任务 +func (t *Timer) Add(interval time.Duration, job JobFunc) *Entry { + return t.addEntry(interval, job, false, gDEFAULT_TIMES) +} + +// 添加单例运行循环任务 +func (t *Timer) AddSingleton(interval time.Duration, job JobFunc) *Entry { + return t.addEntry(interval, job, true, gDEFAULT_TIMES) +} + +// 添加只运行一次的循环任务 +func (t *Timer) AddOnce(interval time.Duration, job JobFunc) *Entry { + return t.addEntry(interval, job, false, 1) +} + +// 添加运行指定次数的循环任务 +func (t *Timer) AddTimes(interval time.Duration, times int, job JobFunc) *Entry { + return t.addEntry(interval, job, false, times) +} + +// 延迟添加循环任务 +func (t *Timer) DelayAdd(delay time.Duration, interval time.Duration, job JobFunc) { + t.AddOnce(delay, func() { + t.Add(interval, job) + }) +} + +// 延迟添加单例循环任务 +func (t *Timer) DelayAddSingleton(delay time.Duration, interval time.Duration, job JobFunc) { + t.AddOnce(delay, func() { + t.AddSingleton(interval, job) + }) +} + +// 延迟添加只运行一次的循环任务 +func (t *Timer) DelayAddOnce(delay time.Duration, interval time.Duration, job JobFunc) { + t.AddOnce(delay, func() { + t.AddOnce(interval, job) + }) +} + +// 延迟添加只运行一次的循环任务 +func (t *Timer) DelayAddTimes(delay time.Duration, interval time.Duration, times int, job JobFunc) { + t.AddOnce(delay, func() { + t.AddTimes(interval, times, job) + }) +} + +// 关闭分层时间轮 +func (t *Timer) Close() { + for _, w := range t.wheels { + w.Close() + } +} + +// 添加定时任务 +func (t *Timer) addEntry(interval time.Duration, job JobFunc, singleton bool, times int) *Entry { + intervalMs := interval.Nanoseconds()/1e6 + pos, cmp := t.binSearchIndex(intervalMs) + switch cmp { + // n比最后匹配值小 + case -1: + i := pos + for ; i > 0; i-- { + if intervalMs >= t.wheels[i].intervalMs && intervalMs < t.wheels[i].totalMs { + return t.wheels[i].addEntry(interval, job, singleton, times) + } + } + return t.wheels[i].addEntry(interval, job, singleton, times) + // n比最后匹配值大 + case 1: + i := pos + for ; i < t.length - 1; i++ { + if intervalMs >= t.wheels[i].intervalMs && intervalMs < t.wheels[i].totalMs { + return t.wheels[i].addEntry(interval, job, singleton, times) + } + } + return t.wheels[i].addEntry(interval, job, singleton, times) + + case 0: + return t.wheels[pos].addEntry(interval, job, singleton, times) + } + return nil +} + +// 二分查找当前任务可以添加的时间轮对象索引 +func (t *Timer) binSearchIndex(n int64)(index int, result int) { + min := 0 + max := t.length - 1 + mid := 0 + cmp := -2 + for min <= max { + mid = int((min + max) / 2) + switch { + case t.wheels[mid].intervalMs == n : cmp = 0 + case t.wheels[mid].intervalMs > n : cmp = -1 + case t.wheels[mid].intervalMs < n : cmp = 1 + } + switch cmp { + case -1 : max = mid - 1 + case 1 : min = mid + 1 + case 0 : + return mid, cmp + } + } + return mid, cmp +} \ No newline at end of file diff --git a/g/os/gwheel/gwheel_wheels_wheel.go b/g/os/gtimer/gtimer_wheel.go similarity index 93% rename from g/os/gwheel/gwheel_wheels_wheel.go rename to g/os/gtimer/gtimer_wheel.go index e15e1b12d..91a37eacd 100644 --- a/g/os/gwheel/gwheel_wheels_wheel.go +++ b/g/os/gtimer/gtimer_wheel.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://gitee.com/johng/gf. -package gwheel +package gtimer import ( "gitee.com/johng/gf/g/container/glist" @@ -13,7 +13,7 @@ import ( // 单层时间轮 type wheel struct { - wheels *Wheels // 所属分层时间轮 + wheels *Timer // 所属定时器 level int // 所属分层索引号 slots []*glist.List // 所有的循环任务项, 按照Slot Number进行分组 number int64 // Slot Number diff --git a/g/os/gwheel/gwheel_z_bench_test.go b/g/os/gtimer/gtimer_z_bench_test.go similarity index 83% rename from g/os/gwheel/gwheel_z_bench_test.go rename to g/os/gtimer/gtimer_z_bench_test.go index 950ff6e06..c009fa829 100644 --- a/g/os/gwheel/gwheel_z_bench_test.go +++ b/g/os/gtimer/gtimer_z_bench_test.go @@ -4,10 +4,10 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://gitee.com/johng/gf. -package gwheel_test +package gtimer_test import ( - "gitee.com/johng/gf/g/os/gwheel" + "gitee.com/johng/gf/g/os/gtimer" "testing" "time" ) @@ -16,7 +16,7 @@ import ( func Benchmark_Add(b *testing.B) { for i := 0; i < b.N; i++ { // 基准测试的时候不能设置为1秒,否则大量的任务会崩掉系统 - gwheel.Add(time.Hour, func() { + gtimer.Add(time.Hour, func() { }) } diff --git a/g/os/gwheel/gwheel_z_unit_1_test.go b/g/os/gtimer/gtimer_z_unit_1_test.go similarity index 96% rename from g/os/gwheel/gwheel_z_unit_1_test.go rename to g/os/gtimer/gtimer_z_unit_1_test.go index 1802825dc..45d983d55 100644 --- a/g/os/gwheel/gwheel_z_unit_1_test.go +++ b/g/os/gtimer/gtimer_z_unit_1_test.go @@ -6,19 +6,19 @@ // 包方法操作 -package gwheel_test +package gtimer_test import ( "gitee.com/johng/gf/g/container/garray" - "gitee.com/johng/gf/g/os/gwheel" + "gitee.com/johng/gf/g/os/gtimer" "gitee.com/johng/gf/g/util/gtest" "testing" "time" ) -func New() *gwheel.Wheels { - return gwheel.New(10, 10*time.Millisecond) +func New() *gtimer.Timer { + return gtimer.New(10, 10*time.Millisecond) } func TestWheel_Add_Close(t *testing.T) { @@ -142,7 +142,7 @@ func TestWheel_ExitJob(t *testing.T) { array := garray.New(0, 0) wheel.Add(time.Second, func() { array.Append(1) - gwheel.Exit() + gtimer.Exit() }) time.Sleep(1200*time.Millisecond) gtest.Assert(array.Len(), 1) diff --git a/g/os/gwheel/gwheel_z_unit_2_test.go b/g/os/gtimer/gtimer_z_unit_2_test.go similarity index 98% rename from g/os/gwheel/gwheel_z_unit_2_test.go rename to g/os/gtimer/gtimer_z_unit_2_test.go index 2595c15af..9a783798b 100644 --- a/g/os/gwheel/gwheel_z_unit_2_test.go +++ b/g/os/gtimer/gtimer_z_unit_2_test.go @@ -6,7 +6,7 @@ // Entry操作 -package gwheel_test +package gtimer_test import ( "gitee.com/johng/gf/g/container/garray" diff --git a/g/os/gwheel/gwheel_z_unit_3_test.go b/g/os/gtimer/gtimer_z_unit_3_test.go similarity index 97% rename from g/os/gwheel/gwheel_z_unit_3_test.go rename to g/os/gtimer/gtimer_z_unit_3_test.go index eba64b243..cc2acd478 100644 --- a/g/os/gwheel/gwheel_z_unit_3_test.go +++ b/g/os/gtimer/gtimer_z_unit_3_test.go @@ -6,7 +6,7 @@ // 指定次数运行测试 -package gwheel_test +package gtimer_test import ( "gitee.com/johng/gf/g/container/garray" diff --git a/g/os/gwheel/gwheel_wheels.go b/g/os/gwheel/gwheel_wheels.go deleted file mode 100644 index f6e7972e2..000000000 --- a/g/os/gwheel/gwheel_wheels.go +++ /dev/null @@ -1,174 +0,0 @@ -// 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 gwheel - -import ( - "gitee.com/johng/gf/g/container/glist" - "gitee.com/johng/gf/g/container/gtype" - "time" -) - -// 分层时间轮 -type Wheels struct { - levels []*wheel // 分层 - length int // 层数 - number int // 每一层Slot Number - intervalMs int64 // 最小时间刻度(毫秒) -} - -// 创建分层时间轮 -func New(slot int, interval time.Duration, level...int) *Wheels { - length := gDEFAULT_WHEEL_LEVEL - if len(level) > 0 { - length = level[0] - } - ws := &Wheels { - levels : make([]*wheel, length), - length : length, - number : slot, - intervalMs : interval.Nanoseconds()/1e6, - } - for i := 0; i < length; i++ { - if i > 0 { - n := time.Duration(ws.levels[i - 1].totalMs)*time.Millisecond - w := ws.newWheel(i, slot, n) - ws.levels[i] = w - ws.levels[i - 1].addEntry(n, w.proceed, false, gDEFAULT_TIMES) - } else { - ws.levels[i] = ws.newWheel(i, slot, interval) - } - } - ws.levels[0].start() - return ws -} - -// 创建自定义的循环任务管理对象 -func (ws *Wheels) newWheel(level int, slot int, interval time.Duration) *wheel { - w := &wheel { - wheels : ws, - level : level, - slots : make([]*glist.List, slot), - number : int64(slot), - closed : make(chan struct{}, 1), - ticks : gtype.NewInt64(), - totalMs : int64(slot)*interval.Nanoseconds()/1e6, - createMs : time.Now().UnixNano()/1e6, - intervalMs : interval.Nanoseconds()/1e6, - } - for i := int64(0); i < w.number; i++ { - w.slots[i] = glist.New() - } - return w -} - -// 添加循环任务 -func (ws *Wheels) Add(interval time.Duration, job JobFunc) *Entry { - return ws.addEntry(interval, job, false, gDEFAULT_TIMES) -} - -// 添加单例运行循环任务 -func (ws *Wheels) AddSingleton(interval time.Duration, job JobFunc) *Entry { - return ws.addEntry(interval, job, true, gDEFAULT_TIMES) -} - -// 添加只运行一次的循环任务 -func (ws *Wheels) AddOnce(interval time.Duration, job JobFunc) *Entry { - return ws.addEntry(interval, job, false, 1) -} - -// 添加运行指定次数的循环任务 -func (ws *Wheels) AddTimes(interval time.Duration, times int, job JobFunc) *Entry { - return ws.addEntry(interval, job, false, times) -} - -// 延迟添加循环任务 -func (ws *Wheels) DelayAdd(delay time.Duration, interval time.Duration, job JobFunc) { - ws.AddOnce(delay, func() { - ws.Add(interval, job) - }) -} - -// 延迟添加单例循环任务 -func (ws *Wheels) DelayAddSingleton(delay time.Duration, interval time.Duration, job JobFunc) { - ws.AddOnce(delay, func() { - ws.AddSingleton(interval, job) - }) -} - -// 延迟添加只运行一次的循环任务 -func (ws *Wheels) DelayAddOnce(delay time.Duration, interval time.Duration, job JobFunc) { - ws.AddOnce(delay, func() { - ws.AddOnce(interval, job) - }) -} - -// 延迟添加只运行一次的循环任务 -func (ws *Wheels) DelayAddTimes(delay time.Duration, interval time.Duration, times int, job JobFunc) { - ws.AddOnce(delay, func() { - ws.AddTimes(interval, times, job) - }) -} - -// 关闭分层时间轮 -func (ws *Wheels) Close() { - for _, w := range ws.levels { - w.Close() - } -} - -// 添加循环任务 -func (ws *Wheels) addEntry(interval time.Duration, job JobFunc, singleton bool, times int) *Entry { - intervalMs := interval.Nanoseconds()/1e6 - pos, cmp := ws.binSearchIndex(intervalMs) - switch cmp { - // n比最后匹配值小 - case -1: - i := pos - for ; i > 0; i-- { - if intervalMs > ws.levels[i].totalMs { - return ws.levels[i].addEntry(interval, job, singleton, times) - } - } - return ws.levels[i].addEntry(interval, job, singleton, times) - // n比最后匹配值大 - case 1: - i := pos - for ; i < ws.length - 1; i++ { - if intervalMs < ws.levels[i].totalMs { - return ws.levels[i].addEntry(interval, job, singleton, times) - } - } - return ws.levels[i].addEntry(interval, job, singleton, times) - - case 0: - return ws.levels[pos].addEntry(interval, job, singleton, times) - } - return nil -} - - -func (ws *Wheels) binSearchIndex(n int64)(index int, result int) { - min := 0 - max := ws.length - 1 - mid := 0 - cmp := -2 - for min <= max { - mid = int((min + max) / 2) - switch { - case ws.levels[mid].totalMs == n : cmp = 0 - case ws.levels[mid].totalMs > n : cmp = -1 - case ws.levels[mid].totalMs < n : cmp = 1 - } - switch cmp { - case -1 : max = mid - 1 - case 1 : min = mid + 1 - case 0 : - return mid, cmp - } - } - return mid, cmp -} \ No newline at end of file diff --git a/geg/os/gwheel/gwheel1.go b/geg/os/gtimer/gtimer1.go similarity index 67% rename from geg/os/gwheel/gwheel1.go rename to geg/os/gtimer/gtimer1.go index 43fc75e2b..9d1d525bd 100644 --- a/geg/os/gwheel/gwheel1.go +++ b/geg/os/gtimer/gtimer1.go @@ -2,14 +2,14 @@ package main import ( "fmt" - "gitee.com/johng/gf/g/os/gwheel" + "gitee.com/johng/gf/g/os/gtimer" "time" ) func main() { now := time.Now() - interval := 1400*time.Millisecond - gwheel.Add(interval, func() { + interval := 1000*time.Millisecond + gtimer.Add(interval, func() { fmt.Println(time.Now(), time.Duration(time.Now().UnixNano() - now.UnixNano())) now = time.Now() }) diff --git a/geg/os/gwheel/gwheel2.go b/geg/os/gtimer/gtimer2.go similarity index 64% rename from geg/os/gwheel/gwheel2.go rename to geg/os/gtimer/gtimer2.go index beda19d48..50c3260b4 100644 --- a/geg/os/gwheel/gwheel2.go +++ b/geg/os/gtimer/gtimer2.go @@ -3,24 +3,24 @@ package main import ( "fmt" "gitee.com/johng/gf/g/container/gtype" - "gitee.com/johng/gf/g/os/gwheel" + "gitee.com/johng/gf/g/os/gtimer" "time" ) func main() { v := gtype.NewInt() - w := gwheel.New(10, 10*time.Millisecond) + //w := gtimer.New(10, 10*time.Millisecond) fmt.Println("start:", time.Now()) for i := 0; i < 1000000; i++ { - w.AddOnce(time.Second, func() { + gtimer.AddOnce(time.Second, func() { v.Add(1) }) } fmt.Println("end :", time.Now()) - time.Sleep(3020*time.Millisecond) + time.Sleep(1300*time.Millisecond) fmt.Println(v.Val(), time.Now()) - //gwheel.AddSingleton(time.Second, func() { + //gtimer.AddSingleton(time.Second, func() { // fmt.Println(time.Now().String()) //}) //select { } diff --git a/geg/os/gwheel/sleep1.go b/geg/os/gtimer/sleep1.go similarity index 100% rename from geg/os/gwheel/sleep1.go rename to geg/os/gtimer/sleep1.go diff --git a/geg/os/gwheel/sleep2.go b/geg/os/gtimer/sleep2.go similarity index 100% rename from geg/os/gwheel/sleep2.go rename to geg/os/gtimer/sleep2.go diff --git a/geg/os/gwheel/ticker1.go b/geg/os/gtimer/ticker1.go similarity index 100% rename from geg/os/gwheel/ticker1.go rename to geg/os/gtimer/ticker1.go diff --git a/geg/os/gwheel/ticker2.go b/geg/os/gtimer/ticker2.go similarity index 100% rename from geg/os/gwheel/ticker2.go rename to geg/os/gtimer/ticker2.go