1. 说明
<<transport_layer网络传输层模块源码实现二>>一文中分析了如何阅读百万级大工程源码、Asio网络库实现、线程模型、transport_layer套接字处理及传输层管理子模块、session会话子模块、Ticket数据收发子模块、service_entry_point服务入口点子模块。
本文将继续分析网络传输层模块中service_state_machine状态机调度子模块内核源码实现。
2. service_state_machine状态机调度子模块
service_state_machine状态机处理模块主要复杂一次完整请求的状态转换,确保请求可以按照指定的流程顺利进行,最终实现客户端的正常mongodb访问。该模块核心代码实现主要由以下三个源码文件实现(test为测试相关,可以忽略):
2.1 核心代码实现
在service_entry_point服务入口点子模块分析中,当接收到一个新的链接后,在ServiceEntryPointImpl::startSession(...)回调函数中会构造一个ServiceStateMachine ssm类,从而实现了新链接、session、ssm的一一映射关系。其中,ServiceStateMachine 类实现对ThreadGuard(线程守护)有较多的依赖,因此本文从这两个类核心代码实现来分析整个状态机调度模块的内部设计细节。
2.1.1 ThreadGuard线程守护类核心代码实现
ThreadGuard也就是”线程守护”类,该类主要用于工作线程名的管理维护、ssm归属管理、该ssm对应session链接的回收处理等。该类核心成员及接口实现如下:
1.class ServiceStateMachine::ThreadGuard {
2. ......
3.public:
4. // create a ThreadGuard which will take ownership of the SSM in this thread.
5. //ThreadGuard初始化,标记ssm所有权属于本线程
6. explicit ThreadGuard(ServiceStateMachine* ssm) : _ssm{ssm} {
7. //获取ssm状态机所有权
8. auto owned = _ssm->_owned.compareAndSwap(Ownership::kUnowned, Ownership::kOwned);
9. //如果是一个链接一个线程模型,则条件满足
10. if (owned == Ownership::kStatic) {
11. //一个链接一个线程模型,由于链接始终由同一个线程处理,因此该链接对应的ssm始终归属于同一个线程
12. dassert(haveClient());
13. dassert(Client::getCurrent() == _ssm->_dbClientPtr);
14. //标识归属权已确定
15. _haveTakenOwnership = true;
16. return;
17. }
18. ......
19. //adaptive 动态线程模式走下面的模式
20.
21. //把当前线程的线程名零时保存起来
22. auto oldThreadName = getThreadName();
23. //ssm保存的线程名和当前线程名不同
24. if (oldThreadName != _ssm->_threadName) {
25. //即将修改线程名了,把修改前的线程名保存到_oldThreadName
26. _ssm->_oldThreadName = getThreadName().toString();
27. //把运行本ssm状态机的线程名改为conn-x线程
28. setThreadName(_ssm->_threadName); //把当前线程改名为_threadName
29. }
30.
31. //设置本线程对应client信息,一个链接对应一个client,标识本client当前归属于本线程处理
32. Client::setCurrent(std::move(_ssm->_dbClient));
33. //本状态机ssm所有权有了,归属于运行本ssm的线程
34. _haveTakenOwnership = true;
35. }
36. ......
37. //重新赋值
38. ThreadGuard& operator=(ThreadGuard&& other) {
39. if (this != &other) {
40. _ssm = other._ssm;
41. _haveTakenOwnership = other._haveTakenOwnership;
42. //原来的other所有权失效
43. other._haveTakenOwnership = false;
44. }
45. //返回
46. return *this;
47. };
48.
49. //析构函数
50. ~ThreadGuard() {
51. //ssm所有权已确定,则析构的时候,调用release处理,恢复线程原有线程名
52. if (_haveTakenOwnership)
53. release();
54. }
55.
56. //一个链接一个线程模型,标记_owned为kStatic,也就是线程名永远不会改变
57. void markStaticOwnership() {
58. dassert(static_cast<bool>(*this));
59. _ssm->_owned.store(Ownership::kStatic);
60. }
61.
62. //恢复原有线程名,同时把client信息从调度线程归还给状态机
63. void release() {
64. auto owned = _ssm->_owned.load();
65. //adaptive异步线程池模式满足if条件,表示SSM固定归属于某个线程
66. if (owned != Ownership::kStatic) {
67. //本线程拥有currentClient信息,于是把它归还给SSM状态机
68. if (haveClient()) {
69. _ssm->_dbClient = Client::releaseCurrent();
70. }
71. //恢复到以前的线程名
72. if (!_ssm->_oldThreadName.empty()) {
73. //恢复到老线程名
74. setThreadName(_ssm->_oldThreadName);
75. }
76. }
77. //状态机状态进入end,则调用对应回收hook处理
78. if (_ssm->state() == State::Ended) {
79. //链接关闭的回收处理 ServiceStateMachine::setCleanupHook
80. auto cleanupHook = std::move(_ssm->_cleanupHook);
81. if (cleanupHook)
82. cleanupHook();
83. return;
84. }
85.
86. //归属权失效
87. _haveTakenOwnership = false;
88. //归属状态变为未知
89. if (owned == Ownership::kOwned) {
90. _ssm->_owned.store(Ownership::kUnowned);
91. }
92. }
93.
94.private:
95. //本线程守护当前对应的ssm
96. ServiceStateMachine* _ssm;
97. //默认false,标识该状态机ssm不归属于任何线程
98. bool _haveTakenOwnership = false;
99.}
从上面的代码分析可以看出线程守护类作用比较明确,就是守护当前线程的归属状态,并记录状态机ssm不同状态变化前后的线程名。此外,状态机ssm对应的session链接如果进入end状态,则该链接的资源回收释放也由该类完成。
————————————————
版权声明:本文为CSDN博主「tuoyi123」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tuoyi123/article/details/109164997
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69997197/viewspace-2764979/ ,如需转载,请注明出处,否则将追究法律责任。