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{} } }