asgard項目已經(jīng)準(zhǔn)備了一段時間了,不過有些基本問題還需要考慮,也有一些是新發(fā)現(xiàn)的問題,以及自認(rèn)為比較好的解決辦法。
通過第2、第4條的仔細(xì)研究,已經(jīng)漸漸完善、明確了動態(tài)部分和靜態(tài)部分的關(guān)系,使得Method包裝類所完成的功能漸漸接近于一個函數(shù),而元信息則脫離具體的對象提升到全局(當(dāng)然還有些小問題沒有解決)。
1、參數(shù)名稱的問題。為了與SOAP等基于XML的協(xié)議兼容,必須開始就把參數(shù)名稱考慮在內(nèi)。
代碼經(jīng)過C++編譯器編譯以后,類型、變量名稱等都不復(fù)存在,唯一留下的是RTTI,顯然不能解決這個問題。所以只能在定義時把它加入。
BEGIN_SERVICE(TestService)
METHOD (void(in<int>, inout<string>, out<short>), method1, index, info, result);
END_SERVICE()
如果使用這種方式,index, info, result分別表示變量名字,在宏里面轉(zhuǎn)成字符串,看起來好像不太舒服,而且宏不支持參數(shù)個數(shù)變化。
BEGIN_SERVICE(TestService)
METHOD (void(in<int>, inout<string>, out<short>), method1, "(index, info, result)");
METHOD (int(in<int>, inout<string>), method2, "result(index, info)");
END_SERVICE()
這種可能稍稍舒服一點,在Method構(gòu)造函數(shù)或其它地方解析這個字符串,賦給各個參數(shù)。不過它的缺點是把編譯期應(yīng)該檢查出來的錯誤,延遲到運行期。如果在編譯期來做,又會使接口描述變得很復(fù)雜。
只是為了得到參數(shù)的名字,就要增加這么些麻煩。
c++0x只是一個庫的標(biāo)準(zhǔn),估計XTI也不會加入這些特性,而且c++0x很遙遠(yuǎn),所以暫時以這種方式來做。
暫時的解決辦法:
BEGIN_SERVICE(TestService)
METHOD (void(in<int>, inout<string>, out<short>), method1);
METHOD (int(in<int>, inout<string>), method2);
BEGIN_SERVICE_DEFINE(TestService)
METHOD_DEFINE (method1, "(index, info, result)", test_func);
METHOD_DEFINE (method2, "result(index, info)", &Test::test_method);
END_SERVICE_DEFINE()
END_SERVICE()
缺點是參數(shù)名稱中的錯誤,要延遲到運行期才能解決掉。
2、服務(wù)對象的大小。
如果客戶端要調(diào)用其中一個方法,生成一個TestService,則構(gòu)造成本太高,特別是一個服務(wù)中有多個方法的時候。一個服務(wù)容納了多個方法,而每個方法包含一個vector,以及各個參數(shù),這還沒考慮以后的擴展。
所以應(yīng)該修改調(diào)用方式,讓它只只需要生成調(diào)用所需的最小(少)對象。
這部分考慮還不成熟,暫時可以不管它,而以方法作為考慮的對象。
暫時想到的解決辦法:Method對象中的parameters容器和各個參數(shù),只在調(diào)用operator ()或async_call時,才真正生成出來。
這樣的話,Method對象中僅保存一個空的vector。
甚至這個vector也可以只是一個空指針,當(dāng)調(diào)用那幾個函數(shù)時,才生成一個。
暫時把這個過程命名為Create On Call(COC)。
COC的好處是顯而易見的,每個對象將只有8字節(jié),虛表指針+數(shù)據(jù)對象的指針,“數(shù)據(jù)對象”是實際調(diào)用時才生成的對象,包括參數(shù)vector容器、回調(diào)函數(shù)指針(可能由動態(tài)生成一個委托對象,以適應(yīng)廣泛類型的回調(diào)函數(shù))、對象鎖(防止干擾到前一個調(diào)用)。初始化成本接近0(虛函數(shù)表的初始化忽略不計)。
當(dāng)調(diào)用operator()或async_call時(以下簡稱CALL),將調(diào)用create_parameters虛函數(shù),動態(tài)生成一個vector。這樣,沒有調(diào)用到的Method不會象原來一樣影響到服務(wù)對象的構(gòu)建性能。
這就要求把Method的“元”信息提到全局,當(dāng)然更符合“元”的本意,原來由服務(wù)對象查詢Method以獲得“元”信息的過程,現(xiàn)在看來也是不合理的。
3、in模板可以省略。in是默認(rèn)的參數(shù)類型,返回值則默認(rèn)為out類型,這都是不需要明確指定的。
解決辦法:
這個問題是比較好解決的,在InOutTypeTraits模板類中,為各個偏特化版本定義一個type類型,InOutTypeTraits<T>::type的類型為in<T>,InOutTypes<in<T>>::type的類型為in<T>,InOutTypes<inout<T>>::type的類型為inout<T>,InOutTypes<o(jì)ut<T>>::type的類型為out<T>,InList模板類中進(jìn)行這種轉(zhuǎn)換。
4、異步調(diào)用隊列。在第2點中介紹道:
每個對象將只有8字節(jié),虛表指針+數(shù)據(jù)對象的指針,“數(shù)據(jù)對象”是實際調(diào)用時才生成的對象,包括參數(shù)vector容器、回調(diào)函數(shù)指針(可能由動態(tài)生成一個委托對象,以適應(yīng)廣泛類型的回調(diào)函數(shù))、對象鎖(防止干擾到前一個調(diào)用)。初始化成本接近0(虛函數(shù)表的初始化忽略不計)。
提到了對象鎖,這是一種低效的做法,可以使用異步調(diào)用隊列來替代它。
解決辦法:當(dāng)開始一個調(diào)用時,臨時生成上面所說的“數(shù)據(jù)對象”,交由一個調(diào)用隊列去完成。這時,由于Method對象基本不管理數(shù)據(jù),所以它成了一個空殼,作用是保存類型信息。
異步調(diào)用最好的實現(xiàn)就是整個系統(tǒng)都由異步調(diào)用構(gòu)成,而同步調(diào)用是由異步調(diào)用模擬而成。原本打算繞過這種方式,用最簡單的方法來做,現(xiàn)在好像又繞回來了。
上面這個做法,很好地把元信息和真實數(shù)據(jù)分開了,所以打算改成這種結(jié)構(gòu)。
5、全局元信息。
通過第4條的研究,已經(jīng)使得Method對象成為一個空殼,而“數(shù)據(jù)對象”在沒有調(diào)用時又不生成,使得自省結(jié)構(gòu)必須重新做。
考察了java等語言的自省,也打算把元信息的位置提升到全局,而每個Method對象將只保留一個全局元信息的指針,這樣應(yīng)該更自然。
(以后遇到的問題只更新到這個文檔中)