Live555 源代碼分析(一)

版本說(shuō)明

本文分析基于2019-12-30的版本稚配。(Live555沒(méi)有版本管理?)

1 Hash容器

1.1 HashTable

HashTable 定義了Hash表的接口淆攻。

  • 成員函數(shù) Add()、Remove() 和 Lookup() 分別用于添加、刪除和查找元素臭猜。

1.2 HashTable

BasicHashTable實(shí)現(xiàn)了HashTable接口。這是hash表的一個(gè)標(biāo)準(zhǔn)實(shí)現(xiàn)押蚤。

  • 成員fBuckets[]指向一個(gè)TableEntry*的數(shù)組蔑歌。其中每個(gè)元素指向一個(gè)TableEntry鏈表。TableEntry包括一個(gè)(key揽碘,value)對(duì)次屠。
  • 成員函數(shù) hashIndexFromKey()計(jì)算key的HASH值。它將Key值進(jìn)行若干變換雳刺,然后限縮在數(shù)組fBuckets的索引范圍內(nèi)劫灶。
  • 成員函數(shù)keyMatches()用于比較兩個(gè)key值是否相同。
  • insertNewEntry()向Hash表添加新元素掖桦。
    • 它調(diào)用hashIndexFromKey()計(jì)算在數(shù)組fBucket中的索引浑此,然后創(chuàng)建新的TableEntry實(shí)例,并掛接到該索引位置上的TableEntry鏈表滞详。
  • TableEntry的key值一般有兩種類(lèi)型:string和unsigned凛俱。兩種類(lèi)型計(jì)算HASH值的方法不同紊馏。
  • 如果Hash表中的TableEntry實(shí)例數(shù)超過(guò)指定的閾值,則調(diào)用rebuild()重建Hash表蒲犬,將成員fBuckets[]加長(zhǎng)朱监。這樣做的目的是保證Hash表的效率。

2 任務(wù)調(diào)度

2.1 TaskScheduler

TaskScheduler定義任務(wù)調(diào)度器接口原叮。

TaskScheduler接口涵蓋三種任務(wù):Socket監(jiān)聽(tīng)赫编、延時(shí)任務(wù)、和事件通知任務(wù)奋隶。后面依次說(shuō)明這三種任務(wù)擂送。

  • 成員函數(shù)setBackgroundHandling()創(chuàng)建Socket監(jiān)聽(tīng)任務(wù)。
  • 成員函數(shù)createEventTrigger()創(chuàng)建事件通知任務(wù)唯欣,triggerEvent()觸發(fā)任務(wù)嘹吨。
  • 成員函數(shù)scheduleDelayedTask()創(chuàng)建延時(shí)任務(wù)。
  • 成員函數(shù)doEventLoop()處理任務(wù)境氢。

2.2 HandlerDescritor蟀拷、HandlerSet - Socket監(jiān)聽(tīng)任務(wù)

HandlerDescriptor保存socket、以及與socket關(guān)聯(lián)的處理函數(shù)萍聊。

  • 成員socketNum是socket的值
  • 成員conditionSet是fd_set值的組合
  • handlerProc是指定的處理函數(shù)问芬,clientData是handlerProc的參數(shù)。

這些成員分別指定應(yīng)該監(jiān)控Socket上的什么事件(可讀寿桨、可寫(xiě)此衅、異常),事件發(fā)生時(shí)應(yīng)該調(diào)用什么函數(shù)處理它亭螟。

HandlerSet是HandlerDescriptor的集合挡鞍。

如下圖,HandlerSet的成員fHandlers保存一個(gè)HandlerDescriptor雙向列表媒佣。

對(duì)于HandlerDescriptor匕累,

  • 成員fPrevHandler和fNextHandler用于鏈接雙向鏈表陵刹。

對(duì)于HandlerSet默伍,

  • 成員函數(shù)assignHandler()設(shè)置Socket的處理函數(shù)。創(chuàng)建新的HandlerDescriptor實(shí)例衰琐,或者更新已有的實(shí)例也糊。創(chuàng)建HandlerDescriptor實(shí)例時(shí),將它鏈接在雙向鏈表的尾部羡宙。
  • 成員函數(shù)clearHandler()清除Socket的處理函數(shù)狸剃。在HandlerDescriptor的析構(gòu)函數(shù)中,把它自身從雙向鏈表中移除狗热。
  • 成員函數(shù)lookupHandler()查找Socket的處理函數(shù)钞馁。

HanderIterator基于HandlerDescriptor雙向鏈表虑省。

  • 調(diào)用它的成員函數(shù)next(),可以遍歷HandlerDescriptor鏈表僧凰。

