??? 摘 要: 提出一種基于CAR構(gòu)件的用戶自定義事件" title="用戶自定義事件">用戶自定義事件機(jī)制。該機(jī)制是一種適用于嵌入式系統(tǒng)的、用戶自定義的、實(shí)現(xiàn)客戶與構(gòu)件間交互通信的計(jì)算機(jī)運(yùn)行環(huán)境的事件管理機(jī)制及裝置。該機(jī)制可自動(dòng)生成構(gòu)件,生成構(gòu)件具有升級(jí)獨(dú)立性、構(gòu)件互操作的簡(jiǎn)單快速性、接口重用性、構(gòu)件本地/遠(yuǎn)程透明化、編程語(yǔ)言無(wú)關(guān)性等特性。該機(jī)制屏蔽了客戶程序調(diào)用構(gòu)件對(duì)象過(guò)程中繁瑣的細(xì)節(jié),大大簡(jiǎn)化了客戶程序的實(shí)現(xiàn)。
?? ?關(guān)鍵詞: CAR構(gòu)件? 用戶自定義事件? 回調(diào)
?
??? 現(xiàn)有的構(gòu)件技術(shù)中客戶與構(gòu)件之間的通信過(guò)程多為單向;客戶創(chuàng)建構(gòu)件對(duì)象,然后客戶調(diào)用對(duì)象所提供的接口函數(shù),在這樣的交互過(guò)程中,客戶總是主動(dòng)的,而構(gòu)件對(duì)象則處于被動(dòng)狀態(tài)。對(duì)于一個(gè)全面的交互過(guò)程,這樣的單向通信往往不能滿足實(shí)際需要。
??? 微軟提供的可連接對(duì)象技術(shù)可實(shí)現(xiàn)構(gòu)件對(duì)客戶的調(diào)用。但該技術(shù)需要用戶去實(shí)現(xiàn)客戶程序與構(gòu)件對(duì)象的連接、事件的激發(fā)、接收器的編寫(xiě)等;而且只能以接口為單位注冊(cè),即不能為接口中每個(gè)成員函數(shù)分別注冊(cè)。另外,Windows應(yīng)用程序" title="應(yīng)用程序">應(yīng)用程序都必須有一個(gè)消息循環(huán)以處理消息隊(duì)列中Windows發(fā)送過(guò)來(lái)的消息。這樣每個(gè)應(yīng)用程序都有一個(gè)等待消息的線程,當(dāng)同時(shí)運(yùn)行的程序較多時(shí),占用系統(tǒng)資源比較大。
??? COM技術(shù)主要解決的問(wèn)題:不同來(lái)源的構(gòu)件實(shí)現(xiàn)互操作,構(gòu)件升級(jí)不影響其他構(gòu)件、獨(dú)立于編程語(yǔ)言,構(gòu)件在進(jìn)程內(nèi)、跨進(jìn)程甚至跨網(wǎng)絡(luò)運(yùn)行的透明度。但調(diào)用COM構(gòu)件對(duì)象的過(guò)程相當(dāng)繁瑣,不易操作。
??? 本文提出一種基于CAR構(gòu)件的用戶自定義事件機(jī)制, 該機(jī)制能夠?qū)崿F(xiàn)構(gòu)件端和客戶端" title="客戶端">客戶端的交互操作,跨平臺(tái)的構(gòu)件開(kāi)發(fā)、運(yùn)行環(huán)境和構(gòu)件庫(kù);其通過(guò)在操作系統(tǒng)上自動(dòng)生成中間件(代理構(gòu)件),提供構(gòu)件定位、調(diào)用、管理、中間件啟動(dòng)生成、構(gòu)件通信的進(jìn)程內(nèi)、跨進(jìn)程、跨網(wǎng)功能;并保證軟件互操作性、版本升級(jí)獨(dú)立性,具有運(yùn)行環(huán)境透明性、軟件協(xié)同開(kāi)發(fā)、軟件容錯(cuò)、可靠性、軟件復(fù)用、軟件升級(jí)的能力;具有構(gòu)件升級(jí)的獨(dú)立性、簡(jiǎn)單快速的構(gòu)件互操作、接口重用、本地/遠(yuǎn)程透明性、編程語(yǔ)言無(wú)關(guān)性的特性。該機(jī)制還可自動(dòng)實(shí)現(xiàn)標(biāo)準(zhǔn)接口類封裝層,屏蔽調(diào)用COM構(gòu)件對(duì)象過(guò)程的繁瑣細(xì)節(jié),從而簡(jiǎn)化客戶程序的實(shí)現(xiàn)。
??? 基于CAR構(gòu)件的用戶自定義事件機(jī)制,其技術(shù)實(shí)現(xiàn)包括設(shè)置事件管理方(EventManager)、事件發(fā)送方(EventDispatcher)兩個(gè)方面,兩者通過(guò)接口建立關(guān)聯(lián),其具體實(shí)施過(guò)程如圖1所示。該機(jī)制包括事件管理方——客戶端以及事件發(fā)送方——構(gòu)件端。其中連接點(diǎn)對(duì)象記錄了包含已注冊(cè)事件處理函數(shù)指針" title="函數(shù)指針">函數(shù)指針的接收器的接口指針。其實(shí)施過(guò)程包括:(1)注冊(cè)事件時(shí)保存IDispatch接口指針到連接點(diǎn)對(duì)象中;(2)注冊(cè)事件時(shí)把標(biāo)識(shí)該連接的dwCookie保存到EventHandler中;(3)激發(fā)事件時(shí),利用所保存的IDispatch接口指針調(diào)用其Invoke方法;(4)利用EventHandler所保存的dwCookie注銷事件。
?
?
??? 事件發(fā)送方組織不同參數(shù)構(gòu)成可連接對(duì)象事件,可連接對(duì)象事件具有接口,用戶自定義事件函數(shù)接口注冊(cè)。具體地,事件發(fā)送方在可連接對(duì)象事件內(nèi)設(shè)置事件標(biāo)識(shí),事件管理方創(chuàng)建接收器,將事件函數(shù)指針打包設(shè)置在事件管理方的接收器內(nèi)。接收器具有接口,通過(guò)注冊(cè)與可連接對(duì)象端連接,把可連接對(duì)象接口指針寫(xiě)入對(duì)應(yīng)的接收器內(nèi),并把包含事件處理函數(shù)指針的接收器所提供的接口指針設(shè)置在對(duì)應(yīng)的可連接對(duì)象內(nèi)。在條件符合時(shí),事件發(fā)送方激發(fā)事件,通過(guò)接收器接口,事件管理方回調(diào)" title="回調(diào)">回調(diào)函數(shù),并解包,執(zhí)行程序。事件管理方的接收器通過(guò)接口尋找事件標(biāo)識(shí),獲得該事件連接點(diǎn)對(duì)象的連接接口指針。其中事件處理函數(shù)參數(shù)中的第一個(gè)參數(shù)包括該事件接口的類的智能指針,用于標(biāo)識(shí)事件的發(fā)送者;第二個(gè)及其后的參數(shù)與構(gòu)件定義中的事件參數(shù)定義相同。接口包括普通接口和事件接口。其中普通接口為入接口,用于向客戶端提供服務(wù);事件接口為出接口,用于事件發(fā)生時(shí)回調(diào)客戶端所注冊(cè)的事件處理函數(shù)。對(duì)象通過(guò)事件接口與客戶進(jìn)行通信,而每一個(gè)接口有惟一的標(biāo)識(shí)符,構(gòu)件若需添加新的功能,必須先定義新的接口描述。當(dāng)激發(fā)事件時(shí),系統(tǒng)將按照處理函數(shù)的注冊(cè)順序調(diào)用各個(gè)事件處理函數(shù)。
??? 另外,對(duì)于已注冊(cè)事件,在不需要該事件時(shí)可進(jìn)行注銷事件處理,取消該可連接對(duì)象事件對(duì)應(yīng)的事件處理函數(shù)的連接。具體為可連接對(duì)象內(nèi)取消接收器接口指針,接收器對(duì)象被刪除(它所保存的事件處理函數(shù)指針和可連接對(duì)象指針也就沒(méi)了)。
??? 為實(shí)現(xiàn)一對(duì)多或多對(duì)一的情況,事件發(fā)送方內(nèi)設(shè)置一個(gè)以上可連接對(duì)象事件,每個(gè)事件對(duì)應(yīng)一個(gè)可連接對(duì)象;事件管理方內(nèi)可創(chuàng)建一個(gè)以上接收器。
??? 為將同一個(gè)事件處理函數(shù)注冊(cè)到不同對(duì)象的事件中,事件管理方接收器可與一個(gè)以上的可連接對(duì)象建立關(guān)系;事件發(fā)送方可連接對(duì)象可與一個(gè)以上事件管理方接收器建立關(guān)系??蓪⑼粋€(gè)事件對(duì)應(yīng)的多個(gè)事件處理函數(shù)注冊(cè),也就是一個(gè)事件可對(duì)應(yīng)多個(gè)事件處理函數(shù),用于分別執(zhí)行同一事件的不同注冊(cè)請(qǐng)求。
??? 為更好地管理可連接對(duì)象狀態(tài),可連接對(duì)象設(shè)置有重載處理,用于作為可連接對(duì)象處于可調(diào)用狀態(tài)的“開(kāi)或關(guān)”,管理可連接對(duì)象是否能夠被調(diào)用。
??? 在事件管理方第一次注冊(cè)某可連接對(duì)象時(shí),調(diào)用重載處理,也就是將可連接對(duì)象的調(diào)用狀態(tài)設(shè)置為“開(kāi)”;在事件管理方最后一次注銷可連接對(duì)象時(shí),調(diào)用重載處理,將可連接對(duì)象的調(diào)用狀態(tài)設(shè)置為“關(guān)”;沒(méi)有重載處理時(shí),執(zhí)行空操作。其中,可連接對(duì)象設(shè)置連接計(jì)數(shù)器,用于統(tǒng)計(jì)該可連接對(duì)象所建立連接的數(shù)量,每注冊(cè)一次,計(jì)數(shù)器加1;注銷一次,計(jì)數(shù)器減1。當(dāng)計(jì)數(shù)器數(shù)量為零時(shí),調(diào)用重載處理,將可連接對(duì)象的調(diào)用狀態(tài)設(shè)置為“關(guān)”。
??? 事件發(fā)送方內(nèi)設(shè)有接口指針容器,用于存儲(chǔ)可連接對(duì)象事件的描述信息以及接口指針。事件管理方內(nèi)的接收器注冊(cè)時(shí),通過(guò)接口指針容器尋找所需要的可連接對(duì)象事件。這樣具體的尋找方式為枚舉方式,逐一尋找事件標(biāo)識(shí),再連接指針將具體事件對(duì)應(yīng)的事件標(biāo)識(shí)傳入,獲得該事件連接點(diǎn)對(duì)象的連接接口指針。
??? 事件管理方設(shè)有與應(yīng)用程序連接的管理接口,用于接收應(yīng)用程序的調(diào)用,應(yīng)用程序通過(guò)該接口把事件處理函數(shù)的指針傳入事件管理方,事件管理方再去注冊(cè)該事件處理函數(shù)。因?yàn)槭录芾矸降淖?cè)、回調(diào)等代碼是自動(dòng)生成的,所以需要這個(gè)接口與應(yīng)用程序交互。
??? 事件發(fā)送方分發(fā)事件,事件管理方實(shí)現(xiàn)事件處理函數(shù)指針的保存、與原對(duì)象端的連接、回調(diào)函數(shù)的過(guò)程,兩者通過(guò)接口建立通信。其中建立通信應(yīng)包括用戶自定義的接口注冊(cè),具體步驟如圖2所示;根據(jù)注冊(cè)信息進(jìn)行事件激發(fā)的步驟,具體步驟如圖3所示;用于注銷事件處理函數(shù)的注銷步驟,具體步驟如圖4所示。
?
?
?
?
??? 如圖2所示,機(jī)制的客戶注冊(cè)事件處理函數(shù)將完成以下操作:
??? 步驟1:獲得事件管理方接口指針;
??? 步驟2:通過(guò)事件管理方接口創(chuàng)建接收器對(duì)象(EventHandler),保存事件處理函數(shù)的指針到該對(duì)象中;
??? 步驟3:利用源對(duì)象提供的連接點(diǎn)容器接口中的尋找連接指針函數(shù),找到與該事件對(duì)應(yīng)的連接點(diǎn)對(duì)象;
??? 步驟4:通過(guò)連接點(diǎn)對(duì)象提供的連接點(diǎn)指針接口中的Advise函數(shù),把事件接收器提供的管理方接口注冊(cè)到源對(duì)象端;
??? 步驟5:注冊(cè)時(shí)獲得標(biāo)識(shí)該連接的dwCookie,保存到接收器對(duì)象中。
??? 如圖3所示,構(gòu)件激發(fā)事件將完成以下操作:
??? 步驟1:枚舉與該事件對(duì)應(yīng)的連接點(diǎn)對(duì)象中的每個(gè)連接;
??? 步驟2:把事件的參數(shù)打包,并對(duì)每個(gè)連接調(diào)用其IDispatch接口中的Invoke函數(shù),以激發(fā)事件;
??? 步驟3:接收器對(duì)象把傳過(guò)來(lái)的Invoke的參數(shù)解包,并通過(guò)其保存的函數(shù)指針調(diào)用事件處理函數(shù)。
??? 如圖4所示,客戶注銷事件處理函數(shù)將完成以下操作:
??? 步驟1:通過(guò)事件處理函數(shù)的指針和事件的EID(Event ID 事件標(biāo)識(shí))找到對(duì)應(yīng)的接收器對(duì)象;
??? 步驟2:獲得接收器對(duì)象保存的標(biāo)識(shí)該連接的dwCookie;
??? 步驟3:利用源對(duì)象提供的IConnectionPointContainer接口中的FindConnectionPoint函數(shù),找到與該事件對(duì)應(yīng)的連接點(diǎn)對(duì)象;
??? 步驟4:通過(guò)連接點(diǎn)對(duì)象提供的IConnectionPoint接口中的Unadvise函數(shù),傳入dwCookie作參數(shù),注銷事件處理器提供的IDispatch接口;
??? 步驟5:釋放接收器對(duì)象。
??? 基于CAR構(gòu)件的用戶自定義事件機(jī)制實(shí)現(xiàn)了跨平臺(tái)的構(gòu)件開(kāi)發(fā)和運(yùn)行環(huán)境,該機(jī)制安全可靠,容錯(cuò)性好,并且小型高效。
該機(jī)制可運(yùn)用于嵌入式操作系統(tǒng)圖形系統(tǒng),操作系統(tǒng)只在有事件發(fā)生時(shí)回調(diào)用戶程序的事件處理函數(shù),不需要消息循環(huán)。用戶進(jìn)程可以沒(méi)有線程,操作系統(tǒng)在有事件發(fā)生時(shí),再啟動(dòng)線程執(zhí)行事件處理函數(shù),從而大大提高了操作系統(tǒng)的效率。Elastos的圖形系統(tǒng)即采用該機(jī)制。
??? 該機(jī)制還可用于嵌入式系統(tǒng)的驅(qū)動(dòng)程序。用戶程序或操作系統(tǒng)把事件處理函數(shù)注冊(cè)到用事件機(jī)制編寫(xiě)的設(shè)備驅(qū)動(dòng)程序構(gòu)件中。當(dāng)有硬件中斷時(shí),驅(qū)動(dòng)程序直接回調(diào)用戶程序或操作系統(tǒng)的事件處理函數(shù)。這樣就可以省去用線程定期查詢?cè)O(shè)備狀態(tài)的資源,也使程序編寫(xiě)變得更簡(jiǎn)單。
參考文獻(xiàn)
[1] Koretide.Elastos2.0Manual.http://www.koretide.com.cn/download/download.php?id=2,2006.
[2] PAN A.COM′s Principle and COM′s Application.The?Tsinghua Press,1999.
[3] ROGERSON D.Inside COM:Microsoft′s Component Object?Model.Microsoft Press,1999.
[4] ECKEL B.Thinking in C++(Second Edition).Prentice Hall,2002.
[5] Koretide.CAR′s Manual[M],2006.
[6] Koretide.Website[EB/OL].http://www.koretide.com.cn
[7] 陳榕,劉藝平.技術(shù)報(bào)告:基于構(gòu)件、中間件的因特網(wǎng)操作系統(tǒng)及跨操作系統(tǒng)的構(gòu)件、中間件運(yùn)行平臺(tái)(863課題技術(shù)鑒定文件),2003.