一、前言
hhvm源码中充满了很多C++11的新特性,并且使用了各种设计模式如工厂,模板方法等,利用智能指针包裹指针,让delete没有肆意的出现
模板,继承,explicit,纯虚函数的出现令代码中充满了惊喜
例如下面这段代码:run_函数是pthread_create执行的函数
hhvm/main.cpp
75行:调用execute_program函数进行具体的逻辑
runtime/base/program-functions.cpp
885行:调用execute_program_impl进行具体的逻辑
runtime/base/program-functions.cpp
1260: 从配置文件中加载配置项
1475:函数负责启动线程与接收处理请求
总体流程图如下:
RuntimeOption::Load函数负责加载配置文件中的配置项
start_server函数负责启动线程与接收处理请求
以如下配置项的解析为例
Server{ Type= FastCGIServer ThreadCount=20 ###...... }
runtime/base/runtime-option.cpp
782-801行 解析配置文件中Server块中的内容
787行 将配置文件中的type值FastCGIServer赋值给ServerType
800行 将配置文件中的ThreadCount赋值给ServerThreadCount
所以ServerType的值为FastCGIServer
ServerThreadCount的值为20
runtime/base/program-functions.cpp
799行 初始化HttpServer对象
837行 启动server,接受处理请求
httpserver对象的初始化函数
runtime/server/http-server.cpp
88行 KNumProcessors为系统内核的个数,通过62行的 const int kNumProcessors = sysconf(_SC_NPROCESSORS_ONLN);获得
84-90行:如果配置的thread大于系统的内核的个数,则在启动时只启动与系统内核个数相同的thread数,将其余的个数赋值给additionalThreads
92行:调用工厂函数,针对ServerType:FastCGIServerc生成一个工厂对象
96-101行:将配置文件中的信息赋值给options对象,注意这里的startingThreadCount最大为系统内核的个数
102行:根据options配置信息生成一个Server
runtime/server/fastcgi/fastcgi-server-factory.cpp
听过FastCGIServerFactory工厂生成一个FastCGIServer对象
FastCGIServer的构造函数
runtime/server/fastcgi/fastcgi-server.cpp
这里的worker就是启动的线程数目
这里关注一下m_dispatcher的初始化
runtime/server/fastcgi/fastcgi-server.h
JobQueueDispatcher<FastCGIWorker> m_dispatcher;
m_dispatcher的类型为JobQueueDispatcher
FastCGIWorker的定义如下:
typedef ServerWorker<std::shared_ptr<FastCGIJob>,FastCGITransportTraits> FastCGIWorker;
struct ServerWorker : JobQueueWorker<JobPtr,Server*,true,false,JobQueueDropVMStack>{}//传入的第三个参数为true
template<typename TJob, typename TContext = void*, bool countActive = false, bool waitable = false, class Policy = detail::NoDropCachePolicy> class JobQueueWorker {}
ServerWorker的继承关系如下
所以这里的countActive为true
467-473行:由于CountActivewe== true所以不会进入下方的逻辑中
util/job-queue.h
656-658行 同样由于CountActive== true 因此不会走入656-658行里面
runtime/server/http-server.cpp
262-268行 由于没有配置 ThreadDocuments,ThreadLoopDocuments所以size()大小为0 不会走入
269行 ServerPort的初始化值为80,只要配置文件中的Port值不为0(即使配置文件中没有Server.Port值,也会初始化为80) 就会走入
runtime/base/runtime-option.cpp
121 int RuntimeOption::ServerPort = 80;
相比之下
AdminServer.Port的值初始化为0
runtime/base/runtime-option.cpp
266 int RuntimeOption::AdminServerPort = 0;
因此只有配置了才会启动AdminServer
runtime/server/http-server.cpp
非AdminServer的时候 传入的pageServer==true因为走入579行
这里的m_pageServer为fastcgi-server对象
runtime/server/fastcgi/fastcgi-server.cpp
263行 m_worker.start()通过C++11的thread启动一个线程负责网络IO
264行 m_dispatcher.start() 通过pthread_create启动若干线程负责CPU部分
下面看一看m_dispatcher.start的详细逻辑
util/job-queue.h
513-516行 如果配置的threadCount过小的话 这里会进行增加
517-520行 通过start()函数创建线程
util/job-queue.h
util/async-func.h
AsyncFunc继承自AsyncFuncImpl
AsnycFuncImpl实现了start()函数
util/async-func.cpp
至此线程启动完毕,线程运行的函数为ThreadFunc
ThreadFunc是从那里来的呢?
util/async-func.cpp
这里使用了模板方法设计模式
util/async-func.h
一段神奇的代码.....
util/job-queue.h
最终执行的方法如下