Muduo学习笔记(一) 什么都不做的EventLoop
Muduo学习笔记(一) 什么都不做的EventLoop
EventLoop
EventLoop的基本接口包括构造、析构、loop()。
One Loop Per Thread 一个线程只有一个EventLoop对象、如果当前线程创建了其他 EventLoop对象,则终止程序.
CurrentThread
CurrentThread 通过__thread 关键字和系统调用syscall() 保存获取线程的的pid(不通于线程tid,tid属于进程,进程内唯一,线程pid属于内核).
#ifndef _CURRENT_THREAD
#define _CURRENT_THREAD
#include <stdint.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <pthread.h>
#include <unistd.h>
namespace CurrentThread
{
// internal
extern __thread int t_cachedTid;
extern __thread char t_tidString[32];
extern __thread int t_tidStringLength;
extern __thread const char* t_threadName;
inline int tid()
{
if (__builtin_expect(t_cachedTid == 0, 0))
{
if (t_cachedTid == 0)
{
t_cachedTid = static_cast<pid_t>(::syscall(SYS_gettid));
t_tidStringLength = snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid);
}
}
return t_cachedTid;
}
inline const char* tidString() // for logging
{
return t_tidString;
}
inline int tidStringLength() // for logging
{
return t_tidStringLength;
}
inline const char* name()
{
return t_threadName;
}
}
#endif
//CurrentThread.cpp
#include "CurrentThread.hh"
namespace CurrentThread
{
__thread int t_cachedTid = 0;
__thread char t_tidString[32];
__thread int t_tidStringLength = 6;
__thread const char* t_threadName = "unknown";
}
getEventLoopOfCurrentThread
每个线程至多有一个EventLoop对象,那么我们通过static 成员函数getEventLoopOfCurrentThread() 返回此对象.
EventLoop* EventLoop::getEventLoopOfCurrentThread()
{
return t_loopInThisThread;
}
EventLoop 源代码
#ifndef NET_EVENTLOOP_H
#define NET_EVENTLOOP_H
#include "CurrentThread.hh"
class EventLoop
{
public:
EventLoop();
~EventLoop();
void loop();
void assertInLoopThread()
{
if(!isInloopThread())
{
abortNotInLoopThread();
}
}
bool isInloopThread() const {return m_threadId == CurrentThread::tid(); }
static EventLoop* getEventLoopOfCurrentThread();
private:
EventLoop& operator=(const EventLoop&);
EventLoop(const EventLoop&);
void abortNotInLoopThread();
bool m_looping;
const pid_t m_threadId;
};
#endif
// EventLoop.cpp
#include "EventLoop.hh"
#include "Logger.hh"
#include <assert.h>
#include <poll.h>
__thread EventLoop* t_loopInThisThread = 0;
EventLoop::EventLoop()
:m_looping(false),
m_threadId(CurrentThread::tid())
{
LOG_TRACE << "EventLoop Create " << this << " in thread " << m_threadId;
if(t_loopInThisThread)
{ //每个线程只有一个EventLoop对象 , 如果当前线程创建了其他 EventLoop对象,则终止程序.
LOG_FATAL << "Anthor EventLoop " << t_loopInThisThread
<< " exists in this thread " << m_threadId;
}
else
{
t_loopInThisThread = this;
}
}
EventLoop::~EventLoop()
{
assert(!m_looping);
t_loopInThisThread = NULL;
}
void EventLoop::loop()
{
assert(!m_looping);
assertInLoopThread();
m_looping = true;
LOG_TRACE << "EventLoop " << this << " start loopig";
::poll(NULL, 0, 3*1000);
LOG_TRACE << "EventLoop " << this << " stop loopig";
m_looping = false;
}
void EventLoop::abortNotInLoopThread()
{
LOG_FATAL << "EventLoop::abortNotInLoopThread - EventLoop " << this
<< " was created in threadId_ = " << m_threadId
<< ", current thread id = " << CurrentThread::tid();
}
EventLoop* EventLoop::getEventLoopOfCurrentThread()
{
return t_loopInThisThread;
}
测试程序
test1
正确的逻辑.
#include <errno.h>
#include "EventLoop.hh"
#include <thread>
int main()
{
EventLoop testloop;
testloop.loop();
return 0;
}
./test.out
2018-10-25 20:01:03.287601 [TRACE] [EventLoop.cpp:12] [EventLoop] EventLoop Create 0x7FFF7B1E2780 in thread 2086
2018-10-25 20:01:03.287750 [TRACE] [EventLoop.cpp:36] [loop] EventLoop 0x7FFF7B1E2780 start loopig
2018-10-25 20:01:06.291622 [TRACE] [EventLoop.cpp:40] [loop] EventLoop 0x7FFF7B1E2780 stop loopig
test2
企图在当前线程启用其他线程创建的EventLoop对象
#include <errno.h>
#include "EventLoop.hh"
#include <thread>
EventLoop* g_loop;
void test()
{
g_loop->loop();
}
int main()
{
EventLoop testloop;
//testloop.loop();
g_loop = &testloop;
std::thread test_thread(test);
test_thread.join();
return 0;
}
./test.out
2018-10-25 20:05:49.618701 [TRACE] [EventLoop.cpp:12] [EventLoop] EventLoop Create 0x7FFCA55A35F0 in thread 2114
2018-10-25 20:05:49.619057 [FATAL] [EventLoop.cpp:47] EventLoop::abortNotInLoopThread - EventLoop 0x7FFCA55A35F0 was created in threadId_ = 2114, current thread id = 2115
Aborted (core dumped)
Muduo学习笔记(一) 什么都不做的EventLoop的更多相关文章
- muduo学习笔记(二)Reactor关键结构
目录 muduo学习笔记(二)Reactor关键结构 Reactor简述 什么是Reactor Reactor模型的优缺点 poll简述 poll使用样例 muduo Reactor关键结构 Chan ...
- muduo学习笔记(六) 多线程的TcpServer
目录 前言 多线程TcpServer EventLoopThreadPool 线程池设计模式 muduo中的使用 连接的建立.消息.销毁 on_connection on_message on_clo ...
- Python学习笔记:Flask-Migrate基于model做upgrade的基本原理
1)flask-migrate的官网:https://flask-migrate.readthedocs.io/en/latest/ 2)获取帮助,在pycharm的控制台中输入 flask d ...
- Python学习笔记1——人人都爱列表
一些BIF函数在列表中的应用: Python 3.3.4 (v3.3.4:7ff62415e426, Feb 10 2014, 18:13:51) [MSC v.1600 64 bit (AMD64) ...
- Java学习笔记--HashMap中使用object做key的问题【转】
在HashMap中,如果需要使用多个属性组合作为key,可以将这几个属性组合成一个对象作为key.但是存在的问题是,要做get时,往往没办法保存当初put操作时的key object的referenc ...
- 学习笔记之08试用div做网页(滨院)-小作业
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- C#学习笔记(35)——事件做的登录案例
说明(2018-4-9 20:11:42): 1. 先自定义了一个登录控件,可以输入账号.密码,点击登录.然后在Form1里面拖入这个控件,要求输入账号密码正确时,点击登录,控件显示绿色,否则显示红色 ...
- 自然语言处理NLP学习笔记三:使用Django做一个NLP的Web站点
前言: 前面我们已经能初步实现一个中文自然处理语言的模型了,但交互界面是命令行的,不太友好. 如果想做一个类似http://xiaosi.trs.cn/demo/rs/demo的界面,那就还需要继续往 ...
- Mudo C++网络库第六章学习笔记
muduo网络库简介 高级语言(Java, Python等)的Sockects库并没有对Sockects API提供更高层的封装, 直接用它编写程序很容易掉到陷阱中: 网络库的价值还在于能方便地处理并 ...
随机推荐
- 批处理之windows更改网卡IP地址
新建文本文档,更改后缀为“.bat”,写入以下代码: netsh interface ip set address name="本地连接" source=static 192.16 ...
- 【转】Java学习---JDK、JRE和JVM的关系
[原文]https://www.toutiao.com/i6591348937267872269/ 首先是JDK JDK(Java Development Kit) 是 Java 语言的软件开发工具包 ...
- List特有迭代器--ListIterator的特殊功能
/** * >列表迭代器: * ListIterator listIterator():List集合特有的迭代器 * 该迭代器继承了Iterat ...
- DevExpress11、TreeList
一.简介 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; ...
- DevExpress07、DataNavigator、 ControlNavigator
https://documentation.devexpress.com/WindowsForms/DevExpress.XtraEditors.DataNavigator.class 1.DataN ...
- PyQt5--QToggleButton
# -*- coding:utf-8 -*- ''' Created on Sep 20, 2018 @author: SaShuangYiBing Comment: '' import sys fr ...
- eclipse能正常启动tomcat,但是网页访问不了
参考网址https://blog.csdn.net/did_itmyway/article/details/62099930
- IOS和安卓不同浏览器常见bug
一.IOS自带safari浏览器 1.safari不支持fixed.input输入框 iOS下的 Fixed + Input 调用键盘的时候fixed无效问题 拖动页面时 header 和 foote ...
- WCF简单实例--用Winform启动和引用
以订票为例简单应用wcf程序,需要的朋友可以参考下 本篇转自百度文档,自己试过,确实可以用. 以订票为例简单应用wcf 新建一个wcf服务应用程序 在IService1.cs定义服务契约 namesp ...
- Springboot集成Common模块中的的全局异常处理遇见的问题
由于项目公共代码需要提取一个common模块,例如对于项目的文件上传,异常处理等,本次集成common代码时候maven引入common的全局异常处理代码之后发现不生效,由于common包路径与自己的 ...