2.3 AlarmHandler - 延時(shí)任務(wù)

DelayQueueEntry保存延時(shí)任務(wù)探颈,而DelayQueue保存一個(gè)DelayQueueEntry雙向鏈表。

對(duì)于DelayQueueEntry训措,

  • 成員fDeltaTimeRemaining保存延時(shí)的時(shí)長(zhǎng)伪节,這是一個(gè)相對(duì)值。
  • 成員fPrev和fNext 讓DelayQueueEntry的多個(gè)實(shí)例能鏈成一個(gè)雙向列表绩鸣。
  • 虛擬成員函數(shù)handleTimeout()是延時(shí)到達(dá)時(shí)執(zhí)行的函數(shù)怀大。DelayQueueEntry的派生類(lèi)可以定制自己的實(shí)現(xiàn)。

DelayQueue是一個(gè)DelayQueueEntry容器呀闻。

  • 它從DelayQueueEntry派生化借。這樣的設(shè)計(jì)看起來(lái)只是為了不需要為起始節(jié)點(diǎn)加一個(gè)DelayQueryEntry成員。(讓人迷惑的設(shè)計(jì)W苤椤)
  • 成員函數(shù)addEntry()屏鳍、updateEntry()、和removeEntry()分別用于增加局服、更新和移除元素钓瞭。

AlarmHandler是DelayQueueEntry的派生類(lèi),實(shí)現(xiàn)了虛擬成員函數(shù)handleTimeout()淫奔。

  • 成員fProc是處理函數(shù)山涡,由handleTimeout()調(diào)用。成員fClientData是fProc的參數(shù)唆迁。兩者在AlarmHandler的構(gòu)造函數(shù)中作為參數(shù)指定鸭丛。

在DelayQueueEntry雙向鏈表中,元素的延時(shí)fDeltaTimeRemaining是相對(duì)的唐责,是前一個(gè)元素的相對(duì)值鳞溉。

如下圖中,有4個(gè)元素鼠哥,它們的fDeltaTimeRemaining值分別是4熟菲、4、3和2朴恳,那么第一個(gè)元素的實(shí)際延時(shí)是最近的抄罕,是4,其他元素的實(shí)際延時(shí)依次累加于颖,分別是8呆贿、11和13。

DelayQueueEntry和DelayQueue用Timeval度量時(shí)間森渐。Timeval的派生類(lèi)DelayInterval和_EventTime做入,是對(duì)Timeval的簡(jiǎn)單包裝冒晰。

2.4 事件通知任務(wù)

沒(méi)有定義專(zhuān)門(mén)的類(lèi)處理事件通知任務(wù)。BasicTaskScheduler0類(lèi)直接處理這類(lèi)任務(wù)竟块。

2.5 BasicTaskScheduler0旧巾、BasicTaskScheduler

BasicTaskSchduler0實(shí)現(xiàn)了TaskScheduler接口箭窜,實(shí)現(xiàn)延時(shí)任務(wù)和事件監(jiān)聽(tīng)任務(wù)芹橡。

BasicTaskScheduler派生自BasicTaskScheduler0打厘,進(jìn)一步實(shí)現(xiàn)socket監(jiān)聽(tīng)任務(wù)。

對(duì)于BasicTaskSchduler0秫逝,

  • 實(shí)現(xiàn)shceduleDelayedTask()創(chuàng)建延時(shí)任務(wù)恕出。成員fDelayQueue保存一組延時(shí)任務(wù)。
  • 實(shí)現(xiàn)createEventTrigger()和triggerEvent()违帆,創(chuàng)建浙巫、觸發(fā)事件通知任務(wù)。成員fTriggerEventHandlers[]保存一組事件通知任務(wù)刷后。
  • BasicTaskScheduler0定義了新接口的畴,也就是新的虛擬函數(shù)SingleStep()。它實(shí)現(xiàn)了虛擬函數(shù)doEventLoop()尝胆。在里面丧裁,它在循環(huán)中調(diào)用singleStep()。

對(duì)于BasicTaskScheduler含衔,

  • 實(shí)現(xiàn)setBackgroundHandling()創(chuàng)建Socket監(jiān)聽(tīng)任務(wù)煎娇。BasicTaskScheduler0的成員fHandlers保存socket處理函數(shù)。(為什么不是BasicTaskSchduler的成員贪染?)
  • 實(shí)現(xiàn)BasicTaskScheduler0定義的接口SingleStep()缓呛。

