muduo原始碼解析之EventLoopThread

2021-07-27 10:30:27 字數 3173 閱讀 5864

回到tcpserver,我們記得裡面有乙個eventloopthreadpool,根據名字,這是乙個執行緒池,它主要用於管理所有的eventloop,每個eventloop對應乙個執行緒。當新連線到來時,acceptor事件分發器將連線分發到合適的執行緒中。執行緒裡面核心是執行eventloop類裡面的loop函式,這個函式主要是執行epoll_wait和一些其他的處理函式。loop是乙個while迴圈。muduo在eventloop上面包裝了一層eventloopthread。eventloopthreadpool直接管理eventloopthread,eventloopthread再管理具體的thread和eventloop:

thread資料成員是是對原生執行緒的封裝,因為執行緒核心是執行eventloop,所以這裡需要乙個eventloop成員loop_來管理這個事件迴圈。threadloop通過startloop開始開啟乙個執行緒,但記住,這時候新的執行緒還沒有建立

eventloop* eventloopthread::startloop()

} return loop_;

}

到這裡新的執行緒依舊沒有建立,下面繼續看一下thread類裡面的start函式:

void

thread

::start()

}

這裡就會用pthread_create新建乙個執行緒,執行緒裡面將會執行data中的func函式,這個函式是thread類中的乙個資料成員,我們關心的是func實在**被設定的呢。回頭看一下thread的建構函式:

thread::thread(const threadfunc& func, const

string& n)

: started_(false),

joined_(false),

pthreadid_(0),

tid_(new pid_t(0)),

func_(func),//設定func

name_(n)

也就是說在新建thread的時候會確定新建執行緒執行的函式,我們回頭看一下eventloopthread的資料成員thread的建立過程:

eventloopthread::eventloopthread(const threadinitcallback& cb,

const string

& name)

: loop_(null),

exiting_(false),

thread_(boost::bind(&eventloopthread::threadfunc, this), name), //建立thread

mutex_(),

cond_(mutex_),

callback_(cb)

可以看到新建執行緒中執行的函式是eventloopthread中的threadfunc私有成員函式:

void eventloopthread::threadfunc() // 這個函式執行在乙個新的執行緒中

loop

.loop(); //這裡就會一直迴圈,

//assert(exiting_);

loop_ =

null; //如果到達了這裡,說明這個loop退出了

}

這裡先呼叫callback_,然後呼叫eventloop中的loop()函式。到此,eventloop便和這個新建立的執行緒聯絡起來了。我們知道loop函式是乙個while迴圈,因此執行緒將會一直執行loop函式,並在裡面處理事情。這個loop函式顯然可以訪問eventloop結構中的資料成員和函式成員,因此我們通過改變這個eventloop結構中的具體資料成員和函式成員,就可以達到讓執行緒在loop函式中為我們做定製的事情。所以我們通過eventloop結構接管了對這個執行緒的控制。

另外我們可以看到函式中有條件變數的使用,這裡的條件變數主要是作用於最開始時,eventloopthread中的startloop的呼叫。在startloop中需要返回loop_指標,但是這個指標開始時是空的,到新執行緒中才建立具體的eventloop,而此時loop_指正才指向它。因此需要用條件變數,以等待新執行緒中建立好eventloop,否則返回的loop_將為空。這裡的notify主要是通知呼叫startloop的執行緒,指向新執行緒的eventloop已經建立完畢了,並已經用loop_指正指向了它,可以將loop_從startloop函式返回了。

我們還應該注意到,這個eventloop結構是在threadfunc中建立的。在eventloopthread的建構函式中直接將loop_指標指向null。之所以在這裡建立eventloop主要是為了記錄執行緒號。因為這個函式已經執行在新建執行緒中了,這樣我們就可以獲得新執行緒號,並把它記錄在新建的loop結構中。這樣我們就把每個eventloop和乙個唯一的執行緒繫結起來了。後面我們通過控制這個eventloop就可以控制線程的執行。這裡主要是可以把任務掛到eventloop的pendingfunctors_中讓loop去完成。從loop函式的原始碼可以看到這點:

void eventloop::loop()

// todo sort channel by priority

eventhandling_ =

true;

for (channellist::iterator it = activechannels_.begin();

it != activechannels_.end(); ++it)

currentactivechannel_ =

null;

eventhandling_ =

false;

dopendingfunctors(); // 處理完了io事件之後,處理等待在佇列中的任務

} log_trace <<

"eventloop "

<< this <<

" stop looping";

looping_ =

false;

}

loop函式的核心是事件迴圈,這裡我們關心的是最後的

dopendingfunctors();

muduo原始碼解析1 timestamp類

class timestamp public mymuduo copyable,public boost equality comparable,public boost less than comparable 主要是實現了時間戳的相關操作,例如時間戳的格式化,返回當前時間戳等等。private ...

muduo原始碼解析21 Socket類

封裝了乙個套接字sokcet類,內部只儲存乙個套接字檔案描述符m sockfd 提供了常用的套接字相關的操作,例如 繫結套接字,監聽,接受乙個連線,關閉寫操作,獲取tcp資訊,設定套接字為no delay模式,設定位址重用,埠重用,設定keepalive private 套接字檔案描述符,用cons...

muduo原始碼解析9 timezone類

class timezone public copyable 感覺有點看不懂,detail內部實現檔案類不明白跟時區有什麼關係.timezone類主要是完成各個時區之間的轉換,感覺自己用不到,乙個時區就夠了.內部成員變數就乙個,是個data結構體的共享智慧型指標 提供了3個建構函式,timezone...