源码实在是简单,在这就简单描述2个过程
一:事件监听
当需要监听事件时,调用NoticeCenter的addListener函数,调用者将事件类型(event),标识(tag),处理函数(func),addListener函数根据事件类型先找到事件派发器(没有则会创建),然后调用其addListener函数
template<typename FUNC>
void addListener(void *tag, const string &event, FUNC &&func) {
getDispatcher(event, true)->addListener(tag, std::forward<FUNC>(func));
}
EventDispatcher的addListener函数如下,该函数将标识(tag),处理函数(func)插入自身的成员变量_mapListener,这是一个键值对。存储了多个执行函数
template<typename FUNC>
void addListener(void *tag, FUNC &&func) {
typedef typename function_traits<typename std::remove_reference<FUNC>::type>::stl_function_type funType;
std::shared_ptr<void> pListener(new funType(std::forward<FUNC>(func)), [](void *ptr) {
funType *obj = (funType *) ptr;
delete obj;
});
lock_guard<recursive_mutex> lck(_mtxListener);
_mapListener.emplace(tag, pListener);
}
所以当添加事件监听时,就会将需要监听的事件与该事件的处理函数全部保存
二:事件触发
调用函数如下,也是先找到事件派发器,然后执行他emitEvent函数
template<typename ...ArgsType>
int emitEvent(const string &strEvent, ArgsType &&...args) {
auto dispatcher = getDispatcher(strEvent);
if (!dispatcher) {
//该事件无人监听
return 0;
}
return dispatcher->emitEvent(std::forward<ArgsType>(args)...);
}
EventDispatcher的emitEvent函数如下,很容易理解,就是遍历_mapListener,然后执行里面保存的处理函数,也就是添加事件监听时传递进来的处理函数,
template<typename ...ArgsType>
int emitEvent(ArgsType &&...args) {
typedef function<void(decltype(std::forward<ArgsType>(args))...)> funType;
decltype(_mapListener) copy;
{
//先拷贝(开销比较小),目的是防止在触发回调时还是上锁状态从而导致交叉互锁
lock_guard<recursive_mutex> lck(_mtxListener);
copy = _mapListener;
}
int ret = 0;
for (auto &pr : copy) {
funType *obj = (funType *) (pr.second.get());
try {
(*obj)(std::forward<ArgsType>(args)...);
++ret;
} catch (InterruptException &) {
++ret;
break;
}
}
return ret;
}
三:总结
逻辑就很简单,
1、调用者需要监听某一个事件时,由通知中心(NoticeCenter)找到事件派发器(EventDispatcher),同时将事件类型和事件处理函数传递进去,然后由事件派发器(EventDispatcher)保存所有处理函数
2、当某处触发事件时(开启通知),由通知中心(NoticeCenter)找到事件派发器(EventDispatcher),然后由事件派发器(EventDispatcher)轮巡执行所有保存的处理函数,这样所有加入监听的都能执行他们想要执行的任务。
3、注意:如果处理函数没有做异步处理,那么他归属的线程在触发事件里,就是在emitEvent时的线程,而不是在调用者所在的线程,