Chromium多線程模型設(shè)計和視線分析_第1頁
Chromium多線程模型設(shè)計和視線分析_第2頁
Chromium多線程模型設(shè)計和視線分析_第3頁
Chromium多線程模型設(shè)計和視線分析_第4頁
Chromium多線程模型設(shè)計和視線分析_第5頁
已閱讀5頁,還剩62頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、一個典型的異步通信過程如圖1所示:圖1  線程異步通信過程       Task-1被分解成三個子任務(wù)Task-1(1)、Task-1(2)和Task-1(3)。其中,Task-1(1)由Thread-1執(zhí)行。Task-1(1)執(zhí)行完成后,Thread-1通過我們在前面Chromium多線程通信的Closure機(jī)制分析一文分析的Closure請求Thread-2執(zhí)行Task-1(2)。Task-1(2)執(zhí)行完成后,Thread-2又通過一個Closure請求Thread-1執(zhí)行Task-1(3)。至此,Task-1就執(zhí)行完成。我們可以將第一個C

2、losure看作是一個Request操作,而第二個Closure是一個Reply操作。這是一個典型的異步通信過程。當(dāng)然,如果不需要知道異步通信結(jié)果,那么第二個Closure和Task-1(3)就是不需要的。       假設(shè)Thread-1需要知道異步通信的結(jié)果,那么在圖1中我們可以看到一個非常關(guān)鍵的點(diǎn):Thread-1并不是什么也不干就只是等著Thread-2執(zhí)行完成Task-1(2),它趁著這個等待的空隙,干了另外一件事情Task-2。如果我們將Thread-1看作是一個UI線程,那么就意味著這種異步通信模式是可以提高它的響應(yīng)性的。  &#

3、160;    為了能夠完成上述的異步通信過程,一個線程的生命周期如圖2所示:圖2 線程生命周期       線程經(jīng)過短暫的啟動之后(Start),就圍繞著一個任務(wù)隊列(TaskQueue)不斷地進(jìn)行循環(huán),直到被通知停止為止(Stop)。在圍繞任務(wù)隊列循環(huán)期間,它會不斷地檢查任務(wù)隊列是否為空。如果不為空,那么就會將里面的任務(wù)(Task)取出來,并且進(jìn)行處理。這樣,一個線程如果要請求另外一個線程執(zhí)行某一個操作,那么只需要將該操作封裝成一個任務(wù),并且發(fā)送到目標(biāo)線程的任務(wù)隊列去即可。       為了

4、更好地理解這種基于任務(wù)隊列的線程運(yùn)行模式,我們腦補(bǔ)一下另外一種常用的基于鎖的線程運(yùn)行模式。一個線程要執(zhí)行某一個操作的時候,就直接調(diào)用一個代表該操作的一個函數(shù)。如果該函數(shù)需要訪問全局?jǐn)?shù)據(jù)或者共享數(shù)據(jù),那么就需要進(jìn)行加鎖,避免其它線程也正在訪問這些全局?jǐn)?shù)據(jù)或者共享數(shù)據(jù)。這樣做的一個好處是我們只需要關(guān)心問題的建模,而不需要關(guān)心問題是由誰來執(zhí)行的,只要保證邏輯正確并且數(shù)據(jù)完整即可。當(dāng)然壞處也是顯然的。首先是為了保持?jǐn)?shù)據(jù)完整性,也就是避免訪問數(shù)據(jù)時出現(xiàn)競爭條件,代碼里面充斥著各種鎖。其次,如果多個線程同時獲取同一個鎖,那么就會產(chǎn)生競爭。這種鎖競爭會帶來額外的開銷,從而降低線程的響應(yīng)性。  &#

5、160;    基于任務(wù)隊列的線程運(yùn)行模式,要求在對問題進(jìn)行建模時,要提前知道誰是執(zhí)行者。也就是說,在對問題進(jìn)行建模時,需要指派好每一個子問題的執(zhí)行者。這樣我們?yōu)樽訂栴}設(shè)計數(shù)據(jù)結(jié)構(gòu)時,就規(guī)定這些數(shù)據(jù)結(jié)構(gòu)僅僅會被子問題的執(zhí)行者訪問。這樣執(zhí)行者在解決指派給它的問題時,就不需要進(jìn)行加鎖操作,因為在解決問題過程中需要訪問的數(shù)據(jù)不會同時被其它執(zhí)行者訪問。這就是通過任務(wù)隊列來實現(xiàn)異步通信的多線程模型的設(shè)計哲學(xué)。       當(dāng)然,這并不是說,基于任務(wù)隊列的線程運(yùn)行模式可以完全避免使用鎖,因為任務(wù)隊列本身就是一個線程間的共享資源。想象一下,一個線程

