日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

第二人生的源碼分析(四十二)實(shí)現(xiàn)消息處理的線程

系統(tǒng) 1874 0
第二人生里使用線程循環(huán)來處理消息,這樣的結(jié)構(gòu)就比較清晰。比如有一個(gè)寫文件的請(qǐng)求,就可以把這個(gè)請(qǐng)求放到線程隊(duì)列里,然后喚醒線程,讓線程處理這個(gè)請(qǐng)求。那么在第二人生里是怎么樣構(gòu)造消息循環(huán)呢?又是怎么樣執(zhí)行其它線程發(fā)過來的請(qǐng)求呢?帶著這兩個(gè)問題來分析下面這幾段代碼。
#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ù)來處理本線程消息隊(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來處理消息隊(duì)列里的消息。下面就來分析函數(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è)消息正在處理過程中。
#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.
?
下面開始處理獲取到的消息。
#040? ???? if (req)
#041? ???? {
?
開始調(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?
?
通過在processNextRequest里調(diào)用更加具體的消息處理函數(shù)processRequest來實(shí)現(xiàn)各個(gè)消息處理,由于processRequest也是純虛函數(shù),因此通過實(shí)現(xiàn)這個(gè)函數(shù)不同的形式,就可以實(shí)現(xiàn)不同的內(nèi)容處理,這就是C++的多態(tài)特性。不過,要注意的是這個(gè)函數(shù)可能由多線程訪問,需要進(jìn)行同步的操作。
?
?

第二人生的源碼分析(四十二)實(shí)現(xiàn)消息處理的線程類


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

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

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 华亭县| 赣榆县| 洪湖市| 香河县| 建始县| 什邡市| 道孚县| 溆浦县| 龙岩市| 临漳县| 永寿县| 莱州市| 濮阳市| 德化县| 哈巴河县| 安康市| 崇明县| 江源县| 葵青区| 延寿县| 嘉峪关市| 阳谷县| 三河市| 南汇区| 鄂尔多斯市| 武鸣县| 西盟| 长岭县| 铁岭县| 荣成市| 保靖县| 兰考县| 通河县| 抚宁县| 双柏县| 黄平县| 漠河县| 衡水市| 荆州市| 临夏县| 自贡市|