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)