• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 94, comments - 250, trackbacks - 0, articles - 0
              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            核心子系統(tǒng)

            核心庫(kù)(Core namespace)實(shí)現(xiàn)了這些特性:

            • 一個(gè)實(shí)現(xiàn)了引用計(jì)數(shù)的RefCounted基類(lèi)
            • 一個(gè)運(yùn)行時(shí)類(lèi)型信息系統(tǒng)(RTTI)
            • 一個(gè)模板智能指針, 用于處理RefCounted對(duì)象的生命周期
            • 一個(gè)由類(lèi)名創(chuàng)建C++對(duì)象實(shí)例的工廠機(jī)制
            • 一個(gè)中央Server對(duì)象用于建立基本的Nebula3運(yùn)行環(huán)境

            對(duì)象模型

            Nebula3在C++對(duì)象模型的基礎(chǔ)之上實(shí)現(xiàn)了下面這些新特性:

            • 基于引用計(jì)數(shù)和智能指針的生命周期管理
            • 基于類(lèi)名或四字符編碼的對(duì)象創(chuàng)建
            • 一個(gè)運(yùn)行時(shí)類(lèi)型信息系統(tǒng)

            實(shí)現(xiàn)一個(gè)新的Nebula3類(lèi)

            當(dāng)實(shí)現(xiàn)一個(gè)新的類(lèi)時(shí)首先要考慮它是一個(gè)傳統(tǒng)的C++類(lèi)還是要從Core::RefCounted繼承. 以下幾點(diǎn)可以幫你找到答案:

            • 如果這個(gè)類(lèi)需要使用Nebula3的擴(kuò)展對(duì)象特性, 如引用計(jì)數(shù), RTTI等, 則它必須從Core::RefCounted繼承.
            • 如果這個(gè)類(lèi)是一個(gè)典型的小工具類(lèi), 如動(dòng)態(tài)數(shù)組, 數(shù)學(xué)向量, 或其它相似的東西, 那么它從Core::RefCounted 繼承也沒(méi)有什么意義.

            從Core::RefCounted類(lèi)繼承有一些限制:

            • RefCounted派生類(lèi)不應(yīng)該在棧上創(chuàng)建對(duì)象, 因?yàn)闂?duì)象的生命周期是由C++來(lái)管理的(他們會(huì)在離開(kāi)當(dāng)前上下文時(shí)被銷(xiāo)毀, 從而繞過(guò)了Nebula3的引用計(jì)數(shù)生命周期 管理)
            • RefCounted的派生類(lèi)只有一個(gè)默認(rèn)的構(gòu)造函數(shù).
            • RefCounted的派生類(lèi)必須有一個(gè)虛析構(gòu)函數(shù).
            • RefCounted的派生類(lèi)不能進(jìn)行拷貝, 因?yàn)檫@樣會(huì)造成引用計(jì)數(shù)機(jī)制混亂.

            要使用Nebula3的對(duì)象模型特性, 除了需要從Core::RefCounted繼承外, 還需要在頭文件新類(lèi)的聲明中進(jìn)行額外的標(biāo)注:

            一個(gè)標(biāo)準(zhǔn)的RefCounted派生類(lèi)一般這樣聲明:

            1: namespace MyNamespace

            2: {

            3: class MyClass : public Core::RefCounted

            4: {

            5: DeclareClass(MyClass);

            6: public:

            7: /// constructor

            8:     MyClass();

            9: /// destructor

            10: virtual ~MyClass();

            11: ...

            12: };

            13: RegisterClass(MyClass);

            注意DeclareClass()宏, 構(gòu)造函數(shù), 析構(gòu)函數(shù)還有類(lèi)外面的RegisterClass()宏. DeclareClass()宏加入了RTTI和工廠機(jī)制所需的最小代價(jià)的信息, 它隱藏了Nebula3的對(duì)象模型, 希望可以在不影響已有類(lèi)的基礎(chǔ)進(jìn)上進(jìn)行內(nèi)部機(jī)制的變更. RegisterClass()宏是可選的, 它把當(dāng)前類(lèi)在中央工廠進(jìn)行注冊(cè). 如果你知道這個(gè)類(lèi)永遠(yuǎn)不會(huì)由類(lèi)名或四字符編碼進(jìn)行創(chuàng)建, 這個(gè)宏可以省略.

            在這個(gè)類(lèi)的.cpp文件里需要包含Nebula3特有的信息:

            1: namespace MyNamespace

            2: {

            3: ImplementClass(MyNamespace::MyClass, 'MYCL', Core::RefCounted);

            4:

            5: }

            ImplementClass()宏注冊(cè)類(lèi)的RTTI機(jī)制, 第一個(gè)參數(shù)描述了類(lèi)的名字(注意命名空間必須包含). 第二個(gè)參數(shù)是類(lèi)的四字符編碼, 它必須是所有類(lèi)中唯一的(如果有重復(fù), 你會(huì)在啟動(dòng)程序時(shí)得到一個(gè)錯(cuò)誤提示). 第三個(gè)參數(shù)是父類(lèi)的名字, 用于RTTI系統(tǒng)去構(gòu)造類(lèi)的關(guān)系樹(shù).

            引用計(jì)數(shù)和智能指針

            Nebula3使用傳統(tǒng)的引用計(jì)數(shù)來(lái)管理對(duì)象的生命周期. 一個(gè)模板智能指針類(lèi)Ptr<>對(duì)程序員隱藏了引用計(jì)數(shù)的實(shí)現(xiàn)細(xì)節(jié). 一般來(lái)說(shuō), 應(yīng)該一直使用智能指針指向RefCounted的派生對(duì)象, 除非你能肯定在給出的代碼塊中這個(gè)對(duì)象的引用計(jì)數(shù)不會(huì)發(fā)生變化.

            智能指針相對(duì)于一般指針有很多好處:

            • 訪問(wèn)一個(gè)空指針會(huì)給你一個(gè)斷言警告而不是一個(gè)內(nèi)存錯(cuò)誤
            • 你不需要對(duì)引用計(jì)數(shù)的對(duì)象調(diào)用AddRef()或Release() (事實(shí)上如果你調(diào)了, 會(huì)了發(fā)生嚴(yán)重的錯(cuò)誤)
            • 智能指針可以在容器類(lèi)里良好地工作, 一個(gè)智能指針的數(shù)組會(huì)消除所有的一般指針需要的生命周期管理, 你永遠(yuǎn)不需要考慮去釋放指針?biāo)羔樀膶?duì)象, 數(shù)組包含的像是真正的C++對(duì)象一樣
            • 用智能指針不需要考慮指針的所屬, 不需要為誰(shuí)delete對(duì)象而煩惱

            智能指針也有一些缺點(diǎn):

            • 性能: 拷貝和賦值會(huì)引起對(duì)象的引用計(jì)數(shù)的變化, 解除引用會(huì)引起指針的斷言檢查. 這導(dǎo)致的性能消耗一般是可以忽略的, 但是你最好保證它不在內(nèi)部循環(huán)中發(fā)生.
            • 應(yīng)該銷(xiāo)毀的對(duì)象還存在: 因?yàn)橹悄苤羔樄芾淼膶?duì)象只有在最后一個(gè)引用放棄時(shí)才會(huì)銷(xiāo)毀, 這樣會(huì)使對(duì)象存在超過(guò)預(yù)訂的時(shí)間. 這經(jīng)常會(huì)導(dǎo)致一個(gè)BUG的產(chǎn)生. 不過(guò)引用計(jì)數(shù)泄露(程序退出時(shí)還仍然存在的對(duì)象)時(shí)Nebula3會(huì)提醒你.

            創(chuàng)建Nebula3對(duì)象

            從Core::RefCounted繼承的類(lèi)可以通過(guò)3種不同的方式進(jìn)行創(chuàng)建:

            直接通過(guò)靜態(tài)的Create方法:

            1: Ptr<MyClass> myObj = MyClass::Create();

            靜態(tài)的Create()方法是之前提到的DeclareClass()宏加入的, 相對(duì)于new操作符來(lái)說(shuō), 它并沒(méi)有多做什么. 注意正確使用智能指針來(lái)保存新建的對(duì)象.

            另一種創(chuàng)建方式是通過(guò)類(lèi)名:

            1: using namespace Core;

            2: Ptr<MyClass> myObj = (MyClass*)Factory::Instance()->Create("MyNamespace::MyClass");

            當(dāng)你在運(yùn)行時(shí)通過(guò)類(lèi)名來(lái)創(chuàng)建十分有用, 特別是對(duì)象的反序列化和腳本接口的使用. 注意類(lèi)型轉(zhuǎn)換是必須的, 因?yàn)楣S的Creat()方法返回的是RefCounted指針.

            由類(lèi)名創(chuàng)建的變種是根據(jù)四字符編碼進(jìn)行創(chuàng)建:

            1: using namespace Core;

            2: using namespace Util;

            3: Ptr<MyClass> myObj = (MyClass*) Factory::Instance()->Create(FourCC('MYCL'));

            這個(gè)方法看上去沒(méi)有那個(gè)直觀, 但是它比類(lèi)名創(chuàng)建快得多. 并且四字符編碼比類(lèi)名占用的空間更少, 這更利于對(duì)象寫(xiě)入二進(jìn)制流或從中讀取.

            運(yùn)行時(shí)類(lèi)型信息系統(tǒng)

            Nebula3的RTTI系統(tǒng)可以讓你在運(yùn)行時(shí)訪問(wèn)對(duì)象的類(lèi)型, 檢查一個(gè)對(duì)象是不是某個(gè)類(lèi)的實(shí)例, 或者某個(gè)派生類(lèi)的實(shí)例. 你也可以直接獲得一個(gè)對(duì)象的類(lèi)名和四字符編碼. 所有這些功能是由DeclareClass() 和 ImplementClass() 宏在背后實(shí)現(xiàn)的.

            這時(shí)有示例程序:

            1:     using namespace Util;

            2:     using namespace Core;

            3:

            4: // check whether an object is instance of a specific class

            5: if (myObj->IsInstanceOf(MyClass::RTTI))

            6: {

            7: // it's a MyClass object

            8: }

            9:

            10: // check whether an object is instance of a derived class

            11: if (myObj->IsA(RefCounted::RTTI))

            12: {

            13: // it's a RefCounted instance or some RefCounted-derived instance

            14: }

            15:

            16: // get the class name of my object, this yields "MyNamespace::MyClass"

            17: const String& className = myObj->GetClassName();

            18:

            19: // get the fourcc class identifier of my object, this yields 'MYCL'

            20: const FourCC& fourcc = myObj->GetClassFourCC();

            你也可以向中央工廠查詢一個(gè)類(lèi)是否已經(jīng)注冊(cè):

            1:     using namespace Core;

            2:

            3: // check if a class has been registered by class name

            4: if (Factory::Instance()->ClassExists("MyNamespace::MyClass"))

            5: {

            6: // yep, the class exists

            7: }

            8:

            9: // check if a class has been registered by class fourcc code

            10: if (Factory::Instance()->ClassExists(FourCC('MYCL')))

            11: {

            12: // yep, the class exists

            13: }

            Nebula3單件

            很多Nebula3的核心對(duì)象都是單件, 就是只存在一個(gè)實(shí)例, 并且所有其它對(duì)象都知道它.

            你可以通過(guò)靜態(tài)方法Instance()來(lái)訪問(wèn)單件, 它返回唯一實(shí)例的一個(gè)指針. 返回的指針保證是合法的. 如果在調(diào)用Instance()方法時(shí)對(duì)象實(shí)例不存在, 一個(gè)斷點(diǎn)會(huì)被拋出:

            1: // obtain a pointer to the Core::Server singleton

            2:     Ptr<Core::Server> coreServer = Core::Server::Instance();

            你也可以檢查單件是否存在:

            1: // does the Core::Server object exist?

            2: if (Core::Server::HasInstance())

            3: {

            4: // yep, the core server exists

            5: }

            Nebula3提供了一些輔助的宏來(lái)實(shí)現(xiàn)單件:

            1: // declare a singleton class

            2: class MySingletonClass : public Core::RefCounted

            3: {

            4: DeclareClass(MySingletonClass);

            5: DeclareSingleton(MySingletonClass);

            6: public:

            7: /// constructor

            8:     MySingletonClass();

            9: /// destructor

            10: virtual ~MySingletonClass();

            11: ...

            12: };

            13:

            14: // implement the singleton class

            15: ImplementClass(MyNamespace::MySingletonClass, 'MYSC', Core::RefCounted);

            16: ImplementSingleton(MyNamespace::MySingletonClass);

            17:

            18: //------------------------------------------------------------------------------

            19: /**

            20:     Implements the Singleton constructor.

            21: */

            22: MySingletonClass::MySingletonClass()

            23: {

            24: ConstructSingleton;

            25: }

            26:

            27: //------------------------------------------------------------------------------

            28: /**

            29:     Implements the Singleton destructor.

            30: */

            31: MySingletonClass:~MySingletonClass()

            32: {

            33: DestructSingleton;

            34: }

            DeclareSingleton()和ImplementSingleton()宏跟DeclareClass()和ImplementClass()宏差不多.它們?cè)陬?lèi)中添加了一些靜態(tài)方法(也就是Instance()和HasInstance()). 類(lèi)的構(gòu)造函數(shù)和析構(gòu)函數(shù)必須包含ConstructSingletonDestructSingleton宏. ContructSingleton初始化了一個(gè)私有的單件指針并保證沒(méi)有其它的類(lèi)實(shí)例存在(如果不是, 會(huì)拋出斷言). DestructSingleton讓私有的單件指針無(wú)效化.

            單件的訪問(wèn)默認(rèn)是只有本地線程. 這意味著在一個(gè)線程中創(chuàng)建的單件無(wú)法被其他線程訪問(wèn). 這使得”并行Nebula”大大簡(jiǎn)化了多線程編程. “并行Nebula”的基本思想是, 一個(gè)典型的Nebula3應(yīng)用程序包含一些”Fat線程”, 每一個(gè)Fat線程都是運(yùn)行在一個(gè)單獨(dú)的CPU核心上. Fat線程可以用于實(shí)現(xiàn)異步IO, 渲染, 物理等等. 每一個(gè)Fat線程都初始化了它們自己的Nebula3運(yùn)行環(huán)境, 它們執(zhí)行特性任務(wù)所需的最少依賴(lài). 這基本上消除了大部分Nebula3代碼的同步問(wèn)題, 并且把線程相關(guān)的代碼集中到一個(gè)明確定義的代碼區(qū)域中. “并行Nebula”的另一個(gè)好處就是, 程序員在多線程環(huán)境中編程時(shí)不需要關(guān)心太多. 大多數(shù)Nebula3代碼看起來(lái)就像單線程代碼一樣, 但是它們卻運(yùn)行在各自的Fat線程中.

            性能與內(nèi)存占用的考慮

            Nebula3核心層的一個(gè)設(shè)計(jì)目標(biāo)就是減少底層代碼的內(nèi)存占用, 來(lái)更好的適應(yīng)微型平臺(tái), 像手持設(shè)備. 這里有一些已經(jīng)完成的目標(biāo):

            • RefCounted 類(lèi)在每個(gè)實(shí)例中只增加了4byte用于引用計(jì)數(shù).
            • RTTI機(jī)制在開(kāi)頭增加了30 到 60 byte, 但是這是對(duì)于每個(gè)類(lèi)來(lái)說(shuō)的, 而是不是每個(gè)實(shí)例.
            • 一個(gè)智能指針僅僅4 byte, 就像普通指針一樣.
            • 一些監(jiān)控結(jié)構(gòu)只會(huì)在debug模型下創(chuàng)建, 特別是用來(lái)檢測(cè)引擎計(jì)數(shù)泄露的RefCountedList.

            這里一些用三種不種的創(chuàng)建方法創(chuàng)建一百萬(wàn)個(gè)RefCounted 對(duì)象所需的時(shí)間信息. 這些時(shí)間信息是在臺(tái)Intel Pentium 800 MHz的筆記本上得出的.  

            • Create(): 0.29 seconds
            • FourCC: 0.65 seconds
            • 類(lèi)名: 1.45 seconds

            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            精品久久亚洲中文无码| 日韩精品久久久久久久电影| 一本久久a久久精品vr综合| 久久综合国产乱子伦精品免费| 伊人久久无码中文字幕| 久久精品人人做人人爽97| 久久亚洲欧洲国产综合| 色综合久久久久综合体桃花网| 久久精品无码一区二区三区日韩 | 日韩乱码人妻无码中文字幕久久| 久久精品午夜一区二区福利| 国产日韩久久久精品影院首页| 久久久久久久久久久| 狠狠色噜噜狠狠狠狠狠色综合久久| 中文字幕无码久久精品青草| AAA级久久久精品无码区| 久久无码AV中文出轨人妻| 久久精品成人免费网站| 久久久国产视频| 久久人人爽人人精品视频| 久久精品九九亚洲精品天堂| 777午夜精品久久av蜜臀| 国产福利电影一区二区三区,免费久久久久久久精 | 蜜桃麻豆www久久国产精品| 久久99久久99精品免视看动漫| 日产精品久久久久久久| 久久99久久无码毛片一区二区| 99久久国产综合精品网成人影院| 免费国产99久久久香蕉| 婷婷综合久久狠狠色99h| 日韩AV无码久久一区二区| 日韩久久久久中文字幕人妻| 亚洲?V乱码久久精品蜜桃| 精品人妻伦九区久久AAA片69| 国产国产成人精品久久| 欧美亚洲另类久久综合| 久久精品国产只有精品2020| 国产精品久久久久久吹潮| 久久精品国产精品亚洲精品| 国产美女久久久| 久久本道久久综合伊人|