第二人生里使用線程循環(huán)來(lái)處理消息,這樣的結(jié)構(gòu)就比較清晰。比如有一個(gè)寫(xiě)文件的請(qǐng)求,就可以把這個(gè)請(qǐng)求放到線程隊(duì)列里,然后喚醒線程,讓線程處理這個(gè)請(qǐng)求。那么在第二人生里是怎么樣構(gòu)造消息循環(huán)呢?又是怎么樣執(zhí)行其它線程發(fā)過(guò)來(lái)的請(qǐng)求呢?帶著這兩個(gè)問(wèn)題來(lái)分析下面這幾段代碼。
#001?void LLQueuedThread::run()
#002?{
?
下面實(shí)現(xiàn)消息循環(huán)。
#003?
???? while (1)
#004?
???? {
#005?
??????????? // this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state.
?
下面檢查是否暫停線程執(zhí)行。
#006?
??????????? checkPause();
#007?
???????????
?
檢查線程是否要結(jié)束循環(huán)。
#008?
??????????? if(isQuitting())
#009?
?????????????????? break;
#010?
#011?
??????????? //llinfos << "QUEUED THREAD RUNNING, queue size = " << mRequestQueue.size() << llendl;
#012?
?
標(biāo)志線程已經(jīng)非空閑狀態(tài)。
#013?
??????????? mIdleThread = FALSE;
#014?
???????????
?
調(diào)用processNextRequest函數(shù)來(lái)處理本線程消息隊(duì)列里的消息。
#015?
??????????? int res = processNextRequest();
#016?
??????????? if (res == 0)
#017?
??????????? {
#018?
?????????????????? mIdleThread = TRUE;
#019?
??????????? }
#020?
???????????
?
處理線程消息出錯(cuò),退出線程循環(huán)。
#021?
??????????? if (res < 0) // finished working and want to exit
#022?
??????????? {
#023?
?????????????????? break;
#024?
??????????? }
#025?
#026?
??????????? //LLThread::yield(); // thread should yield after each request??????????
#027?
???? }
#028?
#029?
???? llinfos << "QUEUED THREAD " << mName << " EXITING." << llendl;
#030?}
?
由線程接口類LLThread就知道,線程里主要處理函數(shù)是run(),而在LLThread繼承類LLQueuedThread里也就是實(shí)現(xiàn)了這個(gè)函數(shù)的功能,主要就是調(diào)用函數(shù)processNextRequest來(lái)處理消息隊(duì)列里的消息。下面就來(lái)分析函數(shù)processNextRequest的代碼,如下:
?
#001?
#002?S32 LLQueuedThread::processNextRequest()
#003?{
#004?
???? QueuedRequest *req;
#005?
???? // Get next request from pool
?
鎖住線程消息隊(duì)列。
#006?
???? lockData();
?
循環(huán)地找到可用的消息。
#007?
???? while(1)
#008?
???? {
#009?
??????????? req = NULL;
?
線程消息隊(duì)列為空,退出處理消息。
#010?
??????????? if (mRequestQueue.empty())
#011?
??????????? {
#012?
?????????????????? break;
#013?
??????????? }
?
獲取第一個(gè)消息請(qǐng)求。
#014?
??????????? req = *mRequestQueue.begin();
?
刪除第一個(gè)消息請(qǐng)求。
#015?
??????????? mRequestQueue.erase(mRequestQueue.begin());
?
判斷是否丟掉這個(gè)消息請(qǐng)求。
#016?
??????????? if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
#017?
??????????? {
#018?
?????????????????? req->setStatus(STATUS_ABORTED);
#019?
?????????????????? req->finishRequest(false);
#020?
?????????????????? if (req->getFlags() & FLAG_AUTO_COMPLETE)
#021?
?????????????????? {
#022?
????????????????????????? mRequestHash.erase(req);
#023?
????????????????????????? req->deleteRequest();
#024?//
????????????????????? check();
#025?
?????????????????? }
#026?
?????????????????? continue;
#027?
??????????? }
#028?
??????????? llassert_always(req->getStatus() == STATUS_QUEUED);
#029?
??????????? break;
#030?
???? }
?
設(shè)置這個(gè)消息正在處理過(guò)程中。
#031?
???? if (req)
#032?
???? {
#033?
??????????? req->setStatus(STATUS_INPROGRESS);
#034?
???? }
?
解鎖消息隊(duì)列。
#035?
???? unlockData();
#036?
#037?
???? // This is the only place we will call req->setStatus() after
#038?
???? // it has initially been seet to STATUS_QUEUED, so it is
#039?
???? // safe to access req.
?
下面開(kāi)始處理獲取到的消息。
#040?
???? if (req)
#041?
???? {
?
開(kāi)始調(diào)用這個(gè)消息的特別處理函數(shù)。
#042?
??????????? // process request
#043?
??????????? bool complete = req->processRequest();
#044?
?
判斷這個(gè)請(qǐng)求是否完成。
#045?
??????????? if (complete)
#046?
??????????? {
#047?
?????????????????? lockData();
#048?
?????????????????? req->setStatus(STATUS_COMPLETE);
#049?
?????????????????? req->finishRequest(true);
#050?
?????????????????? if (req->getFlags() & FLAG_AUTO_COMPLETE)
#051?
?????????????????? {
#052?
????????????????????????? mRequestHash.erase(req);
#053?
????????????????????????? req->deleteRequest();
#054?//
????????????????????? check();
#055?
?????????????????? }
#056?
?????????????????? unlockData();
#057?
??????????? }
#058?
??????????? else
#059?
??????????? {
#060?
?????????????????? lockData();
#061?
?????????????????? req->setStatus(STATUS_QUEUED);
#062?
?????????????????? mRequestQueue.insert(req);
#063?
?????????????????? U32 priority = req->getPriority();
#064?
?????????????????? unlockData();
#065?
?????????????????? if (priority < PRIORITY_NORMAL)
#066?
?????????????????? {
#067?
????????????????????????? ms_sleep(1); // sleep the thread a little
#068?
?????????????????? }
#069?
??????????? }
#070?
???? }
#071?
?
查看是否需要退出線程。
#072?
???? S32 res;
#073?
???? S32 pending = getPending();
#074?
???? if (pending == 0)
#075?
???? {
#076?
??????????? if (isQuitting())
#077?
??????????? {
#078?
?????????????????? res = -1; // exit thread
#079?
??????????? }
#080?
??????????? else
#081?
??????????? {
#082?
?????????????????? res = 0;
#083?
??????????? }
#084?
???? }
#085?
???? else
#086?
???? {
#087?
??????????? res = pending;
#088?
???? }
#089?
???? return res;
#090?}
#091?
?
通過(guò)在processNextRequest里調(diào)用更加具體的消息處理函數(shù)processRequest來(lái)實(shí)現(xiàn)各個(gè)消息處理,由于processRequest也是純虛函數(shù),因此通過(guò)實(shí)現(xiàn)這個(gè)函數(shù)不同的形式,就可以實(shí)現(xiàn)不同的內(nèi)容處理,這就是C++的多態(tài)特性。不過(guò),要注意的是這個(gè)函數(shù)可能由多線程訪問(wèn),需要進(jìn)行同步的操作。
?
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
