zoukankan      html  css  js  c++  java
  • 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)
    
  • 相关阅读:
    mongodb配置主[Master]从[Slave]同步
    consul[安装/服务启用/注册].md
    Mysql用户管理相关
    GIT简易操作手册与分支管理策略
    Java 集合类高阶面试题
    List和Set相关面试题
    Map类面试题
    JDK相关基础面试题
    Java面向对象面试题
    MySQL in CentOS 7 安装部署
  • 原文地址:https://www.cnblogs.com/ailumiyana/p/9852498.html
Copyright © 2011-2022 走看看