Google C++ 开源项目的格式
潘忠显 / 2020-06-29
从三个项目看Google C++的文件组织形式
一个功能涉及的文件
简单来说,一个功能涉及到的文件可能包括以下几种
- 声明的头文件 local_span_store.h
- 声明的源文件 local_span_store.cc
- 实现的头文件 local_span_store_impl.h
- 实现的源文件 local_span_store_impl.cc
- 测试文件 local_span_store_test.cc
- 压测文件 local_span_store_benchmark.cc
- Fuzzing文件 local_span_store_fuzzer.cc
Envoy
Timer相关
source/common/http/http1/conn_pool.h中有用到定时器。
#include "envoy/event/timer.h"
struct ActiveClient : ...{
...
Event::TimerPtr connect_timer_;
...
ActiveClient::ActiveClient(ConnPoolImpl& parent)
: parent_(parent),
connect_timer_(parent_.dispatcher_.createTimer([this]() -> void { onConnectTimeout(); })),...{
...
}
}
在ActiveClient构造的时候,创建定时器并存使用unique_ptr的指针管理。
Timer
的声明
Timer是个抽象的定时器事件类(abstract timer event),定义了几个接口:
- disableTimer()
- enableTimer(const std::chrono::milliseconds& d)
- enabled()
自己实现的定时器类继承自Timer
即可,比如timer_impl.h
中的TimerUtils
类。
Utils可以看做是`Utility helper functions的缩写,这种类我们大多称为“实用工具类”。
TimerUtils 实现了Timer
的所有虚函数。对应两个文件
source/common/event/timer_impl.h
source/common/event/timer_impl.cc
Q: 为什么timer_impl.h是放在source目录下而不是include目录下?
A: 是为了内部使用,而不是作为提供给外边库使用的。
parent_.dispatcher_.createTimer
如何创建定时器
跟Timer类似,Envoy::Event::Dispatcher
也是一个抽象类,这里调用的是Envoy::Http:Http1::ConnPoolImpl
的成员变量dispatcher_
的成员变量,而这个成员是在构造ConnPoolmpl的时候复制构造的。
ConnPoolImpl::ConnPoolImpl(Event::Dispatcher& dispatcher, Upstream::HostConstSharedPtr host,
Upstream::ResourcePriority priority,
const Network::ConnectionSocket::OptionsSharedPtr& options)
: ConnPoolImplBase(std::move(host), std::move(priority)), dispatcher_(dispatcher),
socket_options_(options),
upstream_ready_timer_(dispatcher_.createTimer([this]() { onUpstreamReady(); })) {}
还有生产环境的实现:
/**
* Production implementation of the ConnPoolImpl.
*/
class ProdConnPoolImpl : public ConnPoolImpl {
...
我们的主要目的是为了找个创建定时器的实现,追复杂调用关系就偏离主题了。可以直接看看dispatcher_impl.h
中的DispatcherImpl
中的createTimer
即可。
TimerPtr DispatcherImpl::createTimer(TimerCb cb) { return createTimerInternal(cb); }
TimerPtr DispatcherImpl::createTimerInternal(TimerCb cb) {
ASSERT(isThreadSafe());
return scheduler_->createTimer(cb);
}
实际是使用LibeventScheduler
创建的TimerImpl
的对象,构造接受两个参数Libevent::BasePtr
和TimerCb cb
用到了libevent库。
#include "event2/event.h"
evtimer_assign(
&raw_event_, libevent.get(),
[](evutil_socket_t, short, void* arg) -> void { static_cast<TimerImpl*>(arg)->cb_(); }, this);
libevent库
http://www.wangafu.net/~nickm/libevent-book/
internal 与 implementation
为什么会有Impl的存在?
https://en.cppreference.com/w/cpp/language/pimpl
createTimer
与createTimerInternal
C++ Core Guidelines https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md
Anything not specifically forbidden is allowed.
C++中的虚函数是如何工作的
https://www.geeksforgeeks.org/virtual-function-cpp/
override 描述符的作用
编译时错误
三种方式的比较
头文件: envoy/event/timer.h
Envoy::Event::Timer