Webrtc 多線程模塊主要涉及 criticalsection、event、messagequeue、thread、messagehandler、physicalsocketserver 等文件. 注意 webrtc 最新的代碼將 base 目錄改為了 rtc_base。
Event
文件路徑 webrtc/base/event.h webrtc/base/event.c.
event.h/event.cc文件中在 namespace rtc 中, 只有class Event類。
該類主要實(shí)現(xiàn)了跨平臺(tái)的Win32 Event功能。Event類的各個(gè)成員函數(shù)與Win32 Event所提供的API幾乎一致。
在 Linux 系統(tǒng)中,WebRTC 使用了mutex和條件變量來(lái)實(shí)現(xiàn)Event的功能。首先,對(duì)Win 32 API和pthread API做一下類比:
- CreateEvent
pthread_mutex_init、pthread_cond_init這兩個(gè)函數(shù)用來(lái)創(chuàng)建pthread的mute和條件變量。
- CloseHandle
pthread_mutex_destroy、pthread_cond_destroy這兩個(gè)函數(shù)用來(lái)銷毀pthread的mute和條件變量。
- SetEvent
pthread_mutex_lock、pthread_mutex_unlock這兩個(gè)函數(shù)加鎖和解鎖mutex,
pthread_cond_broadcast函數(shù)用來(lái)解除所有等待在該條件變量上的線程的阻塞狀態(tài)。
- ResetEvent
pthrea_mutex_lock、pthread_mutex_unlock(已解釋)
- WaitForSingleObject
pthrea_mutex_lock、pthread_mutex_unlock(已解釋)。pthrea_cond_wait函數(shù)用來(lái)使線程阻塞在條件變量上。
下面將大致解釋一下 Event 類的實(shí)現(xiàn)原理:
Event的主要功能由條件變量實(shí)現(xiàn),mutex只是輔助條件變量起到鎖的作用。條件變量的 pthread_cond_wait 和pthread_cond_broadcast函數(shù)與Win32 Event的WaitForSingleObject和SetEvent基本類似。Event是否為signal狀態(tài)由布爾類型的成員變量event_status_控制。是否為manual reset的Event由布爾類型的成員變量is_manual_reset_控制。與Win32 Event不同的狀況主要體現(xiàn)在Event的manual reset控制上。
linux 系統(tǒng)下所有調(diào)用 Event::Wait 函數(shù)的線程會(huì)阻塞在pthread_cond_wait 函數(shù)上。當(dāng) Event::Set 函數(shù)被調(diào)用時(shí),pthread_cond_broadcast 函數(shù)會(huì)解除所有等待在 pthread_cond_wait 函數(shù)上的線程的阻塞狀態(tài)。這對(duì)于 manual reset 的 Win32 Event 來(lái)說(shuō)沒(méi)什么問(wèn)題,問(wèn)題出在 auto reset 的 Win32 Event 上。Auto reset 的 Win32 Event 每次只能解除一條等待在Event上的線程的阻塞狀態(tài),其他線程依然為阻塞狀態(tài)。這就需要mutex來(lái)配合實(shí)現(xiàn)了。
在這里要重點(diǎn)解釋一下 pthread_cond_wait 函數(shù)的第二個(gè)參數(shù) pthread_mutex_t *mutex。當(dāng)線程進(jìn)入pthread_cond_wait 函數(shù)時(shí)會(huì)解鎖 mutex,而在離開 pthread_cond_wait 時(shí)會(huì)重新加鎖 mutex??梢岳斫鉃椋?/p>
intpthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex)
{
pthread_mutex_unlock(mutex);
…
…
…
pthread_mutex_lock(mutex);
return0;
}
這是 Win32 沒(méi)有的行為,需要特別注意。
有了以上的機(jī)制后,模擬 auto rest的 Win32 Event 就沒(méi)問(wèn)題了。當(dāng)?shù)谝粭l線程獲得 mutex 鎖并離開pthread_cond_wait 函數(shù)時(shí),其他線程會(huì)依然被阻塞在 pthread_mutex_lock(mutex) 函數(shù)上,無(wú)法離開 pthread_cond_wait 函數(shù)。那條成功離開線程會(huì)馬上檢測(cè)當(dāng)前的 Event 是否為 manual reset 的,如果不是就馬上將 event_status_ 成員變量設(shè)置為 false,并解鎖 mutex。這時(shí)其他線程才能有機(jī)會(huì)離開pthread_cond_wait 函數(shù)。不過(guò)當(dāng)他們離開 pthread_cond_wait 后立即檢測(cè) event_status_ 成員變量,如果為 false 就重新調(diào)用 pthread_cond_wait 函數(shù)。這就完美實(shí)現(xiàn)了 Win32 Event 的 auto reset 的語(yǔ)義。
條件變量和 mutex 的配合是 Event 類的難點(diǎn)。如果讀者還是不能完全理解,請(qǐng)仔細(xì)閱讀以上 3 段的內(nèi)容(也可以上網(wǎng)查找 pthread_cond_wait 函數(shù)),并結(jié)合 event.cc 的源代碼反復(fù)揣摩,應(yīng)該可以很快理解的(畢竟代碼不多,而且也不是WebRTC中真正困難的部分)