建立異步操作組件:隊(duì)列和線(xiàn)程
6.25.2008
Kevin Lynx
引言
在一個(gè)高效的系統(tǒng)中,我們經(jīng)常會(huì)將一些費(fèi)時(shí)的操作轉(zhuǎn)換為異步操作。例如往數(shù)據(jù)庫(kù)中寫(xiě)日志。如果數(shù)據(jù)庫(kù)
配置在網(wǎng)絡(luò)上,那么往數(shù)據(jù)庫(kù)中插入一些日志信息將非常慢(相對(duì)于程序其他部分)。
如何轉(zhuǎn)換為異步?
將類(lèi)似于以上過(guò)程轉(zhuǎn)換為異步操作,一個(gè)典型的做法是:建立一個(gè)單獨(dú)的數(shù)據(jù)庫(kù)日志線(xiàn)程,一個(gè)線(xiàn)程安全的
隊(duì)列。要寫(xiě)日志時(shí),只需要往隊(duì)列里放入數(shù)據(jù),數(shù)據(jù)庫(kù)日志線(xiàn)程則從這個(gè)隊(duì)列里取數(shù)據(jù)然后完成寫(xiě)操作。
大致的過(guò)程類(lèi)似于:




























將他們包裝起來(lái)
我們很有可能會(huì)在同一個(gè)系統(tǒng)中多次遇到類(lèi)似需要轉(zhuǎn)換為異步操作的地方,如果每一次都手動(dòng)去創(chuàng)建一個(gè)隊(duì)列和一
個(gè)線(xiàn)程,那將會(huì)多么乏味啊!懶惰的程序員喜歡重用各種代碼。所以,我自己覺(jué)得很有必要將這一切封裝起來(lái)。我
們只需要封裝這個(gè)隊(duì)列和創(chuàng)建線(xiàn)程的繁瑣細(xì)節(jié),讓?xiě)?yīng)用層全部專(zhuān)注于具體的邏輯處理:



















































我利用了已有的組件:線(xiàn)程安全的容器multi_list、包裝任意執(zhí)行體的functor、線(xiàn)程維護(hù)類(lèi)thread。那么,現(xiàn)在,
應(yīng)用層只需要定義隊(duì)列節(jié)點(diǎn)類(lèi)型,寫(xiě)應(yīng)用相關(guān)的回調(diào)函數(shù)(任意可被functor包裝的廣義函數(shù))。(見(jiàn)附件例子)
之所以為這個(gè)組件加上init和release,是因?yàn)橛行〇|西(例如COM)需要在線(xiàn)程啟動(dòng)時(shí)初始化,而在線(xiàn)程快結(jié)束時(shí)釋放,例如對(duì)于
使用COM的應(yīng)用來(lái)說(shuō),就需要在線(xiàn)程初始化時(shí)CoInitialize,結(jié)束時(shí)CoUninitialize。
閑說(shuō)下其他東西
在本文的附件代碼里,你可以獲取到functor、thread、multi_list這些東西,所以我有必要提一下。
關(guān)于functor,你可以參看<實(shí)現(xiàn)functor - 增強(qiáng)型的函數(shù)指針>,基本上可以看成增強(qiáng)版的C回調(diào)函數(shù);至于multi_list,基本上
是一個(gè)container adapter (套用下STL的概念),使用條件變量參與線(xiàn)程同步,據(jù)說(shuō)效率要比簡(jiǎn)單的互斥高點(diǎn);至于thread,我需要
特別說(shuō)下:
thread最為重要的就是為其附加了一個(gè)windows的消息隊(duì)列(只要調(diào)用PeekMessage之類(lèi)的函數(shù)該隊(duì)列就存在),本意是可以讓其他線(xiàn)
程傳送數(shù)據(jù)到該線(xiàn)程,但是目前只用于線(xiàn)程退出,即其他線(xiàn)程可以在任何時(shí)候要求該線(xiàn)程安全地退出(該線(xiàn)程沒(méi)有阻塞的情況下,
阻塞時(shí)獲取不到消息)。我不知道這個(gè)安全退出策略是否真的有必要存在,但是我討厭看到各種撇腳的退出方法(例如設(shè)置全局標(biāo)志
變量,增加額外的--沒(méi)封裝前---event對(duì)象之類(lèi))。
結(jié)束
不知道其他人是如何做這種異步轉(zhuǎn)換操作的,在這里我只是起個(gè)拋磚引玉的作用,歡迎大家提出意見(jiàn)。
例子下載
posted on 2008-06-25 15:47 Kevin Lynx 閱讀(5062) 評(píng)論(29) 編輯 收藏 引用 所屬分類(lèi): 通用編程