6、要往里面添加任務(wù),另一個線程要從里面將任務(wù)提取出來處理。因此,所有涉及到任務(wù)隊列訪問的地方都是需要加鎖的。但是如果我們再仔細(xì)想想,那么就會發(fā)現(xiàn),任務(wù)隊列只是一個基礎(chǔ)設(shè)施,它與具體的問題是無關(guān)的。因此,只要我們遵循上述設(shè)計哲學(xué),就可以將代碼里面需要加鎖的地方僅限于訪問任務(wù)隊列的地方,從而就可以減少鎖競爭帶來的額外的開銷。       這樣說來,似乎基于任務(wù)隊列的線程運(yùn)行模式很好,但是實際上它對問題建模提出了更高的要求,也就是進(jìn)行子問題劃分時,要求劃分出來的子問題是正交的,這樣我們才有可能為這些子問題設(shè)計出不會同時被訪問的數(shù)據(jù)結(jié)構(gòu)??吹健罢弧眱蓚€字,是不是

7、想起高數(shù)里面的向量空間的正交基了?或者傅里葉變換用到的一組三角函數(shù)了?其實道理就是一樣一樣的。       好了,說了這么多,我們就步入到正題,分析Chromium多線程模型的設(shè)計和實現(xiàn),也就是基于任務(wù)隊列的線程運(yùn)行模式涉及到核心類圖,如圖3所示:圖3 基于任務(wù)隊列的線程運(yùn)行模式核心類關(guān)系圖       Thread是一個用來創(chuàng)建帶消息循環(huán)的類。當(dāng)我們創(chuàng)建一個Thread對象后,調(diào)用它的成員函數(shù)Start或者StartWithOptions就可以啟動一個帶消息循環(huán)的線程。其中,成員函數(shù)StartWithO

8、ptions可以指定線程創(chuàng)建參數(shù)。當(dāng)我們不需要這個線程時,就可以調(diào)用之前創(chuàng)建的Thread對象的成員函數(shù)Stop。       Thread類繼承了PlatformThread:Delegate類,并且重寫了它的成員函數(shù)ThreadMain。我們知道,Chromium是跨平臺的,這樣各個平臺創(chuàng)建線程使用的API有可能是不一樣的。不過,我們可以通過PlatformThread:Delegate類為各個平臺創(chuàng)建的線程提供一個入口點(diǎn)。這個入口點(diǎn)就是PlatformThread:Delegate類的成員函數(shù)ThreadMain。由于Thread類重寫了父類Pla

9、tformThread:Delegate的成員函數(shù)ThreadMain,因此無論是哪一個平臺,當(dāng)它創(chuàng)建完成一個線程后,都會以Thread類的成員函數(shù)ThreadMain作為線程的入口點(diǎn)。       Thread類有一個重要的成員變量message_loop_,它指向的是一個MessageLoop對象。這個MessageLoop對象就是用來描述線程的消息循環(huán)的。MessageLoop類內(nèi)部通過成員變量run_loop_指向的一個RunLoop對象和成員變量pump_指向的一個MessagePump對象來描述一個線程的消息循環(huán)。   

10、   一個線程在運(yùn)行的過程中,可以有若干個消息循環(huán),也就是一個消息循環(huán)可以運(yùn)行在另外一個消息循環(huán)里面。除了最外層的消息循環(huán),其余的消息的消息循環(huán)稱為嵌套消息循環(huán)。我們?yōu)槭裁葱枰短紫⒀h(huán)呢?這主要是跟模式對話框有關(guān)。       考慮一個情景,我們在一個窗口彈出一個文件選擇對話框。窗口必須要等到用戶在文件選擇對話框選擇了文件之后,才能去做其它事情。窗口是在消息循環(huán)過程中打開文件對話框的,它要等待用戶在文件選擇對話框中選擇文件 ,就意味著消息循環(huán)被中止了。由于文件選擇對話框也是通過消息循環(huán)來響應(yīng)用戶輸入的,因此如果打開的它窗口中止了消

11、息循環(huán),就會導(dǎo)致它無法響應(yīng)用戶輸入。為了解決這個問題,就要求打開文件選擇的窗口不能中止消息循環(huán)。方法就是該窗口創(chuàng)建一個子消息循環(huán),該子消息循環(huán)負(fù)責(zé)處理文件選擇對應(yīng)框的輸入事件,直到用戶選擇了一個文件為止。       MessageLoop類的成員變量run_loop_指向的一個RunLoop對象就是用來記錄線程當(dāng)使用的消息循環(huán)的。RunLoop類有三個重要的成員變量:       1. message_loop_,記錄一個RunLoop對象關(guān)聯(lián)的MessageLoop對象。    &

12、#160;  2. previous_loop_,記錄前一個消息循環(huán),當(dāng)就是包含當(dāng)前消息循環(huán)的消息循環(huán)。       3. run_depth_,記錄消息循環(huán)的嵌套深度。       MessageLoop類的成員變量pump_指向的一個MessagePump對象是用來進(jìn)行消息循環(huán)的,也就是說,Thread類描述的線程通過MessagePump類進(jìn)入到消息循環(huán)中去。       Thread類將消息劃分為三類,分別通過以下三個成員變量來描述:&#

13、160;      1. work_queue_,指向一個TaskQueue對象,用來保存那些需要馬上處理的消息。       2. delayed_work_queue_,指向一個DelayedTaskQueue,用來保存那些需要延遲一段時間再處理的消息。       3. deferred_non_nestable_work_queue_,指向一個TaskQueue對象,用來保存那些不能夠在嵌套消息循環(huán)中處理的消息。    

14、0;  一個MessagePump對象在進(jìn)行消息循環(huán)時,如果發(fā)現(xiàn)消息隊列中有消息,那么就需要通知關(guān)聯(lián)的MessageLoop對象進(jìn)行處理。通知使用的接口就通過MessagePump:Delegate類來描述。       MessagePump:Delegate類定義了四個成員函數(shù),如下所示:       1. DoWork,用來通知MessageLoop類處理其成員變量work_queue_保存的消息。       2. DoDelayedWo

15、rk,用來通知MessageLoop類處理其成員變量delayed_work_queue_保存的消息。       3. DoIdleWork,用來通知MessageLoop類當(dāng)前無消息需要處理,MessageLoop類可以利用該間隙做一些Idle Work。       4. GetQueueingInformation,用來獲取MessageLoop類內(nèi)部維護(hù)的消息隊列的信息,例如消息隊列的大小,以及下一個延遲消息的處理時間。       有了前面的基

16、礎(chǔ)知識,接下來我們就可以大概描述Thread類描述的線程的執(zhí)行過程。       首先是線程的啟動過程:       1. 調(diào)用Thread類的成員函數(shù)Start或者StartWithOptions啟動一個線程,并且以Thread類的成員函數(shù)ThreadMain作為入口點(diǎn)。       2. Thread類的成員函數(shù)ThreadMain負(fù)責(zé)創(chuàng)建消息循環(huán),也就是通過MessageLoop類創(chuàng)建消息循環(huán)。       3.

17、0;MessageLoop類在創(chuàng)建消息循環(huán)的過程中,會通過成員函數(shù)Init創(chuàng)建用來一個用來消息循環(huán)的MessagePump對象。       4. 消息循環(huán)創(chuàng)建完成之后,調(diào)用MessageLoop類的成員函數(shù)Run進(jìn)入消息循環(huán)。       5. MessageLoop類的成員函數(shù)Run創(chuàng)建一個RunLoop對象,并且調(diào)用它的成員函數(shù)Run進(jìn)入消息循環(huán)。注意,該RunLoop對象在創(chuàng)建的過程,會關(guān)聯(lián)上當(dāng)前線程使用的消息循環(huán),也就是創(chuàng)建它的MessageLoop對象。    &

18、#160;  6. RunLoop類的成員函數(shù)Run負(fù)責(zé)建立好消息循環(huán)的嵌套關(guān)系,也就是設(shè)置好它的成員變量previous_loop_和run_depth_等,然后就會調(diào)用其關(guān)聯(lián)的MessageLoop對象的成員函數(shù)RunHandler進(jìn)入消息循環(huán)。       7. MessageLoop類的成員函數(shù)RunHandler調(diào)用成員變量pump_描述的一個MessagePump對象的成員函數(shù)Run進(jìn)入消息循環(huán)。       接下來是向線程的消息隊列發(fā)送消息的過程。這是通過MessageL

19、oop類的以下四個成員函數(shù)向消息隊列發(fā)送消息的:       1. PostTask,發(fā)送需要馬上進(jìn)行處理的并且可以在嵌套消息循環(huán)中處理的消息。       2. PostDelayedTask,發(fā)送需要延遲處理的并且可以在嵌套消息循環(huán)中處理的消息。       3. PostNonNestableTask,發(fā)送需要馬上進(jìn)行處理的并且不可以在嵌套消息循環(huán)中處理的消息。(已經(jīng)移除了)       4.

20、0;PostNonNestableDelayedTask,發(fā)送需要延遲處理的并且不可以在嵌套消息循環(huán)中處理的消息。(已經(jīng)移除了)       向線程的消息隊列發(fā)送了新的消息之后,需要喚醒線程,這是通過調(diào)用MessagePump類的成員函數(shù)Schedule進(jìn)行的。線程被喚醒之后 ,就會分別調(diào)用MessageLoop類重寫父類MessagePump:Delegate的兩個成員函數(shù)DoWork和DoDelayedWork對消息隊列的消息進(jìn)行處理。如果沒有消息可以處理,就調(diào)用MessageLoop類重寫父類MessagePump:Delegate的成員函數(shù)DoI

21、dleWork通知線程進(jìn)入Idle狀態(tài),這時候線程就可以做一些Idle Work。       MessageLoop類的成員函數(shù)DoWork在處理消息的過程中,按照以下三個類別進(jìn)行處理:       1. 對于可以馬上處理的消息,即保存在成員變量work_queue_描述的消息隊列的消息,執(zhí)行它們的成員函數(shù)Run。       2. 對于需要延遲處理的消息,將它們保存在成員變量delayed_work_queue_描述的消息隊列中,并且調(diào)用成員變量pump_指向的一個Mes

22、sagePump對象的成員函數(shù)ScheduleDelayedWork設(shè)置最早一個需要處理的延遲消息的處理時間,以便該MessagePump對象可以優(yōu)化消息循環(huán)邏輯。       3. 對于可以馬上處理但是不可以在嵌套消息循環(huán)中處理的消息,如果線程是處理嵌套消息循環(huán)中,那么將它們保存在成員變量deferred_non_nestable_work_queue_描述的消息隊列中,這些消息將會在線程進(jìn)入Idle狀態(tài)時,并且是處理最外層消息循環(huán)時,得到處理。       以上就是Thread類描述的線程的大概執(zhí)行過程,接下來

23、我們通過源碼分析詳細(xì)描述這些過程。 我們首先看線程的啟動過程,即Thread類的成員函數(shù)Start的實現(xiàn),如下所示: 1. bool Thread:Start()   2.   Options options;  3.   .  4.   return StartWithOptions(options);  5.          這個函數(shù)定義在文

24、件external/chromium_org/base/threading/thread.cc中。Thread類的成員函數(shù)Start調(diào)用另外一個成員函數(shù)StartWithOptions來啟動一個線程,后者可以通過一個類型為Options的參數(shù)指定線程的啟動參數(shù),這里沒有指定,意味著采用默認(rèn)參數(shù)啟動一個線程。       Thread類的成員函數(shù)StartWithOptions的實現(xiàn)如下所示: 1. bool Thread:StartWithOptions(const Options& options) &#