在BasicTaskScheduler::SingleStep()中,

  • 調(diào)用select()杭隙,監(jiān)聽(tīng)HandlerSet中保存的socket的可讀哟绊、可寫(xiě)和異常信號(hào)。如果有信號(hào)痰憎,則調(diào)用指定HandlerSet實(shí)例中指定的處理函數(shù)TaskScheduler::BackgroundHandleProc()處理票髓。
  • 檢查fTriggerEventHandlers[]中的任務(wù)是否為觸發(fā)狀態(tài),如果是信殊,則調(diào)用指定處理函數(shù)TaskFunc()進(jìn)行處理炬称。
  • 調(diào)用DelayQueue::handleAlarm()汁果,檢查成員fDelayQueue中延時(shí)任務(wù)是否到達(dá)涡拘,如果是,調(diào)用處理函數(shù)TaskFunc()進(jìn)行處理据德。

3 程序上下文

3.1 UsageEnvironment

UsageEnvironment定義了一個(gè)輸出打印消息的接口鳄乏。

  • 成員函數(shù)setResultMsg()將打印消息保存起來(lái)跷车,getResultMsg()獲得保存的打印信息, reportBackgroundError()輸出保存的打印信息橱野。
  • operator <<() 一系列成員函數(shù)朽缴,輸出指定格式的數(shù)據(jù)。

BasicUsageEnvironment0實(shí)現(xiàn)了這個(gè)接口的setResultMsg()水援、getResultMsg()和reportBackgroundError()密强。

  • 成員fResultMsgBuffer[]保存打印消息。
  • reportBackgroundError()向stderr輸出打印消息蜗元。

BasicUsageEnvironment進(jìn)一步實(shí)現(xiàn)了這個(gè)接口的operator<<()系列函數(shù)或渤。

  • 這些函數(shù)向stderr輸出打印消息。

UsageEnvironment還是整個(gè)程序運(yùn)行的上下文奕扣。

  • 成員fScheduler引用全局唯一的TaskScheduler實(shí)例
  • 成員liveMediaPriv引用全局唯一的_Tables實(shí)例薪鹦,保存了兩個(gè)全局表。
  • 成員groupsockPriv實(shí)際上是_groupsockPriv實(shí)例惯豆,保存幾個(gè)組播全局變量池磁,其中reuseFlag是綁定Socket時(shí)是否重用地址。

應(yīng)用程序只創(chuàng)建一個(gè)UsageEnvironment實(shí)例楷兽。

3.2 _Tables - 全局容器

_Tables保存幾個(gè)hash表地熄。

  • _Tables是singleton模式,調(diào)用getOurTables()可以得到唯一的實(shí)例芯杀。
  • 成員mediaTable是其中一個(gè)Hash表离斩,它是MediumLookupTable的實(shí)例。

3.3 Medium瘪匿、MediaLookupTable

Medium給它的派生類(lèi)的實(shí)例保存一個(gè)名字跛梗。

  • 成員fMediumName[]保存這個(gè)名字。這個(gè)名字調(diào)用MediaLookupTable::generateNewName()得到棋弥。
  • Medium還引用唯一的UsageEnvironment實(shí)例核偿。

MediumLookupTable保存一個(gè)Medium集合。這個(gè)集合保存在成員fTable中顽染,這是一個(gè)HashTable實(shí)例漾岳。

  • addNew()、lookup()和remove()分別向hashtable加入粉寞、查找和刪除Medium實(shí)例尼荆。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市唧垦,隨后出現(xiàn)的幾起案子捅儒,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巧还,死亡現(xiàn)場(chǎng)離奇詭異鞭莽,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)麸祷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)澎怒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人阶牍,你說(shuō)我怎么就攤上這事喷面。” “怎么了走孽?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵乖酬,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我融求,道長(zhǎng)咬像,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任生宛,我火速辦了婚禮县昂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘陷舅。我一直安慰自己倒彰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布莱睁。 她就那樣靜靜地躺著待讳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪仰剿。 梳的紋絲不亂的頭發(fā)上创淡,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音南吮,去河邊找鬼琳彩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛部凑,可吹牛的內(nèi)容都是我干的露乏。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼涂邀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瘟仿!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起比勉,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤劳较,失蹤者是張志新(化名)和其女友劉穎驹止,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體兴想,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年赡勘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嫂便。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡闸与,死狀恐怖毙替,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情践樱,我是刑警寧澤厂画,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站拷邢,受9級(jí)特大地震影響袱院,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瞭稼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一忽洛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧环肘,春花似錦欲虚、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至腌零,卻和暖如春梯找,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背益涧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工初肉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人饰躲。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓牙咏,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親嘹裂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子妄壶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348