muduo源码解析23-网络库1:eventloop初步了解

eventloop类:

作用:

  我们在利用IO复用例如epoll构建服务器的时候,最基本的做法:

epoll_create();
while(1)
{
epoll_wait();
handleEvent();
}

 

如果向上面那样写的话,随着服务器功能要求增多,那个循环体肯定越来越大,代码难以理解与维护。

因此使用eventloop对这个循环体本身进行一次封装。

eventloop.h:

一开始的话eventloop类很简单,需要注意的是我们要求一个线程只能有一个eventloop对象,啥意思呢,

之前我们用while(1){epoll_wait();...}时,也是一个线程只有一个while(1){...},

eventloop正是对其进行封装,因此要求 one eventloop one thread

#ifndef EVENTLOOP_H
#define EVENTLOOP_H

#include<pthread.h>

#include"base/noncopyable.h"

namespace mymuduo
{
namespace net {

class eventloop:noncopyable
{
public:
    eventloop();
    ~eventloop();
    //eventloop的核心函数,用于不断循环,在其中调用poller::poll()用于获取发生的网络事件
    void loop();

    //断言,eventloop所属于的线程ID就是当前线程的ID
    void assertInLoopThread();
    //判断是否eventloop所属于的线程ID就是当先线程的ID
    bool isInLoopThread() const;

    //获得当前线程的那个eventloop*
    eventloop* getEventLoopOfCurrentThread();

private:

    //LOG_FATAL
    void abortNotInLoopThread();

    bool m_looping; //eventloop是否正在loop
    const pid_t m_threadId; //eventloop所在的那个线程ID,要求one eventloop one thread

};

}//namespace net

}//namespace mymuduo


#endif // EVENTLOOP_H

eventloop.cpp

#include "eventloop.h"

#include"base/currentthread.h"
#include"base/logging.h"

#include<poll.h>

namespace mymuduo {

namespace net {

//每个线程都有一个t_loopInThisThread,表示当前线程拥有的那个eventloop*
__thread eventloop* t_loopInThisThread=0;

//构造函数,初始化成员,设置当前线程的t_loopInThisThread为this
eventloop::eventloop()
    :m_looping(false),m_threadId(currentthread::tid())
{
    LOG_TRACE<<"eventloop created "<<this<<" in thread "<<m_threadId;
    //判断当前线程是否已经存在eventloop了,保证最多只有一个
    if(t_loopInThisThread)  //多创建eventloop报错
        LOG_FATAL<<"another eventloop "<<this<<" exits in this thread "<<m_threadId;
    else
        t_loopInThisThread=this;
}

eventloop::~eventloop()
{
    assert(!m_looping);
    t_loopInThisThread=NULL;    //删除当前线程的那个eventlloop*,指向NULL
}

void eventloop::loop()
{
    assert(!m_looping);
    assertInLoopThread();
    m_looping=true;
    ::poll(NULL,0,5*1000);  //poll 5s 等待网络事件
    LOG_TRACE<<"eventllop "<<this<<" stop looping";
    m_looping=false;

}
//断言,当前线程就是eventloop所在的线程
void eventloop::assertInLoopThread()
{
    if(!isInLoopThread())
        abortNotInLoopThread();
}
//...
bool eventloop::isInLoopThread() const
{
    return m_threadId==currentthread::tid();
}

//获取当前线程的那个eventloop*
eventloop* eventloop::getEventLoopOfCurrentThread()
{
    return t_loopInThisThread;
}

//LOG_FATAL,错误:eventloop所属线程不是当前线程
void eventloop::abortNotInLoopThread()
{
    LOG_FATAL << "EventLoop::abortNotInLoopThread - EventLoop " << this
              << " was created in threadId_ = " << m_threadId
              << ", current thread id = " <<  currentthread::tid();
}


}//namespace net

}//namespace mymuduo

时序图很简单

eventloop对象创建-->

eventloop::loop()开始循环-->

  { 

  (在loop()中执行如下操作)

  ::poll/::epoll_wait()等待网络事件发生

  handleEvent()处理网络事件,(之后会提到)

  }

和之前的

while(1)

{

epoll_wait();

handeEvent();

}

基本是一样的。

需要注意的有两点:

1.一个线程只能有一个eventloop

2.一个线程不能去调用另一个线程中的eventloop::loop()

测试:

#include "net/eventloop.h"
#include"base/logging.h"
#include"base/thread.h"
#include <assert.h>
#include <stdio.h>
#include <unistd.h>

using namespace mymuduo;
using namespace mymuduo::net;

//由于eventloop只能属于一个线程,loop()只能够在当前线程调用
//1.测试一下一个线程创建多个eventloop报错
//2.测试一下别的线程调用当前线程的eventloop::loop()报错

void test1()
{
    eventloop loop1;
    eventloop loop2; //error,一个线程只允许有一个eventloop
}

eventloop* g_loop;

void workerthread()
{
    g_loop->loop(); //error,不能调用别的线程的eventloop::loop()
}

void test2()
{
    eventloop loop;
    g_loop=&loop;
    mymuduo::thread t1(workerthread,"t1");
    t1.start();
    t1.join();
}

int main()
{
    mymuduo::logger::setLogLevel(mymuduo::logger::TRACE);

    test2();

}

 

打印结果:

test1:

2020年09月01日 星期2 15:16:52.1598944612 57327 TRACE eventloop eventloop created 0x7FFF3026AC80 in thread 57327 - eventloop.cpp:22
2020年09月01日 星期2 15:16:52.1598944612 57327 TRACE eventloop eventloop created 0x7FFF3026AC90 in thread 57327 - eventloop.cpp:22
2020年09月01日 星期2 15:16:52.1598944612 57327 FATAL another eventloop 0x7FFF3026AC90 exits in this thread 57327 - eventloop.cpp:25

test2:

2020年09月01日 星期2 15:17:24.1598944644 57525 TRACE eventloop eventloop created 0x7FFF0BBBA640 in thread 57525 - eventloop.cpp:22
2020年09月01日 星期2 15:17:24.1598944644 57546 FATAL EventLoop::abortNotInLoopThread - EventLoop 0x7FFF0BBBA640 was created in threadId_ = 57525, current thread id = 57546 - eventloop.cpp:67

 

posted @ 2020-09-01 15:26  WoodInEast  阅读(283)  评论(0编辑  收藏  举报