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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM