diff --git a/g/container/gpool/gpool.go b/g/container/gpool/gpool.go index 4cff7adce..844e0acfe 100644 --- a/g/container/gpool/gpool.go +++ b/g/container/gpool/gpool.go @@ -15,6 +15,7 @@ import ( "gitee.com/johng/gf/g/container/gtype" "gitee.com/johng/gf/g/os/gtime" "gitee.com/johng/gf/g/os/gtimer" + "time" ) // 对象池 @@ -45,7 +46,7 @@ func New(expire int, newFunc...func() (interface{}, error)) *Pool { if len(newFunc) > 0 { r.NewFunc = newFunc[0] } - //gtimer.AddSingleton(time.Second, r.checkExpire) + gtimer.AddSingleton(time.Second, r.checkExpire) return r } diff --git a/g/os/gcache/gcache_cache.go b/g/os/gcache/gcache_cache.go index 290f26907..c3d67d17f 100644 --- a/g/os/gcache/gcache_cache.go +++ b/g/os/gcache/gcache_cache.go @@ -7,7 +7,9 @@ package gcache import ( + "gitee.com/johng/gf/g/os/gtimer" "sync/atomic" + "time" "unsafe" ) @@ -22,7 +24,7 @@ func New(lruCap...int) *Cache { c := &Cache { memCache : newMemCache(lruCap...), } - //gtimer.AddSingleton(time.Second, c.syncEventAndClearExpired) + gtimer.AddSingleton(time.Second, c.syncEventAndClearExpired) return c } diff --git a/g/os/gcache/gcache_mem_cache_lru.go b/g/os/gcache/gcache_mem_cache_lru.go index cfaa6673e..9da2d6dd9 100644 --- a/g/os/gcache/gcache_mem_cache_lru.go +++ b/g/os/gcache/gcache_mem_cache_lru.go @@ -12,6 +12,7 @@ import ( "gitee.com/johng/gf/g/container/gmap" "gitee.com/johng/gf/g/container/gtype" "gitee.com/johng/gf/g/os/gtimer" + "time" ) // LRU算法实现对象,底层双向链表使用了标准库的list.List @@ -32,7 +33,7 @@ func newMemCacheLru(cache *memCache) *memCacheLru { rawList : glist.New(), closed : gtype.NewBool(), } - //gtimer.AddSingleton(time.Second, lru.SyncAndClear) + gtimer.AddSingleton(time.Second, lru.SyncAndClear) return lru } diff --git a/g/os/gtimer/gtimer_entry.go b/g/os/gtimer/gtimer_entry.go index c48fe7bca..871a06e1d 100644 --- a/g/os/gtimer/gtimer_entry.go +++ b/g/os/gtimer/gtimer_entry.go @@ -133,7 +133,7 @@ func (entry *Entry) check(nowTicks int64, nowMs int64) (runnable, addable bool) case STATUS_CLOSED: return false, false } - // 时间轮客户端判断,是否满足运行刻度条件,误差会比较大 + // 时间轮刻度判断,是否满足运行刻度条件,刻度判断的误差会比较大 if diff := nowTicks - entry.create; diff > 0 && diff%entry.interval == 0 { // 分层转换处理 if entry.wheel.level > 0 { @@ -148,6 +148,7 @@ func (entry *Entry) check(nowTicks int64, nowMs int64) (runnable, addable bool) case diffMs >= entry.wheel.timer.intervalMs: // 任务是否有必要进行分层转换 if leftMs := entry.intervalMs - diffMs; leftMs > entry.wheel.timer.intervalMs { + // 往底层添加,通过毫秒计算并重新添加任务到对应的时间轮上,减小运行误差 entry.wheel.timer.doAddEntryByParent(leftMs, entry) return false, false diff --git a/g/os/gtimer/gtimer_loop.go b/g/os/gtimer/gtimer_loop.go index f62de6d25..a61553d87 100644 --- a/g/os/gtimer/gtimer_loop.go +++ b/g/os/gtimer/gtimer_loop.go @@ -19,9 +19,9 @@ func (w *wheel) start() { select { case <- ticker.C: switch w.timer.status.Val() { - case STATUS_READY: fallthrough case STATUS_RUNNING: w.proceed() + case STATUS_STOPPED: case STATUS_CLOSED: ticker.Stop() diff --git a/g/os/gtimer/gtimer_z_unit_0_test.go b/g/os/gtimer/gtimer_z_unit_0_test.go new file mode 100644 index 000000000..4695cd6a9 --- /dev/null +++ b/g/os/gtimer/gtimer_z_unit_0_test.go @@ -0,0 +1,140 @@ +// Copyright 2018 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 functions + +package gtimer_test + +import ( + "gitee.com/johng/gf/g/container/garray" + "gitee.com/johng/gf/g/os/gtimer" + "gitee.com/johng/gf/g/util/gtest" + "testing" + "time" +) + + +func TestSetTimeout(t *testing.T) { + gtest.Case(t, func() { + array := garray.New(0, 0) + gtimer.SetTimeout(200*time.Millisecond, func() { + array.Append(1) + }) + time.Sleep(1000*time.Millisecond) + gtest.Assert(array.Len(), 1) + }) +} + +func TestSetInterval(t *testing.T) { + gtest.Case(t, func() { + array := garray.New(0, 0) + gtimer.SetInterval(200*time.Millisecond, func() { + array.Append(1) + }) + time.Sleep(1100*time.Millisecond) + gtest.Assert(array.Len(), 5) + }) +} + +func TestAddEntry(t *testing.T) { + gtest.Case(t, func() { + array := garray.New(0, 0) + gtimer.AddEntry(200*time.Millisecond, func() { + array.Append(1) + }, false, 2) + time.Sleep(1100*time.Millisecond) + gtest.Assert(array.Len(), 2) + }) +} + +func TestAddSingleton(t *testing.T) { + gtest.Case(t, func() { + array := garray.New(0, 0) + gtimer.AddSingleton(200*time.Millisecond, func() { + array.Append(1) + time.Sleep(10000*time.Millisecond) + }) + time.Sleep(1100*time.Millisecond) + gtest.Assert(array.Len(), 1) + }) +} + +func TestAddTimes(t *testing.T) { + gtest.Case(t, func() { + array := garray.New(0, 0) + gtimer.AddTimes(200*time.Millisecond, 2, func() { + array.Append(1) + }) + time.Sleep(1000*time.Millisecond) + gtest.Assert(array.Len(), 2) + }) +} + +func TestDelayAdd(t *testing.T) { + gtest.Case(t, func() { + array := garray.New(0, 0) + gtimer.DelayAdd(200*time.Millisecond, 200*time.Millisecond, func() { + array.Append(1) + }) + time.Sleep(300*time.Millisecond) + gtest.Assert(array.Len(), 0) + time.Sleep(200*time.Millisecond) + gtest.Assert(array.Len(), 1) + }) +} + +func TestDelayAddEntry(t *testing.T) { + gtest.Case(t, func() { + array := garray.New(0, 0) + gtimer.DelayAddEntry(200*time.Millisecond, 200*time.Millisecond, func() { + array.Append(1) + }, false, 2) + time.Sleep(300*time.Millisecond) + gtest.Assert(array.Len(), 0) + time.Sleep(1000*time.Millisecond) + gtest.Assert(array.Len(), 2) + }) +} + +func TestDelayAddSingleton(t *testing.T) { + gtest.Case(t, func() { + array := garray.New(0, 0) + gtimer.DelayAddSingleton(200*time.Millisecond, 200*time.Millisecond, func() { + array.Append(1) + time.Sleep(10000*time.Millisecond) + }) + time.Sleep(300*time.Millisecond) + gtest.Assert(array.Len(), 0) + time.Sleep(1000*time.Millisecond) + gtest.Assert(array.Len(), 1) + }) +} + +func TestDelayAddOnce(t *testing.T) { + gtest.Case(t, func() { + array := garray.New(0, 0) + gtimer.DelayAddOnce(200*time.Millisecond, 200*time.Millisecond, func() { + array.Append(1) + }) + time.Sleep(300*time.Millisecond) + gtest.Assert(array.Len(), 0) + time.Sleep(1000*time.Millisecond) + gtest.Assert(array.Len(), 1) + }) +} + +func TestDelayAddTimes(t *testing.T) { + gtest.Case(t, func() { + array := garray.New(0, 0) + gtimer.DelayAddTimes(200*time.Millisecond, 200*time.Millisecond, 2, func() { + array.Append(1) + }) + time.Sleep(300*time.Millisecond) + gtest.Assert(array.Len(), 0) + time.Sleep(1000*time.Millisecond) + gtest.Assert(array.Len(), 2) + }) +} diff --git a/g/os/gtimer/gtimer_z_unit_1_test.go b/g/os/gtimer/gtimer_z_unit_1_test.go index 1cc939399..20c745b0f 100644 --- a/g/os/gtimer/gtimer_z_unit_1_test.go +++ b/g/os/gtimer/gtimer_z_unit_1_test.go @@ -21,53 +21,31 @@ func New() *gtimer.Timer { return gtimer.New(10, 10*time.Millisecond) } -func TestSetTimeout(t *testing.T) { - gtest.Case(t, func() { - array := garray.New(0, 0) - gtimer.SetTimeout(200*time.Millisecond, func() { - array.Append(1) - }) - time.Sleep(1000*time.Millisecond) - gtest.Assert(array.Len(), 1) - }) -} - -func TestSetInterval(t *testing.T) { - gtest.Case(t, func() { - array := garray.New(0, 0) - gtimer.SetInterval(200*time.Millisecond, func() { - array.Append(1) - }) - time.Sleep(1100*time.Millisecond) - gtest.Assert(array.Len(), 5) - }) -} - func TestTimer_Add_Close(t *testing.T) { gtest.Case(t, func() { timer := New() array := garray.New(0, 0) //fmt.Println("start", time.Now()) - timer.Add(time.Second, func() { + timer.Add(200*time.Millisecond, func() { //fmt.Println("entry1", time.Now()) array.Append(1) }) - timer.Add(time.Second, func() { + timer.Add(200*time.Millisecond, func() { //fmt.Println("entry2", time.Now()) array.Append(1) }) - timer.Add(2*time.Second, func() { + timer.Add(400*time.Millisecond, func() { //fmt.Println("entry3", time.Now()) array.Append(1) }) - time.Sleep(1300*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 2) - time.Sleep(1300*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 5) timer.Close() - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) fixedLength := array.Len() - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), fixedLength) }) } @@ -99,14 +77,14 @@ func TestTimer_AddSingleton(t *testing.T) { gtest.Case(t, func() { timer := New() array := garray.New(0, 0) - timer.AddSingleton(time.Second, func() { + timer.AddSingleton(200*time.Millisecond, func() { array.Append(1) time.Sleep(10*time.Second) }) - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 1) - time.Sleep(1200*time.Millisecond) + time.Sleep(500*time.Millisecond) gtest.Assert(array.Len(), 1) }) } @@ -115,20 +93,20 @@ func TestTimer_AddOnce(t *testing.T) { gtest.Case(t, func() { timer := New() array := garray.New(0, 0) - timer.AddOnce(time.Second, func() { + timer.AddOnce(200*time.Millisecond, func() { array.Append(1) }) - timer.AddOnce(time.Second, func() { + timer.AddOnce(200*time.Millisecond, func() { array.Append(1) }) - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 2) - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 2) timer.Close() - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) fixedLength := array.Len() - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), fixedLength) }) } @@ -137,10 +115,10 @@ func TestTimer_AddTimes(t *testing.T) { gtest.Case(t, func() { timer := New() array := garray.New(0, 0) - timer.AddTimes(time.Second, 2, func() { + timer.AddTimes(200*time.Millisecond, 2, func() { array.Append(1) }) - time.Sleep(3500*time.Millisecond) + time.Sleep(1000*time.Millisecond) gtest.Assert(array.Len(), 2) }) } @@ -149,28 +127,42 @@ func TestTimer_DelayAdd(t *testing.T) { gtest.Case(t, func() { timer := New() array := garray.New(0, 0) - timer.DelayAdd(time.Second, time.Second, func() { + timer.DelayAdd(200*time.Millisecond, 200*time.Millisecond, func() { array.Append(1) }) - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 0) - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 1) }) } +func TestTimer_DelayAddEntry(t *testing.T) { + gtest.Case(t, func() { + timer := New() + array := garray.New(0, 0) + timer.DelayAddEntry(200*time.Millisecond, 200*time.Millisecond, func() { + array.Append(1) + }, false, 100) + time.Sleep(250*time.Millisecond) + gtest.Assert(array.Len(), 0) + time.Sleep(250*time.Millisecond) + gtest.Assert(array.Len(), 1) + }) +} + func TestTimer_DelayAddSingleton(t *testing.T) { gtest.Case(t, func() { timer := New() array := garray.New(0, 0) - timer.DelayAddSingleton(time.Second, time.Second, func() { + timer.DelayAddSingleton(200*time.Millisecond, 200*time.Millisecond, func() { array.Append(1) time.Sleep(10*time.Second) }) - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 0) - time.Sleep(1200*time.Millisecond) + time.Sleep(1000*time.Millisecond) gtest.Assert(array.Len(), 1) }) } @@ -179,16 +171,16 @@ func TestTimer_DelayAddOnce(t *testing.T) { gtest.Case(t, func() { timer := New() array := garray.New(0, 0) - timer.DelayAddOnce(time.Second, time.Second, func() { + timer.DelayAddOnce(200*time.Millisecond, 200*time.Millisecond, func() { array.Append(1) }) - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 0) - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 1) - time.Sleep(1200*time.Millisecond) + time.Sleep(500*time.Millisecond) gtest.Assert(array.Len(), 1) }) } @@ -214,6 +206,41 @@ func TestTimer_DelayAddTimes(t *testing.T) { }) } +func TestTimer_AddLessThanInterval(t *testing.T) { + gtest.Case(t, func() { + timer := gtimer.New(10, 100*time.Millisecond) + array := garray.New(0, 0) + timer.Add(20*time.Millisecond, func() { + array.Append(1) + }) + time.Sleep(50*time.Millisecond) + gtest.Assert(array.Len(), 0) + + time.Sleep(110*time.Millisecond) + gtest.Assert(array.Len(), 1) + + time.Sleep(110*time.Millisecond) + gtest.Assert(array.Len(), 2) + }) +} + +func TestTimer_AddLeveledEntry1(t *testing.T) { + gtest.Case(t, func() { + timer := New() + array := garray.New(0, 0) + //glog.Println("start") + timer.DelayAdd(1000*time.Millisecond, 1001*time.Millisecond, func() { + //glog.Println("add") + array.Append(1) + }) + time.Sleep(1500*time.Millisecond) + gtest.Assert(array.Len(), 0) + time.Sleep(1200*time.Millisecond) + //glog.Println("check") + gtest.Assert(array.Len(), 1) + }) +} + func TestTimer_Exit(t *testing.T) { gtest.Case(t, func() { timer := New() @@ -226,3 +253,4 @@ func TestTimer_Exit(t *testing.T) { gtest.Assert(array.Len(), 1) }) } + diff --git a/g/os/gtimer/gtimer_z_unit_2_test.go b/g/os/gtimer/gtimer_z_unit_2_test.go index 30b0ae9f4..41a9393bb 100644 --- a/g/os/gtimer/gtimer_z_unit_2_test.go +++ b/g/os/gtimer/gtimer_z_unit_2_test.go @@ -19,19 +19,19 @@ import ( func TestEntry_Start_Stop_Close(t *testing.T) { timer := New() array := garray.New(0, 0) - entry := timer.Add(time.Second, func() { + entry := timer.Add(200*time.Millisecond, func() { array.Append(1) }) - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 1) entry.Stop() - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 1) entry.Start() - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 2) entry.Close() - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 2) gtest.Assert(entry.Status(), gtimer.STATUS_CLOSED) @@ -40,17 +40,17 @@ func TestEntry_Start_Stop_Close(t *testing.T) { func TestEntry_Singleton(t *testing.T) { timer := New() array := garray.New(0, 0) - entry := timer.Add(time.Second, func() { + entry := timer.Add(200*time.Millisecond, func() { array.Append(1) time.Sleep(10*time.Second) }) gtest.Assert(entry.IsSingleton(), false) entry.SetSingleton(true) gtest.Assert(entry.IsSingleton(), true) - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 1) - time.Sleep(1200*time.Millisecond) + time.Sleep(250*time.Millisecond) gtest.Assert(array.Len(), 1) } @@ -65,3 +65,13 @@ func TestEntry_SetTimes(t *testing.T) { gtest.Assert(array.Len(), 2) } +func TestEntry_Run(t *testing.T) { + timer := New() + array := garray.New(0, 0) + entry := timer.Add(1000*time.Millisecond, func() { + array.Append(1) + }) + entry.Run() + gtest.Assert(array.Len(), 1) +} + diff --git a/geg/os/gtimer/gtimer1.go b/geg/os/gtimer/gtimer1.go index e811fc3fc..708a298aa 100644 --- a/geg/os/gtimer/gtimer1.go +++ b/geg/os/gtimer/gtimer1.go @@ -8,7 +8,7 @@ import ( func main() { now := time.Now() - interval := 1400*time.Millisecond + interval := 510*time.Millisecond gtimer.Add(interval, func() { fmt.Println(time.Now(), time.Duration(time.Now().UnixNano() - now.UnixNano())) now = time.Now()