Ebus是O3DE引擎中的消息传递系统,更加详细的信息可以参考官方文档:EBus
这里详细研究它的实现机制。
EBus使用模板编程,主要用来分发事件或者接收请求。
EBus代码架构:
…
EBus中的一些概念
Interface:一个抽象类,其中定义了EBus需要分发或者接收的虚函数。
Traits:用来定义EBus的属性,一般来说如果Interface继承了EBusTraits,它就不用提供了。
Handler:连接到EBus的实例,EBus分发事件或接收请求时,会触发它们的函数。
Address:用来指定确定事件或请求需要分发到哪些Handle,如果使用的话,一般以ID来指定,默认不使用,也就是事件通知到所有Handler。
Internal
Internal中包含了EBus的底层基础组件。
StoragePolicies
此模块提供了Address和Handle的保存机制。
AddressStoragePolicy
用来决定如何保存Address(ID)和HandlerStorage的映射,假如此Ebus不使用AddressPolicy,那么这个类不会被使用。
默认的定义为:
它需要3个模板参数:
Traits:从EBus的Traits中得到,决定了id类型,内存分配器类型,是否排序,如果排序的话如何比较id。
HandlerStorage:保存的handler的数据类型。
EBusAddressPolicy:只有AddressPolicy的EBus才能实例化这个模板。
它是一个空的结构体,具体的功能由模板的特化来实现。
下面为两个模板特化:
其中的不需要排序的AddressStoragePolicy,第3个模板参数提供的是EBusAddressPolicy::ById
其中定义的StorageType为哈希表:
这个哈希表的key是Traits::BusIdType,value是HandlerStorage。
需要排序的AddressStoragePolicy,第三个模板参数提供的是EBusAddressPolicy::ByIdAndOrdered
其中定义的StorageType为红黑树:
同样key是Traits::BusIdType,value是HandlerStorage。比较函数的类型从Traits中获取。
HandlerStoragePolicy
用来决定如何保存handler列表,由于一个EBus可能只连接一个handler,也可能连接多个handler,当连接多个Handler时,要决定如何保存它们。假设EBus是使用AddressPolicy的,那么这个类会被提供为上面AddressStoragePolicy的第二个模板参数。
与上面的AddressStoragePolicy一样,它依靠模板的特化来实现具体的功能。
4个模板参数:
Interface,Traits:都是从EBus中获取,含义与EBus中的相同。
Handler:handler的数据类型。
EBusHandlerPolicy:只有EBu使用了HandlerPolicy::Multiplexxx(即允许多个Handler连接到EBus)才会使用这个类。
需要排序的HandlerStoragePolicy,第4个模板参数提供EBusHandlerPolicy::Multiple。
其中的StorageType是一个list。
需要排序的HandlerStoragePolicy,第4个模板参数提供EBusHandlerPolicy::Multiple。
EBusContainer
Handles
Handle在EBus中作为事件的监听者,它可以连接到EBus系统,当事件触发时Handle响应此事件,并且可以在不需要时断开与EBus的连接。
下面是几种不同类型得Handle。
NonIdHandler
这种Handle用于single address的Bus,也就是说它监听的事件不需要绑定id,所有Handle都可以监听到。