f5/msgqueue.go
aozhiwei 37a99c4226 1
2024-11-06 15:22:32 +08:00

110 lines
2.2 KiB
Go

package f5
import (
"q5"
"sync"
)
type MsgHandler struct {
deleted bool
entry q5.ListHead
cb func(q5.Args)
}
type msgQueue struct {
msgHandlers [256] struct {
lock sync.Mutex
head q5.ListHead
delingLock sync.Mutex
delingHandlers []*MsgHandler
addingLock sync.Mutex
addingHead q5.ListHead
}
}
func (this *msgQueue) init() {
for i := 0; i < len(this.msgHandlers); i++ {
node := &this.msgHandlers[i]
node.lock.Lock()
node.head.Init(nil)
node.lock.Unlock()
node.addingLock.Lock()
node.addingHead.Init(nil)
node.addingLock.Unlock()
}
}
func (this *msgQueue) unInit() {
}
func (this *msgQueue) RegisterCb(msgId int, cb func(q5.Args)) *MsgHandler {
if msgId >= len(this.msgHandlers) {
panic("msgQueue.msgId error")
}
p := new(MsgHandler)
p.cb = cb
p.entry.Init(p)
node := &this.msgHandlers[msgId]
node.addingLock.Lock()
defer node.addingLock.Unlock()
node.addingHead.AddTail(&p.entry)
return p
}
func (this *msgQueue) UnRegisterCb(handler *MsgHandler) {
if handler != nil {
handler.deleted = true
}
}
func (this *msgQueue) FireEvent(msgId int, args q5.Args) {
if msgId < 0 || msgId >= len(this.msgHandlers) {
return
}
node := &this.msgHandlers[msgId]
node.lock.Lock()
defer node.lock.Unlock()
node.head.ForEach(
func (data interface{}) bool {
h := data.(*MsgHandler)
if !h.deleted {
h.cb(args)
} else {
node.delingLock.Lock()
q5.AppendSlice(&node.delingHandlers, h)
node.delingLock.Unlock()
}
return true
})
this.clearNode(&node.delingLock, &node.delingHandlers)
node.addingLock.Lock()
defer node.addingLock.Unlock()
if !node.addingHead.Empty() {
node.addingHead.ForEach(
func (data interface{}) bool {
h := data.(*MsgHandler)
h.entry.DelInit()
if !h.deleted {
node.head.AddTail(&h.entry)
h.cb(args)
} else {
node.delingLock.Lock()
q5.AppendSlice(&node.delingHandlers, h)
node.delingLock.Unlock()
}
return true
})
}
this.clearNode(&node.delingLock, &node.delingHandlers)
}
func (this *msgQueue) clearNode(delingLock *sync.Mutex, delingHandlers *[]*MsgHandler) {
delingLock.Lock()
defer delingLock.Unlock()
if len(*delingHandlers) > 0 {
*delingHandlers = []*MsgHandler{}
}
}