| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- package event
- import (
- "context"
- "fmt"
- "runtime/debug"
- "sync"
- "time"
- "bet24.com/log"
- )
- type IEventChan interface {
- OnEvent()
- //Dispatch(ch chan<- interface{})
- }
- type EventChan_base struct {
- EventFunc func(arg string)
- Arg string
- obj chan interface{}
- }
- func (e *EventChan_base) OnEvent() {
- if e.EventFunc != nil {
- e.EventFunc(e.Arg)
- }
- }
- func (ei *EventChan_base) isSame(ei2 *EventChan_base) bool {
- if ei2 == nil {
- return false
- }
- if fmt.Sprintf("%p", ei.obj) != fmt.Sprintf("%p", ei2.obj) {
- return false
- }
- return fmt.Sprintf("%p", ei.EventFunc) == fmt.Sprintf("%p", ei2.EventFunc)
- }
- func (ei *EventChan_base) isSameObject(obj interface{}) bool {
- if obj == nil {
- return false
- }
- return fmt.Sprintf("%p", ei.obj) == fmt.Sprintf("%p", obj)
- }
- type event_chan struct {
- sync.RWMutex
- events map[string][]EventChan_base
- }
- var g = newEvent()
- func newEvent() *event_chan {
- return &event_chan{
- events: make(map[string][]EventChan_base),
- }
- }
- func hasFunc(name string, ei *EventChan_base) bool {
- evt, ok := g.events[name]
- if !ok {
- return false
- }
- for _, f := range evt {
- if f.isSame(ei) {
- return true
- }
- }
- return false
- }
- func AddEvent(name string, obj chan interface{}, fn func(arg string)) {
- g.Lock()
- defer g.Unlock()
- if obj == nil || fn == nil {
- log.Release("AddEvent no obj or f %v", name)
- return
- }
- ei := EventChan_base{obj: obj, EventFunc: fn}
- if hasFunc(name, &ei) {
- log.Release("AddEvent same event %v", name)
- return
- }
- g.events[name] = append(g.events[name], ei)
- }
- func RemoveEvent(name string, obj chan interface{}, fn func(arg string)) {
- g.Lock()
- defer g.Unlock()
- if obj == nil || fn == nil {
- log.Release("RemoveEvent no obj or fn %v", name)
- return
- }
- evt, ok := g.events[name]
- if !ok {
- log.Release("RemoveEvent event name not found: %s", name)
- return
- }
- ei := EventChan_base{obj: obj, EventFunc: fn}
- //for k, f := range evt {
- for i := 0; i < len(evt); {
- if evt[i].isSame(&ei) {
- log.Debug("Removing Event %v,%v", name, evt[i])
- evt = append(evt[:i], evt[i+1:]...)
- } else {
- i++
- }
- }
- g.events[name] = evt
- //}
- if len(g.events[name]) == 0 {
- log.Debug("Remove name: %s", name)
- delete(g.events, name)
- }
- }
- // 删除对象所有事件
- func RemoveAllEvent(obj interface{}) {
- if obj == nil {
- log.Release("RemoveAllEvent no obj")
- return
- }
- g.Lock()
- for name, evt := range g.events {
- for i := 0; i < len(evt); {
- if evt[i].isSameObject(obj) {
- evt = append(evt[:i], evt[i+1:]...)
- } else {
- i++
- }
- }
- if len(evt) > 0 {
- g.events[name] = evt
- } else {
- delete(g.events, name)
- }
- }
- g.Unlock()
- }
- func DispatchEvent(eventName, eventArg string) {
- go func(n, a string) {
- g.RLock()
- fns := g.events[n]
- g.RUnlock()
- if len(fns) == 0 {
- return
- }
- defer func() {
- if err := recover(); err != nil {
- log.Release("DispatchEvent recover err %v", err)
- log.Release("%s", debug.Stack())
- }
- }()
- for i := len(fns) - 1; i >= 0; i-- {
- obj := fns[i]
- obj.Arg = a
- //log.Debug("Dispatching event %v:%v", eventName, obj)
- ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*500)
- select {
- case <-ctx.Done():
- //log.Release("Dispatch event timeout %v:%v", eventName, obj)
- //RemoveEvent(n, fns[i].obj, fns[i].EventFunc)
- break
- case fns[i].obj <- &(obj):
- break
- }
- cancel()
- }
- }(eventName, eventArg)
- }
- func Dump() {
- go func() {
- g.RLock()
- defer g.RUnlock()
- for name, fns := range g.events {
- log.Release("event name[%v],count[%d]", name, len(fns))
- for _, v := range fns {
- log.Release("event func %v", v)
- }
- }
- }()
- }
|