25、160; 2.   .  3. / Reset |id_| here to support restarting the thread.4. id_event_.Reset();5. id_ = kInvalidThreadId;6.7. SetThreadWasQuitProperly(false);8.9. MessageLoop:Type type = options.message_loop_type;10. if (!options.message_pump_factory.is_null()11. type = MessageLoo

26、p:TYPE_CUSTOM;12.13. message_loop_timer_slack_ = options.timer_slack;14. std:unique_ptr<MessageLoop> message_loop =15. MessageLoop:CreateUnbound(type, options.message_pump_factory);16. message_loop_ = message_loop.get();17. start_event_.Reset();18.19. / Hold the thread_lock_ while starting a n

27、ew thread, so that we can make sure20. / that thread_ is populated before the newly created thread accesses it.21. 22. AutoLock lock(thread_lock_);23. if (!PlatformThread:CreateWithPriority(options.stack_size, this, &thread_, options.priority) 24. DLOG(ERROR) << "failed to create thre

28、ad"25. message_loop_ = nullptr;26. return false;27. 28. 29.30. / The ownership of message_loop is managemed by the newly created thread31. / within the ThreadMain.32. ignore_result(message_loop.release();  33. .  34.   return true;  35.   &

29、#160;    這個函數(shù)定義在文件external/chromium_org/base/threading/thread.cc中。變量message_loop_type來創(chuàng)建指定Message Loop的類型 ,從而確定要創(chuàng)建的MessagePump。通過調(diào)用MessageLoop:CreateUnbound來生成一個MessageLoop。start_event_是創(chuàng)建的線程使用message_loop使用的信號。1. std:unique_ptr<MessageLoop> MessageLoop:CreateUnbound(2. Type type,3.

30、MessagePumpFactoryCallback pump_factory) 4. return WrapUnique(new MessageLoop(type, pump_factory);5.  1. template <typename T>2. std:unique_ptr<T> wrapUnique(T* ptr)3. 4. return std:unique_ptr<T>(ptr);5.  通過Messageloop的構(gòu)造函數(shù)來生成。這個函數(shù)定義在文件external/chromium_org/base/message_l

31、oop/Message_loop.cc中。1. MessageLoop:MessageLoop(Type type, MessagePumpFactoryCallback pump_factory)2. : type_(type),3. .4. nestable_tasks_allowed_(true),5. pump_factory_(pump_factory),6. message_histogram_(NULL),7. run_loop_(NULL),8. incoming_task_queue_(new internal:IncomingTaskQueue(this),9. unbou

32、nd_task_runner_(10. new internal:MessageLoopTaskRunner(incoming_task_queue_),11. task_runner_(unbound_task_runner_),12. thread_id_(kInvalidThreadId) 13. / If type is TYPE_CUSTOM non-null pump_factory must be given.14. DCHECK(type_ != TYPE_CUSTOM | !pump_factory_.is_null(); 15.    

33、;MessageLoop類的成員變量type_描述的是消息循環(huán)的類型,nestable_tasks_allowed_描述當(dāng)前是否允許處理嵌套消息,runn_loop_描述的是當(dāng)前使用的消息循環(huán)。 同時創(chuàng)建了一個任務(wù)隊列,并且保存在成員變量incoming_task_queue_中。這個任務(wù)隊列通過IncomingQueue類來描述,它的定義如下所示:1. class BASE_EXPORT IncomingTaskQueue  2.     : public RefCountedThr

34、eadSafe<IncomingTaskQueue>   3.  public:  4.   .  5.   6.   bool AddToIncomingQueue(const tracked_objects:Location& from_here,  7.           

35、0;               const Closure& task,  8.                           Tim

36、eDelta delay,  9.                           bool nestable);  10.   11.   .  12.    13.  &#

37、160;void ReloadWorkQueue(TaskQueue* work_queue);  14.   15.   .  16.   17.   void WillDestroyCurrentMessageLoop();  18.    19.   .  20.   21.  private:  22

38、.   .  23.   24.   TaskQueue incoming_queue_;  25.   26.   .  27.   28.   MessageLoop* message_loop_;  29.   30.   .  31. ;      &

39、#160;  這個類定義在external/chromium_org/base/message_loop/incoming_task_queue.h中。 IncomingQueue類有兩個重要的成員變量:       1. incoming_queue_,它描述的是一個TaskQueue,代表的是線程的消息隊列,也就是所有發(fā)送給線程的消息都保存在這里。       2. message_loop_,它指向一個MessageLoop對象,描述的是線程的消息循環(huán)。  &

40、#160;    IncomingQueue類有三個重要的成員函數(shù):       1. AddToIncomingQueue,用來向成員變量incoming_queue_描述的消息隊列發(fā)送一個消息,并且喚醒線程進(jìn)行處理。       2. ReloadWorkQueue,用來提取成員變量incoming_queue_描述的消息隊列中的消息,并且保存在參數(shù)work_queue中。       3. WillDestroyCurr

41、entMessageLoop,當(dāng)該函數(shù)被調(diào)用時,會將成員變量message_loop_的值設(shè)置為NULL,使得我們不能夠再向線程發(fā)送消息,也就是請求線程執(zhí)行某一個操作。task_runner_是SingleThreadTaskRunner類型的變量,作用包括有:向現(xiàn)有的線程的MessageLoop發(fā)布任務(wù);創(chuàng)建他們自己的工作線程和 發(fā)送任務(wù)給的MessageLoop;將任務(wù)添加到一個 FIFO 和添加信號到非 MessageLoop 線程讓他們來處理。unbound_task_runner_是SingleThreadTaskRunner類型的變量,通過MessageLoop創(chuàng)建和管理的Sing

42、leThreadTaskRunner的常用實現(xiàn),只能作為MessageLoop的一部分。然后調(diào)用PlatformThread: CreateWithPriority方法。1. bool PlatformThread:CreateWithPriority(size_t stack_size, Delegate* delegate,2. PlatformThreadHandle* thread_handle,3. ThreadPriority priority) 4. return CreateThread(stack_size, true, / joinable thread5. delegat

43、e, thread_handle, priority);6.       這個函數(shù)定義在文件external/chromium_org/base/threading/PlatformThread.h中。具體的基于posix平臺的實現(xiàn)在Platform_thread_posix.cc中,調(diào)用方法CreateThread來實現(xiàn)的。下面是CreateThread函數(shù)的主要代碼。pthread_attr_init初始化一個線程對象的屬性,需要用pthread_attr_destroy函數(shù)對其去除初始化。pthread_attr_setdetachstate設(shè)置線

44、程的分離狀態(tài)。線程的分離狀態(tài)決定一個線程以什么樣的方式來終止自己。在默認(rèn)情況下線程是非分離狀態(tài)的,這種情況下,原有的線程等待創(chuàng)建的線程結(jié)束。只有當(dāng)pthread_join()函數(shù)返回時,創(chuàng)建的線程才算終止,才能釋放自己占用的系統(tǒng)資源。而分離線程不是這樣子的,它沒有被其他的線程所等待,自己運(yùn)行結(jié)束了,線程也就終止了,馬上釋放系統(tǒng)資源。設(shè)置線程分離狀態(tài)的函數(shù)為pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)。第二個參數(shù)可選為PTHREAD_CREATE_DETACHED(分離線程)和 PTHREAD _CREATE

45、_JOINABLE(非分離線程)。1. bool CreateThread( ) 2. DCHECK(thread_handle);3. base:InitThreading();4.   .  5. pthread_attr_init(&attributes);6.  .  7. if (!joinable)8. pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);9. . 10. int err = pthread_creat

46、e(&handle, &attributes, ThreadFunc, params.get();11. .  12. *thread_handle = PlatformThreadHandle(handle);13.14. pthread_attr_destroy(&attributes);15.   .  16.  這個函數(shù)定義在external/chromium_org/base/threading/ Platform_thread_posix.cc中,從這里就可以看到,調(diào)用POSIX線程庫中的函數(shù)pth

47、read_create創(chuàng)建了一個線程,并且指定新創(chuàng)建的線程的入口點(diǎn)函數(shù)為ThreadFunc,同時傳遞給該入口點(diǎn)函數(shù)的參數(shù)為一個ThreadParams對象,該ThreadParams對象封裝了線程啟動過程中需要使用到的一系列參數(shù)。新創(chuàng)建線程的入口點(diǎn)函數(shù)ThreadFunc的實現(xiàn)如下所示:1. void* ThreadFunc(void* params)   2.   .  3.   ThreadParams* thread_params = static

48、_cast<ThreadParams*>(params);  4.   5.   PlatformThread:Delegate* delegate = thread_params->delegate;  6.   .  7.   8.   delegate->ThreadMain();  9.   10.   . 

49、; 11.   return NULL;  12.   這個函數(shù)定義在external/chromium_org/base/threading/platform_thread_posix.cc中。函數(shù)ThreadFunc首先將參數(shù)params轉(zhuǎn)換為一個ThreadParams對象。有了這個ThreadParams對象之后,通過它的成員變量delegate獲得一個PlatformThread:Delegate對象。從前面的調(diào)用過程可以知道, PlatformThread:Delegate對象實際是一個Thread對象

50、,用來描述新創(chuàng)建的線程。得到了用來描述新創(chuàng)建線程的Thread對象之后,就可以調(diào)用它的成員函數(shù)ThreadMain繼續(xù)啟動線程了。        Thread類的成員函數(shù)ThreadMain的實現(xiàn)如下所示:1. void Thread:ThreadMain()   2.     3.     .  4.     scoped_ptr<MessageLoop>

51、; message_loop;  5.     std:unique_ptr<MessageLoop> message_loop(message_loop_);6. message_loop_->BindToCurrentThread();7. message_loop_->SetTimerSlack(message_loop_timer_slack_); 8.     .  9.   10.  

52、60; / Let the thread do extra initialization.11. Init();12.13. 14. AutoLock lock(running_lock_);15. running_ = true;16. 17.18. start_event_.Signal();19.20. Run(message_loop_);21.22. 23. AutoLock lock(running_lock_);24. running_ = false;25. 26.27. / Let the thread do extra cleanup.28. CleanUp();

53、29.30. if (message_loop->type() != MessageLoop:TYPE_CUSTOM) 31. / Assert that MessageLoop:QuitWhenIdle was called by ThreadQuitHelper.32. / Don't check for custom message pumps, because their shutdown might not33. / allow this.34. DCHECK(GetThreadWasQuitProperly();35. 36.37. / We can't re

54、ceive messages anymore.38. / (The message loop is destructed at the end of this block)39. message_loop_ = nullptr; 40.     41.   這個函數(shù)定義在文件external/chromium_org/base/threading/thread.cc中。之前的MessageLoop已經(jīng)通過其構(gòu)造函數(shù)創(chuàng)建過。調(diào)用MessageLoop的BindToCurrentThread函數(shù),函數(shù)定義如下:1. void M

55、essageLoop:BindToCurrentThread() 2. DCHECK(!pump_);3. if (!pump_factory_.is_null()4. pump_ = pump_factory_.Run();5. else6. pump_ = CreateMessagePumpForType(type_);7.8. DCHECK(!current() << "should only have one message loop per thread"9. lazy_tls_ptr.Pointer()->Set(this);10.11. in

56、coming_task_queue_->StartScheduling();12. unbound_task_runner_->BindToCurrentThread();13. unbound_task_runner_ = nullptr;14. SetThreadTaskRunnerHandle();15. 16. / Save the current thread's ID for potential use by other threads17. / later from GetThreadName().18. thread_id_ = PlatformThread

57、:CurrentId();19. subtle:MemoryBarrier();20. 21.  該函數(shù)調(diào)用另外一個成員函數(shù)CreateMessagePumpForType根據(jù)消息循環(huán)的類型創(chuàng)建一個消息泵(Message Pump),并且保存在成員變量pump_中。MessageLoop類的成員函數(shù)CreateMessagePumpForType的實現(xiàn)如下所示:1. #if defined(USE_GLIB) && !defined(OS_NACL)2. typedef MessagePumpGlib MessagePumpForUI;3. #elif defined

58、(OS_LINUX) && !defined(OS_NACL)4. typedef MessagePumpLibevent MessagePumpForUI;5. #endif6.7. #if defined(OS_IOS) | defined(OS_MACOSX)8. #define MESSAGE_PUMP_UI std:unique_ptr<MessagePump>(MessagePumpMac:Create()9. #elif defined(OS_NACL)10. / Currently NaCl doesn't have a UI Message

59、Loop.11. / TODO(abarth): Figure out if we need this.12. #define MESSAGE_PUMP_UI std:unique_ptr<MessagePump>()13. #else14. #define MESSAGE_PUMP_UI std:unique_ptr<MessagePump>(new MessagePumpForUI()15. #endif16.17. #if defined(OS_MACOSX)18. / Use an OS native runloop on Mac to support time

60、r coalescing.19. #define MESSAGE_PUMP_DEFAULT 20. std:unique_ptr<MessagePump>(new MessagePumpCFRunLoop()21. #else22. #define MESSAGE_PUMP_DEFAULT 23. std:unique_ptr<MessagePump>(new MessagePumpDefault()24. #endif25. .  26.   if (type = MessageLoop:TYPE_

61、UI)   27.     if (message_pump_for_ui_factory_)  28.       return message_pump_for_ui_factory_();  29.     return MESSAGE_PUMP_UI;  30.     31.  

62、 if (type = MessageLoop:TYPE_IO)  32.     return scoped_ptr<MessagePump>(new MessagePumpForIO();  33.34.   #if defined(OS_ANDROID)35. if (type = MessageLoop:TYPE_JAVA)36. return std:unique_ptr<MessagePump>(ne

63、w MessagePumpForUI();37. #endif38.   return scoped_ptr<MessagePump>(new MessagePumpDefault();  39.    這個函數(shù)定義在文件external/chromium_org/base/message_loop/message_loop.cc中。上面的代碼通過一系列宏來適配不同的平臺,這里我們只考慮Linux平臺,這意味著MessagePumpForUI定義為MessagePumpLibevent,MES

64、SAGE_PUMP_UI定義為std:unique_ptr<MessagePump>(new MessagePumpForUI()。MESSAGE_PUMP_DEFAULT定義為std:unique_ptr<MessagePump>(new MessagePumpDefault()。       從MessageLoop類的成員函數(shù)CreateMessagePumpForType的實現(xiàn)可以知道:       1. 如果消息循環(huán)的類型為MessageLoop:TYPE_UI,那么對應(yīng)的消息泵為

65、MessagePumpForUI,或者由函數(shù)指針message_pump_for_ui_factory_指向的函數(shù)創(chuàng)建。但是一般不設(shè)置函數(shù)指針message_pump_for_ui_factory_,因此,類型為MessageLoop:TYPE_UI的消息循環(huán)對應(yīng)的消息泵為MessagePumpForUI。在Chromium中,消息循環(huán)類型為MessageLoop:TYPE_UI的線程稱為UI線程,也就是應(yīng)用程序的主線程。       2. 如果消息循環(huán)的類型為MessageLoop:TYPE_IO,那么對應(yīng)的消息泵為MessagePumpFo

66、rIO,即MessagePumpLibevent。在Chromium中,消息循環(huán)類型為MessageLoop:TYPE_IO的線程稱為IO線程,但是這里的IO不是讀寫文件的意思,而是執(zhí)行IPC的意思。       3. 如果消息循環(huán)的類型為MessageLoop:TYPE_JAVA,那么對應(yīng)的消息泵為MessagePumpForUI。在Chromium中,消息循環(huán)類型為MessageLoop:TYPE_JAVA的線程稱為JAVA線程,它們與UI線程一樣,在JAVA層具有自己的消息循環(huán)。       4. 其余類型的

67、消息循環(huán),對應(yīng)的消息泵為MessagePumpDefault。       總結(jié)來說,就是在Linux平臺上,涉及到的消息泵有MessagePumpForUI、MessagePumpForIO和MessagePumpDefault三種,各自有不同的用途,其中MessagePumpForUI適用于具有自己的消息循環(huán)的UI線程,MessagePumpLibevent適用于用來負(fù)責(zé)執(zhí)行IPC的IO線程,MessagePumpDefault適用于其它的一般線程。我們先從一般性出發(fā),分析MessagePumpDefault的實現(xiàn),后面再分析MessagePumpF

68、orUI和MessagePumpForIO的實現(xiàn)。       MessagePumpDefault類繼承于MessagePump類,它的定義如下所示:1. class MessagePumpDefault : public MessagePump   2.  public:  3.   MessagePumpDefault();  4.   virtual MessagePumpDef

69、ault();  5.   6.   / MessagePump methods:  7.   virtual void Run(Delegate* delegate) OVERRIDE;  8.   virtual void Quit() OVERRIDE;  9.   virtual void ScheduleWork() OVERRIDE;  10.   virtual void ScheduleDelayedWork(cons

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論