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的更多相关文章

  1. muduo学习笔记(二)Reactor关键结构

    目录 muduo学习笔记(二)Reactor关键结构 Reactor简述 什么是Reactor Reactor模型的优缺点 poll简述 poll使用样例 muduo Reactor关键结构 Chan ...

  2. muduo学习笔记(六) 多线程的TcpServer

    目录 前言 多线程TcpServer EventLoopThreadPool 线程池设计模式 muduo中的使用 连接的建立.消息.销毁 on_connection on_message on_clo ...

  3. Python学习笔记:Flask-Migrate基于model做upgrade的基本原理

      1)flask-migrate的官网:https://flask-migrate.readthedocs.io/en/latest/  2)获取帮助,在pycharm的控制台中输入 flask d ...

  4. Python学习笔记1——人人都爱列表

    一些BIF函数在列表中的应用: Python 3.3.4 (v3.3.4:7ff62415e426, Feb 10 2014, 18:13:51) [MSC v.1600 64 bit (AMD64) ...

  5. Java学习笔记--HashMap中使用object做key的问题【转】

    在HashMap中,如果需要使用多个属性组合作为key,可以将这几个属性组合成一个对象作为key.但是存在的问题是,要做get时,往往没办法保存当初put操作时的key object的referenc ...

  6. 学习笔记之08试用div做网页(滨院)-小作业

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. C#学习笔记(35)——事件做的登录案例

    说明(2018-4-9 20:11:42): 1. 先自定义了一个登录控件,可以输入账号.密码,点击登录.然后在Form1里面拖入这个控件,要求输入账号密码正确时,点击登录,控件显示绿色,否则显示红色 ...

  8. 自然语言处理NLP学习笔记三:使用Django做一个NLP的Web站点

    前言: 前面我们已经能初步实现一个中文自然处理语言的模型了,但交互界面是命令行的,不太友好. 如果想做一个类似http://xiaosi.trs.cn/demo/rs/demo的界面,那就还需要继续往 ...

  9. Mudo C++网络库第六章学习笔记

    muduo网络库简介 高级语言(Java, Python等)的Sockects库并没有对Sockects API提供更高层的封装, 直接用它编写程序很容易掉到陷阱中: 网络库的价值还在于能方便地处理并 ...

随机推荐

  1. Linux parted命令详解

    parted常见命令参数 Usage: parted [OPTION]... [DEVICE [COMMAND [PARAMETERS]...]...] Apply COMMANDs with PAR ...

  2. oracle数据库中如何去除空格

    目前,我所知道的就有两种方法: 一.trim(a)--只能去除字符串左右的空格 select trim(leading from ' ——11—— ') aa from dual; select tr ...

  3. kubeadm快速部署Kubernetes单节点

    1. 安装要求 在开始之前,部署Kubernetes集群机器需要满足以下几个条件: 一台或多台机器,操作系统 CentOS7.x-86_x64 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬 ...

  4. Win10无法启动软件提示MSVCP110.dll丢失

    遇到这种问题,第一种方法可以选择去https://www.microsoft.com/zh-CN/download/details.aspx?id=30679 官网去下载 vc++ 2012 安装和自 ...

  5. es6安装babel包

    1.前面下载node.js及安装淘宝镜像可以查看我写的vue.js环境搭建 2.安装完node后,安装babel npm install -g babel-cli 3.检验babel是否安装成功: b ...

  6. 如何安装Firebug

    Firebug是firefox下的一个插件,能够调试所有网站语言,如Html,Css等,但FireBug最吸引我的就是javascript调试功能,使用起来非常方便,而且在各种浏览器下都能使用(IE, ...

  7. Docker技术入门与实战 第二版-学习笔记-8-网络功能network-1-单个host上的容器网络

    Docker 中的网络功能介绍 Docker 允许通过外部访问容器或容器互联的方式来提供网络服务 1) 外部访问容器 容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -p或 -P参数 ...

  8. MySQL数据类型字节长度

    1.字符串 char(n): n 字节长度 varchar(n): 如果是 utf8 编码, 则是 3 n + 2字节; 如果是 utf8mb4 编码, 则是 4 n + 2 字节. 2.数值类型: ...

  9. Java中的单利模式介绍

    单利模式:本来是不准备写的,但是最近发现好多公司面试时都会或多或少的提到单利模式,因此今天把单利模式拉出来说说. 定义:只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且 ...

  10. 将myeclipse中不适用的插件禁用掉

    转载地址http://blog.csdn.net/yuanboitliuyuan/article/details/7360553 去掉启动时不用的插件启动: 操作方法: windows->pre ...