#Envoy 源码分析(三) --------event
Envoy的网络部分用的是libevent,所以其事件部分也是对libevent接口的封装。
####libevent
首先在libevent中对libevent的几个基础组件做了包装,封装为自动析构的智能指针类型
typedef CSmartPtr BasePtr;
typedef CSmartPtr BufferPtr;
typedef CSmartPtr BufferEventPtr;
typedef CSmartPtr ListenerPtr;
这里有个Global类,提供一个静态initialize方法,初始化libevent线程安全和屏蔽SIGPIPE信号。
####event_impl_base
所有事件类的基类
####timer_impl
对libevent定时器事件的封装,构造是需要传递一个
typedef std::function TimerCb;
函数对象,这里在初始化的时候传递了匿名函数给libevent的event,避免了TimerCb的参数传递过程。
构造函数中通过evtimer_assign宏给libevent赋值,在调用用enableTimer之后定时器启动。
####signal_impl
对libevent信号事件的封装,与timer_impl相同,但是没有成员函数,构造函数中将event注册到libevent中。
####file_event_impl
对io的事件封装,触发回调时区分触发事件参数传递给回调函数。
[](evutil_socket_t, short what, void* arg) -> void {
FileEventImpl* event = static_cast(arg);
uint32_t events = 0;
if (what & EV_READ) {
events |= FileReadyType::Read;
}
if (what & EV_WRITE) {
events |= FileReadyType::Write;
}
if (what & EV_CLOSED) {
events |= FileReadyType::Closed;
}
ASSERT(event);
event->cb_(events);
},
this);
####dispatcher_impl
事件调度循环,在其run方法中调用了libevent的 event_base_loop接口等待事件被触发。这是事件触发比较底层的一个类:
//调用run方法时的线程id
Thread::ThreadId run_tid_{};
//一个带有水位触发回调的buffer工厂
Buffer::WatermarkFactoryPtr buffer_factory_;
//libevent 的base
Libevent::BasePtr base_;
//延时删除定时器
TimerPtr deferred_delete_timer_;
//post 方法调用触发器
TimerPtr post_timer_;
//延时删除队列 插入删除时用current_to_delete_指向不同的to_delete*
std::vector to_delete_1_;
std::vector to_delete_2_;
std::vector* current_to_delete_;
//保护post_callbacks_ 的锁
Thread::MutexBasicLockable post_lock_;
//post 函数对象存储
std::list> post_callbacks_ GUARDED_BY(post_lock_);
//标示删除操作阶段
bool deferred_deleting_{};
这里有一点疑惑是两个定时器当插入操作发生时,有且仅有一个项时会设置0秒触发,好像没有找到其他地方的调用。
从成员变量即可简单的看到dispatcher_impl主要做的事情就是对libevent base的封装,此外还提供了一系列的创建函数:
Network::ConnectionPtr createServerConnection
Network::ClientConnectionPtr createClientConnection
Network::DnsResolverSharedPtr createDnsResolve
FileEventPtr createFileEvent
Filesystem::WatcherPtr createFilesystemWatcher
Network::ListenerPtr createListener
TimerPtr createTimer
这些对象在创建的过程中都会将自己的时间事件,信号事件,IO事件在构造函数中注册到dispatcher_impl的base_上,唯一不同的是createListener接口创建时调用的libevent接口不同,不过同样会将对应的回调接口注册到base上。
####dispatched_thread