webrtc執行緒模型分析
目錄
概述
webrtc是一個跨平臺的實時音訊通訊技術,底層對不同平臺的執行緒介面進行了封裝,本文以windows平臺為例,簡要分析一下其封裝的執行緒類的特點和使用方法。在90版本的webrtc,封裝了三個執行緒相關的類,分別是modules/utility/source/ProcessThreadImpl、rtc_base/TaskQueue、rtc_base/Thread,這三個類建立執行緒都是通過呼叫CreateThread函式來實現,webrtc使用執行緒基本上都是通過這三個類來進行的。
個人感覺webrtc執行緒類的最大特點就是支援線上程間傳遞訊息處理函式,例如執行緒A想讓執行緒B乾點事情,那麼就向執行緒B傳送一個任務,這個任務裡面就包含了需要線上程B內執行的訊息處理函式,這個處理函式往往是lambda函式(當然也可以是全域性的函式)。這種設計最大好處的就是簡化了執行緒間進行通訊的方法,而這又是通過lambda函式的引數捕獲機制來實現的。舉個例子當我們需要向另一個執行緒傳遞多個變數的時候,往往都是通過設計多個引數或者定義一個結構體來實現,在傳遞資料前可能還需要一個個的進行變數賦值,但是通過lambda函式一切就變得簡單了,使用lambda函式的捕獲列表功能,目標執行緒處理訊息時需要什麼引數就可以直接在捕獲列表傳進去,甚至還可以把this指標也給傳進去,然後再在lambda函式內部呼叫類的成員函式。當然了,使用這種執行緒通訊模型需要十分清楚類的成員變數會在哪些執行緒被訪問、那些地方需要加鎖進行保護。
1.ProcessThreadImpl類
ProcessThread執行緒提供的函式是Start、Stop、WakeUp、RegisterModule、DeRegisterModule,可以向執行緒註冊多個處理模組,這些模組會線上程內被頻繁定時呼叫。ProcessThread主要用於建立需要迴圈處理訊息型別的執行緒,例如webrtc中就通過ProcessThread建立了PacerThread、ModuleProcessThread執行緒,其中PacerThread執行緒用於平滑網路資料包的傳送,而ModuleProcessThread用於處理rtp/rtcp訊息等。
2.TaskQueue類
TaskQueue主要提供了PostTask、PostDelayedTask介面。PostTask、PostDelayedTask可以將一個lambda函式作為引數傳入,在lambda函式內部也可以呼叫包含lambda函式的函式,這樣就看下來一個類的成員函式會被不同的執行緒所呼叫,如下面的函式:
void VideoStreamEncoder::OnLossNotification(
const VideoEncoder::LossNotification& loss_notification) {
if (!encoder_queue_.IsCurrent()) {
encoder_queue_.PostTask(
[this, loss_notification] { OnLossNotification(loss_notification); });
return;
}
RTC_DCHECK_RUN_ON(&encoder_queue_);
if (encoder_) {
encoder_->OnLossNotification(loss_notification);
}
}
TaskQueue使用了TaskQueueBase型別的例項。TaskQueue沒有實現不同執行緒間的同步呼叫,PostTask把訊息發到目標執行緒後會立即返回,不會等待目標執行緒處理完訊息,而rtc_base/Thread類的Send/Invoke函式就會等待。
3.Thread類
Thread裡面的Send/Invoke函式可以實現兩個不同執行緒之間的同步呼叫,例如A執行緒呼叫B執行緒的一個函式F,函式F是執行在B執行緒裡面,但是A執行緒在Invoke後會阻塞,等到B執行緒執行完F後A執行緒才繼續往下執行。實現原理是在Invoke內部呼叫了PostTask,在呼叫PostTask時傳入了一個lambda函式,這個lambda函式以引用方式捕獲了一個區域性變數ready,ready在目標執行緒執行完訊息處理函式後會被設定為true,而呼叫者執行緒在PostTask後迴圈等待ready,只有ready等於true後才結束迴圈,從而函式返回,這樣就實現了以同步方式呼叫另一個執行緒的函式。程式碼如下:
bool ready = false;
PostTask(
webrtc::ToQueuedTask([msg]() mutable { msg.phandler->OnMessage(&msg); },
[this, &ready, current_thread] {
CritScope cs(&crit_);
// 執行緒B執行
ready = true;
current_thread->socketserver()->WakeUp();
}));
bool waited = false;
crit_.Enter();
// 執行緒A執行
while (!ready) {
crit_.Leave();
current_thread->socketserver()->Wait(kForever, false);
waited = true;
crit_.Enter();
}
crit_.Leave();
Thread繼承自TaskQueueBase,Thread類主要提供了三個傳送訊息的函式Post、Send、Invoke,其中Post不會阻塞,而Send/Invoke會阻塞,Post/Send可以傳入訊息處理物件,而Invoke可以傳入訊息處理函式(lambda函式)。
全文完。
相關文章
- Dubbo RPC執行緒模型 原始碼分析RPC執行緒模型原始碼
- 執行緒模型執行緒模型
- Redis執行緒模型的原理分析蒼癘Redis執行緒模型
- Dubbo執行緒模型執行緒模型
- WPF執行緒模型執行緒模型
- redis執行緒模型Redis執行緒模型
- Dubbo的執行緒模型執行緒模型
- 程式和執行緒模型執行緒模型
- Redis的執行緒模型Redis執行緒模型
- 03.執行緒模型執行緒模型
- Netty原始碼分析之Reactor執行緒模型詳解Netty原始碼React執行緒模型
- 多執行緒之共享模型執行緒模型
- 執行緒池執行模型原始碼全解析執行緒模型原始碼
- Netty原始碼解析一——執行緒池模型之執行緒池NioEventLoopGroupNetty原始碼執行緒模型OOP
- 淺談Netty的執行緒模型Netty執行緒模型
- Java 執行緒記憶體模型Java執行緒記憶體模型
- (三)Redis 執行緒與IO模型Redis執行緒模型
- Redis之單執行緒 Reactor 模型Redis執行緒React模型
- Redis執行緒模型的前世今生Redis執行緒模型
- Node.js 的單執行緒事件驅動模型和內建的執行緒池模型Node.js執行緒事件模型
- Java多執行緒-程式執行堆疊分析Java執行緒
- 鴻蒙HarmonyOS實戰-Stage模型(執行緒模型)鴻蒙模型執行緒
- 多執行緒:原理分析整理執行緒
- 執行緒池原始碼分析執行緒原始碼
- 執行緒池之ScheduledThreadPoolExecutor執行緒池原始碼分析筆記執行緒thread原始碼筆記
- 執行緒池之ThreadPoolExecutor執行緒池原始碼分析筆記執行緒thread原始碼筆記
- 常用高併發網路執行緒模型設計及mongodb執行緒模型優化實踐執行緒模型MongoDB優化
- 多執行緒------執行緒與程式/執行緒排程/建立執行緒執行緒
- 深入學習redis 的執行緒模型Redis執行緒模型
- Java多執行緒記憶體模型Java執行緒記憶體模型
- Redis篇:單執行緒I/O模型Redis執行緒模型
- IO流中「執行緒」模型總結執行緒模型
- redis執行緒模型-學習小結Redis執行緒模型
- 伺服器模型——從單執行緒阻塞到多執行緒非阻塞(下)伺服器模型執行緒
- 伺服器模型——從單執行緒阻塞到多執行緒非阻塞(中)伺服器模型執行緒
- java多執行緒:執行緒間通訊——生產者消費者模型Java執行緒模型
- Tomcat執行緒模型 BIO模型原始碼與調優Tomcat執行緒模型原始碼
- iOS - 多執行緒分析之 DispatchQueue ⅠiOS執行緒