package f5 import ( "flag" "sync" "sync/atomic" "time" "os" "q5" ) type App_ struct { nodeId int instanceId int terminated bool pkgName string flags map[int32]int32 servicing bool contextHash map[int32]q5.Args loopCond *sync.Cond imTopNode *IMMsgNode imBotNode *IMMsgNode imWorkNode *IMMsgNode imMsgMutex sync.RWMutex chGoLoopTimerExit chan int chGoLoopWait chan int64 nowTime time.Time nowUnixNano int64 imMsgHandlers [1024]func(int16, q5.Args) maxRunDelay int64 maxScheduleTime int64 updateFunc func () } func (this *App_) Init(updateFunc func ()) { this.updateFunc = updateFunc this.nowTime = time.Now() atomic.StoreInt64(&this.nowUnixNano, this.nowTime.UnixNano()) _Timer = &q5.XTimer{} _Timer.Init( func (context interface{}) int64 { return q5.GetTickCount() }, nil, 1000 * 60, 5000) _SysLog = new(SysLog_) _SysLog.Init() _TgLog = new(TGLog_) _TgLog.Init() flag.IntVar(&this.nodeId, "n", 0, "node id") flag.IntVar(&this.instanceId, "i", 0, "instance id") flag.Parse() this.loopCond = sync.NewCond(new(sync.Mutex)) this.chGoLoopTimerExit = make(chan int) this.chGoLoopWait = make(chan int64) this.outputRuningLog() SysLog().Info("node_id:%d instance_id:%d pid:%d", this.nodeId, this.instanceId, os.Getpid()) this.installTimer() go this.goLoopTimer() } func (this *App_) UnInit() { this.chGoLoopTimerExit <- 1 _Timer.UnInit() _Timer = nil } func (this *App_) Run() { for !this.terminated { this.nowTime = time.Now() atomic.StoreInt64(&this.nowUnixNano, this.nowTime.UnixNano()) beginTick := q5.GetTickCount() _Timer.Update() this.dispatchIMMsg() this.updateFunc() this.schedule() endTick := q5.GetTickCount() if this.maxRunDelay < endTick - beginTick { this.maxRunDelay = endTick - beginTick } } } func (this *App_) NewUuid() int64 { return 0 } func (this *App_) GetInstanceId() uint32 { return uint32(this.instanceId) } func (this *App_) GetNodeId() uint32 { return uint32(this.nodeId) } func (this *App_) GetPkgName() string { return this.pkgName } func (this *App_) SetPkgName(pkgName string) { this.pkgName = pkgName } func (this *App_) HasFlag(flag int32) bool { _, ok := this.flags[flag] return ok } func (this *App_) AddIMMsg(msgId int16, params q5.Args) { p := new(IMMsgNode) p.msgId = msgId p.params = params this.imMsgMutex.Lock() if this.imBotNode != nil { this.imBotNode.next = p this.imBotNode = p } else { this.imTopNode = p this.imBotNode = p } this.imMsgMutex.Unlock() this.loopCond.Broadcast() } func (this *App_) RegisterIMMsgHandle(msgId int16, handle func(int16,q5.Args)) { this.imMsgHandlers[msgId] = handle } func (this *App_) goLoopTimer() { var waitMs int64 = 1000 * 10 for { select { case <-this.chGoLoopTimerExit: return case waitMs = <-this.chGoLoopWait: if waitMs < 1 { waitMs = 1 } case <-time.After(time.Millisecond * time.Duration(waitMs)): waitMs = 1000 * 10 this.loopCond.Broadcast() } } } func (this *App_) schedule() { this.chGoLoopWait <- Timer().GetIdleTime() this.loopCond.L.Lock() this.loopCond.Wait() this.loopCond.L.Unlock() } func (this *App_) NotifyLoopCond() { this.loopCond.Broadcast() } func (this *App_) NowUnix() int64 { return this.nowUnixNano / int64(time.Second) } func (this *App_) NowUnixMilli() int64 { return this.nowUnixNano / int64(time.Millisecond) } func (this *App_) NowUnixNano() int64 { return this.nowUnixNano } func (this *App_) outputRuningLog() { for _, val := range q5.GetInitLogs() { SysLog().Info("%s", val) } } func (this *App_) dispatchIMMsg() { this.imMsgMutex.Lock() this.imWorkNode = this.imTopNode this.imTopNode = nil this.imBotNode = nil this.imMsgMutex.Unlock() for this.imWorkNode != nil { currNode := this.imWorkNode this.imWorkNode = this.imWorkNode.next if this.imMsgHandlers[currNode.msgId] != nil { this.imMsgHandlers[currNode.msgId](currNode.msgId, currNode.params) } } } func (this *App_) installTimer() { Timer().SetInterval(1000 * 60, func (ev int32, params *q5.Args) { if ev == q5.TIMER_EXEC_EVENT { SysLog().Info("max_run_delay:%d max_schedule_time:%d", App.maxRunDelay, App.maxScheduleTime) App.maxRunDelay = 0 App.maxScheduleTime = 0 } }) }