mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-03 22:45:13 +08:00
新增安全定时器功能接口;优化定时器性能
This commit is contained in:
@@ -7,18 +7,19 @@ import (
|
|||||||
rpcHandle "github.com/duanhf2012/origin/rpc"
|
rpcHandle "github.com/duanhf2012/origin/rpc"
|
||||||
"github.com/duanhf2012/origin/util/timer"
|
"github.com/duanhf2012/origin/util/timer"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
const InitModuleId = 1e17
|
const InitModuleId = 1e9
|
||||||
|
|
||||||
type IModule interface {
|
type IModule interface {
|
||||||
SetModuleId(moduleId int64) bool
|
SetModuleId(moduleId uint32) bool
|
||||||
GetModuleId() int64
|
GetModuleId() uint32
|
||||||
AddModule(module IModule) (int64,error)
|
AddModule(module IModule) (uint32,error)
|
||||||
GetModule(moduleId int64) IModule
|
GetModule(moduleId uint32) IModule
|
||||||
GetAncestor()IModule
|
GetAncestor()IModule
|
||||||
ReleaseModule(moduleId int64)
|
ReleaseModule(moduleId uint32)
|
||||||
NewModuleId() int64
|
NewModuleId() uint32
|
||||||
GetParent()IModule
|
GetParent()IModule
|
||||||
OnInit() error
|
OnInit() error
|
||||||
OnRelease()
|
OnRelease()
|
||||||
@@ -37,24 +38,25 @@ type IModuleTimer interface {
|
|||||||
|
|
||||||
type Module struct {
|
type Module struct {
|
||||||
rpcHandle.IRpcHandler
|
rpcHandle.IRpcHandler
|
||||||
moduleId int64 //模块Id
|
moduleId uint32 //模块Id
|
||||||
moduleName string //模块名称
|
moduleName string //模块名称
|
||||||
parent IModule //父亲
|
parent IModule //父亲
|
||||||
self IModule //自己
|
self IModule //自己
|
||||||
child map[int64]IModule //孩子们
|
child map[uint32]IModule //孩子们
|
||||||
mapActiveTimer map[*timer.Timer]interface{}
|
mapActiveTimer map[timer.ITimer]struct{}
|
||||||
|
mapActiveIdTimer map[uint64]timer.ITimer
|
||||||
dispatcher *timer.Dispatcher //timer
|
dispatcher *timer.Dispatcher //timer
|
||||||
|
|
||||||
//根结点
|
//根结点
|
||||||
ancestor IModule //始祖
|
ancestor IModule //始祖
|
||||||
seedModuleId int64 //模块id种子
|
seedModuleId uint32 //模块id种子
|
||||||
descendants map[int64]IModule //始祖的后裔们
|
descendants map[uint32]IModule //始祖的后裔们
|
||||||
|
|
||||||
//事件管道
|
//事件管道
|
||||||
eventHandler event.IEventHandler
|
eventHandler event.IEventHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) SetModuleId(moduleId int64) bool{
|
func (m *Module) SetModuleId(moduleId uint32) bool{
|
||||||
if m.moduleId > 0 {
|
if m.moduleId > 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -63,7 +65,7 @@ func (m *Module) SetModuleId(moduleId int64) bool{
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) GetModuleId() int64{
|
func (m *Module) GetModuleId() uint32{
|
||||||
return m.moduleId
|
return m.moduleId
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +77,7 @@ func (m *Module) OnInit() error{
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) AddModule(module IModule) (int64,error){
|
func (m *Module) AddModule(module IModule) (uint32,error){
|
||||||
//没有事件处理器不允许加入其他模块
|
//没有事件处理器不允许加入其他模块
|
||||||
if m.GetEventProcessor() == nil {
|
if m.GetEventProcessor() == nil {
|
||||||
return 0,fmt.Errorf("module %+v Event Processor is nil", m.self)
|
return 0,fmt.Errorf("module %+v Event Processor is nil", m.self)
|
||||||
@@ -87,7 +89,7 @@ func (m *Module) AddModule(module IModule) (int64,error){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if m.child == nil {
|
if m.child == nil {
|
||||||
m.child = map[int64]IModule{}
|
m.child = map[uint32]IModule{}
|
||||||
}
|
}
|
||||||
_,ok := m.child[module.GetModuleId()]
|
_,ok := m.child[module.GetModuleId()]
|
||||||
if ok == true {
|
if ok == true {
|
||||||
@@ -113,7 +115,7 @@ func (m *Module) AddModule(module IModule) (int64,error){
|
|||||||
return module.GetModuleId(),nil
|
return module.GetModuleId(),nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) ReleaseModule(moduleId int64){
|
func (m *Module) ReleaseModule(moduleId uint32){
|
||||||
pModule := m.GetModule(moduleId).getBaseModule().(*Module)
|
pModule := m.GetModule(moduleId).getBaseModule().(*Module)
|
||||||
|
|
||||||
//释放子孙
|
//释放子孙
|
||||||
@@ -128,6 +130,10 @@ func (m *Module) ReleaseModule(moduleId int64){
|
|||||||
pTimer.Cancel()
|
pTimer.Cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _,t := range pModule.mapActiveIdTimer {
|
||||||
|
t.Cancel()
|
||||||
|
}
|
||||||
|
|
||||||
delete(m.child,moduleId)
|
delete(m.child,moduleId)
|
||||||
delete (m.ancestor.getBaseModule().(*Module).descendants,moduleId)
|
delete (m.ancestor.getBaseModule().(*Module).descendants,moduleId)
|
||||||
|
|
||||||
@@ -140,18 +146,32 @@ func (m *Module) ReleaseModule(moduleId int64){
|
|||||||
pModule.ancestor = nil
|
pModule.ancestor = nil
|
||||||
pModule.descendants = nil
|
pModule.descendants = nil
|
||||||
pModule.IRpcHandler = nil
|
pModule.IRpcHandler = nil
|
||||||
|
pModule.mapActiveIdTimer = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) NewModuleId() int64{
|
func (m *Module) NewModuleId() uint32{
|
||||||
m.ancestor.getBaseModule().(*Module).seedModuleId+=1
|
m.ancestor.getBaseModule().(*Module).seedModuleId+=1
|
||||||
return m.ancestor.getBaseModule().(*Module).seedModuleId
|
return m.ancestor.getBaseModule().(*Module).seedModuleId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var timerSeedId uint32
|
||||||
|
func (m *Module) GenTimerId() uint64{
|
||||||
|
for{
|
||||||
|
newTimerId := (uint64(m.GetModuleId())<<32)|uint64(atomic.AddUint32(&timerSeedId,1))
|
||||||
|
if _,ok := m.mapActiveIdTimer[newTimerId];ok == true {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return newTimerId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (m *Module) GetAncestor()IModule{
|
func (m *Module) GetAncestor()IModule{
|
||||||
return m.ancestor
|
return m.ancestor
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) GetModule(moduleId int64) IModule{
|
func (m *Module) GetModule(moduleId uint32) IModule{
|
||||||
iModule,ok := m.GetAncestor().getBaseModule().(*Module).descendants[moduleId]
|
iModule,ok := m.GetAncestor().getBaseModule().(*Module).descendants[moduleId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return nil
|
return nil
|
||||||
@@ -167,40 +187,108 @@ func (m *Module) GetParent()IModule{
|
|||||||
return m.parent
|
return m.parent
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) OnCloseTimer(timer *timer.Timer){
|
func (m *Module) OnCloseTimer(t timer.ITimer){
|
||||||
delete(m.mapActiveTimer,timer)
|
delete(m.mapActiveIdTimer,t.GetId())
|
||||||
|
delete(m.mapActiveTimer,t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) OnAddTimer(t *timer.Timer){
|
func (m *Module) OnAddTimer(t timer.ITimer){
|
||||||
if t != nil {
|
if t != nil {
|
||||||
m.mapActiveTimer[t] = nil
|
if m.mapActiveTimer == nil {
|
||||||
|
m.mapActiveTimer = map[timer.ITimer]struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.mapActiveTimer[t] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) AfterFunc(d time.Duration, cb func(*timer.Timer)) *timer.Timer {
|
func (m *Module) AfterFunc(d time.Duration, cb func(*timer.Timer)) *timer.Timer {
|
||||||
if m.mapActiveTimer == nil {
|
if m.mapActiveTimer == nil {
|
||||||
m.mapActiveTimer =map[*timer.Timer]interface{}{}
|
m.mapActiveTimer =map[timer.ITimer]struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.dispatcher.AfterFunc(d,cb,m.OnCloseTimer,m.OnAddTimer)
|
return m.dispatcher.AfterFunc(d,nil,cb,m.OnCloseTimer,m.OnAddTimer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) CronFunc(cronExpr *timer.CronExpr, cb func(*timer.Cron)) *timer.Cron {
|
func (m *Module) CronFunc(cronExpr *timer.CronExpr, cb func(*timer.Cron)) *timer.Cron {
|
||||||
if m.mapActiveTimer == nil {
|
if m.mapActiveTimer == nil {
|
||||||
m.mapActiveTimer =map[*timer.Timer]interface{}{}
|
m.mapActiveTimer =map[timer.ITimer]struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.dispatcher.CronFunc(cronExpr,cb,m.OnCloseTimer,m.OnAddTimer)
|
return m.dispatcher.CronFunc(cronExpr,nil,cb,m.OnCloseTimer,m.OnAddTimer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) NewTicker(d time.Duration, cb func(*timer.Ticker)) *timer.Ticker {
|
func (m *Module) NewTicker(d time.Duration, cb func(*timer.Ticker)) *timer.Ticker {
|
||||||
if m.mapActiveTimer == nil {
|
if m.mapActiveTimer == nil {
|
||||||
m.mapActiveTimer =map[*timer.Timer]interface{}{}
|
m.mapActiveTimer =map[timer.ITimer]struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.dispatcher.TickerFunc(d,cb,m.OnCloseTimer,m.OnAddTimer)
|
return m.dispatcher.TickerFunc(d,nil,cb,m.OnCloseTimer,m.OnAddTimer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Module) cb(*timer.Timer){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Module) SafeAfterFunc(timerId *uint64,d time.Duration, AdditionData interface{},cb func(interface{})) {
|
||||||
|
if m.mapActiveIdTimer == nil {
|
||||||
|
m.mapActiveIdTimer = map[uint64]timer.ITimer{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if *timerId != 0 {
|
||||||
|
m.CancelTimerId(timerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
*timerId = m.GenTimerId()
|
||||||
|
t := m.dispatcher.AfterFunc(d,cb,nil,m.OnCloseTimer,m.OnAddTimer)
|
||||||
|
t.AdditionData = AdditionData
|
||||||
|
t.Id = *timerId
|
||||||
|
m.mapActiveIdTimer[*timerId] = t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Module) SafeCronFunc(cronId *uint64,cronExpr *timer.CronExpr, AdditionData interface{}, cb func(interface{})) {
|
||||||
|
if m.mapActiveIdTimer == nil {
|
||||||
|
m.mapActiveIdTimer = map[uint64]timer.ITimer{}
|
||||||
|
}
|
||||||
|
|
||||||
|
*cronId = m.GenTimerId()
|
||||||
|
c := m.dispatcher.CronFunc(cronExpr,cb,nil,m.OnCloseTimer,m.OnAddTimer)
|
||||||
|
c.AdditionData = AdditionData
|
||||||
|
c.Id = *cronId
|
||||||
|
m.mapActiveIdTimer[*cronId] = c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Module) SafeNewTicker(tickerId *uint64,d time.Duration, AdditionData interface{}, cb func(interface{})) {
|
||||||
|
if m.mapActiveIdTimer == nil {
|
||||||
|
m.mapActiveIdTimer = map[uint64]timer.ITimer{}
|
||||||
|
}
|
||||||
|
|
||||||
|
*tickerId = m.GenTimerId()
|
||||||
|
t := m.dispatcher.TickerFunc(d,cb,nil,m.OnCloseTimer,m.OnAddTimer)
|
||||||
|
t.AdditionData = AdditionData
|
||||||
|
t.Id = *tickerId
|
||||||
|
m.mapActiveIdTimer[*tickerId] = t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Module) CancelTimerId(timerId *uint64) bool{
|
||||||
|
if m.mapActiveIdTimer == nil {
|
||||||
|
log.SError("mapActiveIdTimer is nil")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
t,ok := m.mapActiveIdTimer[*timerId]
|
||||||
|
if ok == false {
|
||||||
|
log.SError("cannot find timer id ",timerId)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Cancel()
|
||||||
|
*timerId = 0
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (m *Module) OnRelease(){
|
func (m *Module) OnRelease(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ func (s *Service) Init(iService IService,getClientFun rpc.FuncRpcClient,getServe
|
|||||||
//初始化祖先
|
//初始化祖先
|
||||||
s.ancestor = iService.(IModule)
|
s.ancestor = iService.(IModule)
|
||||||
s.seedModuleId =InitModuleId
|
s.seedModuleId =InitModuleId
|
||||||
s.descendants = map[int64]IModule{}
|
s.descendants = map[uint32]IModule{}
|
||||||
s.serviceCfg = serviceCfg
|
s.serviceCfg = serviceCfg
|
||||||
s.goroutineNum = 1
|
s.goroutineNum = 1
|
||||||
s.eventProcessor = event.NewEventProcessor()
|
s.eventProcessor = event.NewEventProcessor()
|
||||||
|
|||||||
@@ -2,17 +2,16 @@ package timer
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"container/heap"
|
"container/heap"
|
||||||
"github.com/duanhf2012/origin/log"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetupTimer(timer *Timer) *Timer{
|
func SetupTimer(timer ITimer) ITimer{
|
||||||
if timer.rOpen == true {
|
if timer.IsOpen() == true {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.rOpen = true
|
timer.Open(true)
|
||||||
timerHeapLock.Lock() // 使用锁规避竞争条件
|
timerHeapLock.Lock() // 使用锁规避竞争条件
|
||||||
heap.Push(&timerHeap,timer)
|
heap.Push(&timerHeap,timer)
|
||||||
timerHeapLock.Unlock()
|
timerHeapLock.Unlock()
|
||||||
@@ -20,9 +19,10 @@ func SetupTimer(timer *Timer) *Timer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewTimer(d time.Duration) *Timer{
|
func NewTimer(d time.Duration) *Timer{
|
||||||
c := make(chan *Timer,1)
|
c := make(chan ITimer,1)
|
||||||
timer := newTimer(d,c,nil,"",nil)
|
timer := newTimer(d,c,nil,"")
|
||||||
SetupTimer(timer)
|
SetupTimer(timer)
|
||||||
|
|
||||||
return timer
|
return timer
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ func ReleaseTimer(timer *Timer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type _TimerHeap struct {
|
type _TimerHeap struct {
|
||||||
timers []*Timer
|
timers []ITimer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *_TimerHeap) Len() int {
|
func (h *_TimerHeap) Len() int {
|
||||||
@@ -39,7 +39,7 @@ func (h *_TimerHeap) Len() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *_TimerHeap) Less(i, j int) bool {
|
func (h *_TimerHeap) Less(i, j int) bool {
|
||||||
return h.timers[i].fireTime.Before(h.timers[j].fireTime)
|
return h.timers[i].GetFireTime().Before(h.timers[j].GetFireTime())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *_TimerHeap) Swap(i, j int) {
|
func (h *_TimerHeap) Swap(i, j int) {
|
||||||
@@ -47,7 +47,7 @@ func (h *_TimerHeap) Swap(i, j int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *_TimerHeap) Push(x interface{}) {
|
func (h *_TimerHeap) Push(x interface{}) {
|
||||||
h.timers = append(h.timers, x.(*Timer))
|
h.timers = append(h.timers, x.(ITimer))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *_TimerHeap) Pop() (ret interface{}) {
|
func (h *_TimerHeap) Pop() (ret interface{}) {
|
||||||
@@ -63,7 +63,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func StartTimer(minTimerInterval time.Duration,maxTimerNum int){
|
func StartTimer(minTimerInterval time.Duration,maxTimerNum int){
|
||||||
timerHeap.timers = make([]*Timer,0,maxTimerNum)
|
timerHeap.timers = make([]ITimer,0,maxTimerNum)
|
||||||
heap.Init(&timerHeap) // 初始化定时器heap
|
heap.Init(&timerHeap) // 初始化定时器heap
|
||||||
|
|
||||||
go tickRoutine(minTimerInterval)
|
go tickRoutine(minTimerInterval)
|
||||||
@@ -86,21 +86,17 @@ func tick() bool{
|
|||||||
timerHeapLock.Unlock()
|
timerHeapLock.Unlock()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
nextFireTime := timerHeap.timers[0].fireTime
|
nextFireTime := timerHeap.timers[0].GetFireTime()
|
||||||
if nextFireTime.After(now) { // 没有到时间的定时器,返回
|
if nextFireTime.After(now) { // 没有到时间的定时器,返回
|
||||||
timerHeapLock.Unlock()
|
timerHeapLock.Unlock()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
t := heap.Pop(&timerHeap).(*Timer)
|
t := heap.Pop(&timerHeap).(ITimer)
|
||||||
timerHeapLock.Unlock()
|
timerHeapLock.Unlock()
|
||||||
if len(t.C)>= cap(t.C) {
|
t.Open(false)
|
||||||
log.SError("Timer channel full!")
|
t.AppendChannel(t)
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
t.rOpen = false
|
|
||||||
t.C <- t
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,14 +9,36 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ITimer
|
||||||
|
type ITimer interface {
|
||||||
|
GetId() uint64
|
||||||
|
Cancel()
|
||||||
|
GetName()string
|
||||||
|
IsActive() bool
|
||||||
|
IsOpen() bool
|
||||||
|
Open(bOpen bool)
|
||||||
|
AppendChannel(timer ITimer)
|
||||||
|
Do()
|
||||||
|
GetFireTime() time.Time
|
||||||
|
SetupTimer(now time.Time) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type OnCloseTimer func(timer ITimer)
|
||||||
|
type OnAddTimer func(timer ITimer)
|
||||||
|
|
||||||
// Timer
|
// Timer
|
||||||
type Timer struct {
|
type Timer struct {
|
||||||
name string
|
Id uint64
|
||||||
cancelled bool //是否关闭
|
cancelled bool //是否关闭
|
||||||
C chan *Timer //定时器管道
|
C chan ITimer //定时器管道
|
||||||
interval time.Duration // 时间间隔(用于循环定时器)
|
interval time.Duration // 时间间隔(用于循环定时器)
|
||||||
fireTime time.Time // 触发时间
|
fireTime time.Time // 触发时间
|
||||||
cb func()
|
cb func(interface{})
|
||||||
|
cbEx func(t *Timer)
|
||||||
|
cbCronEx func(t *Cron)
|
||||||
|
cbTickerEx func(t *Ticker)
|
||||||
|
cbOnCloseTimer OnCloseTimer
|
||||||
|
cronExpr *CronExpr
|
||||||
AdditionData interface{} //定时器附加数据
|
AdditionData interface{} //定时器附加数据
|
||||||
rOpen bool //是否重新打开
|
rOpen bool //是否重新打开
|
||||||
|
|
||||||
@@ -45,17 +67,12 @@ var tickerPool =sync.NewPoolEx(make(chan sync.IPoolData,1000),func() sync.IPoolD
|
|||||||
return &Ticker{}
|
return &Ticker{}
|
||||||
})
|
})
|
||||||
|
|
||||||
func newTimer(d time.Duration,c chan *Timer,cb func(),name string,additionData interface{}) *Timer{
|
func newTimer(d time.Duration,c chan ITimer,cb func(interface{}),additionData interface{}) *Timer{
|
||||||
if c == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
timer := timerPool.Get().(*Timer)
|
timer := timerPool.Get().(*Timer)
|
||||||
timer.AdditionData = additionData
|
timer.AdditionData = additionData
|
||||||
timer.C = c
|
timer.C = c
|
||||||
timer.fireTime = Now().Add(d)
|
timer.fireTime = Now().Add(d)
|
||||||
timer.cb = cb
|
timer.cb = cb
|
||||||
timer.name = name
|
|
||||||
timer.interval = d
|
timer.interval = d
|
||||||
timer.rOpen = false
|
timer.rOpen = false
|
||||||
return timer
|
return timer
|
||||||
@@ -85,20 +102,59 @@ func releaseCron(cron *Cron) {
|
|||||||
|
|
||||||
// one dispatcher per goroutine (goroutine not safe)
|
// one dispatcher per goroutine (goroutine not safe)
|
||||||
type Dispatcher struct {
|
type Dispatcher struct {
|
||||||
ChanTimer chan *Timer
|
ChanTimer chan ITimer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Timer) GetId() uint64{
|
||||||
|
return t.Id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Timer) GetFireTime() time.Time{
|
||||||
|
return t.fireTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Timer) Open(bOpen bool){
|
||||||
|
t.rOpen = bOpen
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Timer) AppendChannel(timer ITimer){
|
||||||
|
t.C <- timer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Timer) IsOpen() bool{
|
||||||
|
return t.rOpen
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Timer) Do(){
|
func (t *Timer) Do(){
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
l := runtime.Stack(buf, false)
|
||||||
|
errString := fmt.Sprint(r)
|
||||||
|
log.SError("core dump info[",errString,"]\n",string(buf[:l]))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if t.IsActive() == false {
|
||||||
|
if t.cbOnCloseTimer!=nil {
|
||||||
|
t.cbOnCloseTimer(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
releaseTimer(t)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if t.cb != nil {
|
if t.cb != nil {
|
||||||
defer func() {
|
t.cb(t.AdditionData)
|
||||||
if r := recover(); r != nil {
|
}else if t.cbEx != nil {
|
||||||
buf := make([]byte, 4096)
|
t.cbEx(t)
|
||||||
l := runtime.Stack(buf, false)
|
}
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
log.SError("core dump info[",errString,"]\n",string(buf[:l]))
|
if t.rOpen ==false {
|
||||||
}
|
if t.cbOnCloseTimer!=nil {
|
||||||
}()
|
t.cbOnCloseTimer(t)
|
||||||
t.cb()
|
}
|
||||||
|
releaseTimer(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,17 +180,18 @@ func (t *Timer) IsActive() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Timer) GetName() string{
|
func (t *Timer) GetName() string{
|
||||||
return t.name
|
if t.cb!=nil {
|
||||||
|
return runtime.FuncForPC(reflect.ValueOf(t.cb).Pointer()).Name()
|
||||||
|
}else if t.cbEx!=nil {
|
||||||
|
return runtime.FuncForPC(reflect.ValueOf(t.cbEx).Pointer()).Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var emptyTimer Timer
|
||||||
func (t *Timer) Reset(){
|
func (t *Timer) Reset(){
|
||||||
t.name = ""
|
*t = emptyTimer
|
||||||
t.cancelled = false
|
|
||||||
t.C = nil
|
|
||||||
t.interval = 0
|
|
||||||
t.cb = nil
|
|
||||||
t.AdditionData = nil
|
|
||||||
t.rOpen = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Timer) IsRef()bool{
|
func (t *Timer) IsRef()bool{
|
||||||
@@ -153,6 +210,50 @@ func (c *Cron) Reset(){
|
|||||||
c.Timer.Reset()
|
c.Timer.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cron) Do() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
l := runtime.Stack(buf, false)
|
||||||
|
errString := fmt.Sprint(r)
|
||||||
|
log.SError("core dump info[",errString,"]\n",string(buf[:l]))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if c.IsActive() == false{
|
||||||
|
if c.cbOnCloseTimer != nil {
|
||||||
|
c.cbOnCloseTimer(c)
|
||||||
|
}
|
||||||
|
releaseCron(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
now := Now()
|
||||||
|
nextTime := c.cronExpr.Next(now)
|
||||||
|
if nextTime.IsZero() {
|
||||||
|
c.cbCronEx(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.cb!=nil {
|
||||||
|
c.cb(c.AdditionData)
|
||||||
|
}else if c.cbEx !=nil {
|
||||||
|
c.cbCronEx(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.IsActive() == true{
|
||||||
|
c.interval = nextTime.Sub(now)
|
||||||
|
c.fireTime = now.Add(c.interval)
|
||||||
|
SetupTimer(c)
|
||||||
|
}else{
|
||||||
|
if c.cbOnCloseTimer!=nil {
|
||||||
|
c.cbOnCloseTimer(c)
|
||||||
|
}
|
||||||
|
releaseCron(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Cron) IsRef()bool{
|
func (c *Cron) IsRef()bool{
|
||||||
return c.ref
|
return c.ref
|
||||||
}
|
}
|
||||||
@@ -165,6 +266,42 @@ func (c *Cron) UnRef(){
|
|||||||
c.ref = false
|
c.ref = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Ticker) Do() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
l := runtime.Stack(buf, false)
|
||||||
|
errString := fmt.Sprint(r)
|
||||||
|
log.SError("core dump info[", errString, "]\n", string(buf[:l]))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if c.IsActive() == false {
|
||||||
|
if c.cbOnCloseTimer!=nil {
|
||||||
|
c.cbOnCloseTimer(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
releaseTicker(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.cb!=nil{
|
||||||
|
c.cb(c.AdditionData)
|
||||||
|
} else if c.cbTickerEx != nil{
|
||||||
|
c.cbTickerEx(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.IsActive() == true{
|
||||||
|
c.fireTime = Now().Add(c.interval)
|
||||||
|
SetupTimer(c)
|
||||||
|
}else{
|
||||||
|
if c.cbOnCloseTimer!=nil {
|
||||||
|
c.cbOnCloseTimer(c)
|
||||||
|
}
|
||||||
|
releaseTicker(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Ticker) Reset(){
|
func (c *Ticker) Reset(){
|
||||||
c.Timer.Reset()
|
c.Timer.Reset()
|
||||||
}
|
}
|
||||||
@@ -183,99 +320,55 @@ func (c *Ticker) UnRef(){
|
|||||||
|
|
||||||
func NewDispatcher(l int) *Dispatcher {
|
func NewDispatcher(l int) *Dispatcher {
|
||||||
dispatcher := new(Dispatcher)
|
dispatcher := new(Dispatcher)
|
||||||
dispatcher.ChanTimer = make(chan *Timer, l)
|
dispatcher.ChanTimer = make(chan ITimer, l)
|
||||||
return dispatcher
|
return dispatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
type OnTimerClose func(timer *Timer)
|
func (dispatcher *Dispatcher) AfterFunc(d time.Duration, cb func(data interface{}),cbEx func(*Timer),onTimerClose OnCloseTimer,onAddTimer OnAddTimer) *Timer {
|
||||||
func (dispatcher *Dispatcher) AfterFunc(d time.Duration, cb func(*Timer),onTimerClose OnTimerClose,onAddTimer func(timer *Timer)) *Timer {
|
timer := newTimer(d,dispatcher.ChanTimer,nil,nil)
|
||||||
funName := runtime.FuncForPC(reflect.ValueOf(cb).Pointer()).Name()
|
timer.cb = cb
|
||||||
timer := newTimer(d,dispatcher.ChanTimer,nil,funName,nil)
|
timer.cbEx = cbEx
|
||||||
cbFunc := func() {
|
timer.cbOnCloseTimer = onTimerClose
|
||||||
if timer.IsActive() == false {
|
|
||||||
onTimerClose(timer)
|
|
||||||
releaseTimer(timer)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cb(timer)
|
t := SetupTimer(timer)
|
||||||
|
if onAddTimer!= nil && t!=nil {
|
||||||
if timer.rOpen ==false {
|
onAddTimer(t)
|
||||||
onTimerClose(timer)
|
|
||||||
releaseTimer(timer)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.cb = cbFunc
|
return timer
|
||||||
t := SetupTimer(timer)
|
|
||||||
onAddTimer(t)
|
|
||||||
|
|
||||||
return t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dispatcher *Dispatcher) CronFunc(cronExpr *CronExpr, cb func(*Cron),onTimerClose OnTimerClose,onAddTimer func(timer *Timer)) *Cron {
|
func (dispatcher *Dispatcher) CronFunc(cronExpr *CronExpr,cb func(data interface{}), cbEx func(*Cron),onTimerClose OnCloseTimer,onAddTimer OnAddTimer) *Cron {
|
||||||
now := Now()
|
now := Now()
|
||||||
nextTime := cronExpr.Next(now)
|
nextTime := cronExpr.Next(now)
|
||||||
if nextTime.IsZero() {
|
if nextTime.IsZero() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
funcName := runtime.FuncForPC(reflect.ValueOf(cb).Pointer()).Name()
|
|
||||||
cron := newCron()
|
cron := newCron()
|
||||||
// callback
|
cron.cb = cb
|
||||||
var cbFunc func()
|
cron.cbCronEx = cbEx
|
||||||
cbFunc = func() {
|
cron.cbOnCloseTimer = onTimerClose
|
||||||
if cron.IsActive() == false{
|
cron.cronExpr = cronExpr
|
||||||
onTimerClose(&cron.Timer)
|
|
||||||
releaseCron(cron)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
now := Now()
|
|
||||||
nextTime := cronExpr.Next(now)
|
|
||||||
if nextTime.IsZero() {
|
|
||||||
cb(cron)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cron.interval = nextTime.Sub(now)
|
|
||||||
cron.fireTime = now.Add(cron.interval)
|
|
||||||
SetupTimer(&cron.Timer)
|
|
||||||
cb(cron)
|
|
||||||
}
|
|
||||||
cron.C = dispatcher.ChanTimer
|
cron.C = dispatcher.ChanTimer
|
||||||
cron.cb = cbFunc
|
|
||||||
cron.name = funcName
|
|
||||||
cron.interval = nextTime.Sub(now)
|
cron.interval = nextTime.Sub(now)
|
||||||
cron.fireTime = Now().Add(cron.interval)
|
cron.fireTime = Now().Add(cron.interval)
|
||||||
SetupTimer(&cron.Timer)
|
SetupTimer(cron)
|
||||||
onAddTimer(&cron.Timer)
|
onAddTimer(cron)
|
||||||
return cron
|
return cron
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dispatcher *Dispatcher) TickerFunc(d time.Duration, cb func(*Ticker),onTimerClose OnTimerClose,onAddTimer func(timer *Timer)) *Ticker {
|
func (dispatcher *Dispatcher) TickerFunc(d time.Duration,cb func(data interface{}), cbEx func(*Ticker),onTimerClose OnCloseTimer,onAddTimer OnAddTimer) *Ticker {
|
||||||
funcName := runtime.FuncForPC(reflect.ValueOf(cb).Pointer()).Name()
|
|
||||||
ticker := newTicker()
|
ticker := newTicker()
|
||||||
cbFunc := func() {
|
|
||||||
cb(ticker)
|
|
||||||
if ticker.Timer.IsActive() == true{
|
|
||||||
ticker.fireTime = Now().Add(d)
|
|
||||||
SetupTimer(&ticker.Timer)
|
|
||||||
}else{
|
|
||||||
onTimerClose(&ticker.Timer)
|
|
||||||
releaseTicker(ticker)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ticker.C = dispatcher.ChanTimer
|
ticker.C = dispatcher.ChanTimer
|
||||||
ticker.fireTime = Now().Add(d)
|
ticker.fireTime = Now().Add(d)
|
||||||
ticker.cb = cbFunc
|
ticker.cb = cb
|
||||||
ticker.name = funcName
|
ticker.cbTickerEx = cbEx
|
||||||
ticker.interval = d
|
ticker.interval = d
|
||||||
|
|
||||||
// callback
|
// callback
|
||||||
SetupTimer(&ticker.Timer)
|
SetupTimer(ticker)
|
||||||
onAddTimer(&ticker.Timer)
|
onAddTimer(ticker)
|
||||||
|
|
||||||
return ticker
|
return ticker
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user