github.com/eframework-cn/EP.GO.UTIL@v1.0.0/xevt/xevt.go (about)

     1  //-----------------------------------------------------------------------//
     2  //                     GNU GENERAL PUBLIC LICENSE                        //
     3  //                        Version 2, June 1991                           //
     4  //                                                                       //
     5  // Copyright (C) EFramework, https://eframework.cn, All rights reserved. //
     6  // Everyone is permitted to copy and distribute verbatim copies          //
     7  // of this license document, but changing it is not allowed.             //
     8  //                   SEE LICENSE.md FOR MORE DETAILS.                    //
     9  //-----------------------------------------------------------------------//
    10  
    11  // 提供事件的注册、注销、通知等功能.
    12  package xevt
    13  
    14  import (
    15  	"github.com/eframework-cn/EP.GO.UTIL/xcollect"
    16  	"github.com/eframework-cn/EP.GO.UTIL/xlog"
    17  	"github.com/eframework-cn/EP.GO.UTIL/xrun"
    18  )
    19  
    20  // 消息句柄
    21  type IHandler interface {
    22  	Handle(reply *EvtReply, receiver interface{}, param interface{})
    23  }
    24  
    25  // 消息中心
    26  type EvtMgr struct {
    27  	HID   int                // 自增ID
    28  	Mutil bool               // 是否支持多个收听者
    29  	Evts  map[int]*EvtEntity // 事件映射
    30  }
    31  
    32  // 消息实体
    33  type EvtEntity struct {
    34  	ID   int          // 事件ID
    35  	Hnds []*HndEntity // 句柄列表
    36  }
    37  
    38  // 句柄实体
    39  type HndEntity struct {
    40  	ID   int      // 句柄ID
    41  	Func IHandler // 句柄函数
    42  }
    43  
    44  // 消息响应
    45  type EvtReply struct {
    46  	Result interface{} // 透传参数
    47  	Pend   chan int    // 阻塞标识
    48  }
    49  
    50  // 新建消息响应
    51  //	pend: 阻塞标识
    52  func NewEvtReply(pend ...chan int) *EvtReply {
    53  	this := new(EvtReply)
    54  	if len(pend) == 1 {
    55  		this.Pend = pend[0]
    56  	}
    57  	return this
    58  }
    59  
    60  // 完成消息响应
    61  //	result: 透传参数
    62  func (this *EvtReply) Done(result ...interface{}) {
    63  	if len(result) == 1 {
    64  		this.Result = result[0]
    65  	}
    66  	if this.Pend != nil {
    67  		close(this.Pend)
    68  	}
    69  }
    70  
    71  // 新建消息中心
    72  //	multi: 是否支持多个收听者
    73  func NewEvtMgr(mutli bool) *EvtMgr {
    74  	return &EvtMgr{0, mutli, make(map[int]*EvtEntity)}
    75  }
    76  
    77  // 清除消息注册
    78  func (this *EvtMgr) Clear() {
    79  	this.Evts = make(map[int]*EvtEntity)
    80  }
    81  
    82  // 获取消息实体
    83  //	id: 消息ID
    84  func (this *EvtMgr) Get(id int) *EvtEntity {
    85  	return this.Evts[id]
    86  }
    87  
    88  // 注册消息
    89  //	id: 消息ID
    90  //	handler: 回调函数
    91  func (this *EvtMgr) Reg(id int, handler IHandler) int {
    92  	if nil == handler {
    93  		xlog.Error("EvtMgr.Reg: nil handler, id=%v", id)
    94  		return -1
    95  	}
    96  	entity := this.Evts[id]
    97  	if entity == nil {
    98  		entity = new(EvtEntity)
    99  		entity.ID = id
   100  		entity.Hnds = make([]*HndEntity, 0)
   101  		this.Evts[id] = entity
   102  	}
   103  	if this.Mutil == false && len(entity.Hnds) > 1 {
   104  		xlog.Error("EvtMgr.Reg: not support multi-register, id=%v", id)
   105  		return -1
   106  	}
   107  	this.HID++
   108  	hnd := new(HndEntity)
   109  	hnd.ID = this.HID
   110  	hnd.Func = handler
   111  	entity.Hnds = append(entity.Hnds, hnd)
   112  	return hnd.ID
   113  }
   114  
   115  // 注销消息
   116  //	id: 消息ID
   117  //	hid: 句柄ID
   118  func (this *EvtMgr) Unreg(id int, hid int) bool {
   119  	entity := this.Evts[id]
   120  	if entity == nil {
   121  		return false
   122  	} else {
   123  		return xcollect.Remove(&entity.Hnds, func(ele interface{}) bool { return ele.(*HndEntity).ID == hid })
   124  	}
   125  }
   126  
   127  // 通知消息
   128  //	id: 消息ID
   129  //	reply: 响应对象
   130  //	param1: 参数1
   131  //	param2: 参数2
   132  func (this *EvtMgr) Notify(id int, reply *EvtReply, param1 interface{}, param2 interface{}) bool {
   133  	defer xrun.Caught(false)
   134  	entity := this.Get(id)
   135  	if entity == nil {
   136  		if id < 0 {
   137  			// reserve msg id
   138  		} else {
   139  			xlog.Warn("xevt.Notify: no handler of msgid=%v found.", id)
   140  		}
   141  		return false
   142  	}
   143  	for _, h := range entity.Hnds {
   144  		if h != nil && h.Func != nil {
   145  			h.Func.Handle(reply, param1, param2)
   146  		}
   147  	}
   148  	return true
   149  }