EOS插件繼承機(jī)制講解

EOS插件繼承機(jī)制講解

1镣奋、EOS的插件接口

class abstract_plugin {
      public:
         enum state {
            registered, ///< the plugin is constructed but doesn't do anything
            initialized, ///< the plugin has initialized any state required but is idle
            started, ///< the plugin is actively running
            stopped ///< the plugin is no longer running
         };

         virtual ~abstract_plugin(){}
         virtual state get_state()const = 0;
         virtual const std::string& name()const  = 0;
         virtual void set_program_options( options_description& cli, options_description& cfg ) = 0;
         virtual void initialize(const variables_map& options) = 0;
         virtual void startup() = 0;
         virtual void shutdown() = 0;
   };

從插件的基類中可以看出插件有4個(gè)狀態(tài)已注冊(cè)币呵、已初始化、運(yùn)行侨颈、停止余赢。其中
已注冊(cè)(registered): 表示插件對(duì)象已經(jīng)被實(shí)例化,但沒(méi)有做任何事情哈垢。
已初始化(initialized): 表示插件的參數(shù)已經(jīng)被初始化妻柒,可以隨時(shí)運(yùn)行
運(yùn)行(started): 表示插件已經(jīng)在運(yùn)行狀態(tài)
停止(stopped): 表示插件已經(jīng)停止運(yùn)行
插件的接口提供了所有插件對(duì)外提供的基本操作
get_state:獲取插件當(dāng)前的狀態(tài)
name:獲取插件名稱
set_program_options:設(shè)置插件所需要的參數(shù)
initialize:插件初始化
startup:插件運(yùn)行
shutdown:插件停止

2耘分、插件模板

EOS插件實(shí)現(xiàn)所用技術(shù)比較復(fù)雜举塔,代碼也比較晦澀。首先EOS插件有三個(gè)層次求泰,第一層是接口abstract_plugin央渣,為插件提供統(tǒng)一的訪問(wèn)接口;第二層是模板層plugin,根據(jù)插件類型去推演出插件自己的父類;第三層EOS插件根據(jù)自己的業(yè)務(wù)去實(shí)現(xiàn)具體的方法渴频。


image.png

EOS插件使用了C++的多態(tài)機(jī)制痹屹,父類只提供接口,不同的子類根據(jù)自己業(yè)務(wù)實(shí)現(xiàn)自己方法。其次EOS插件使用模板機(jī)制,根據(jù)不同的插件類去推演出自己的父類崭倘,EOS插件采用代理的設(shè)計(jì)模式完成實(shí)現(xiàn)業(yè)務(wù)方法與接口方法不同。

template<typename Impl>
   class plugin : public abstract_plugin {
      public:
         plugin():_name(boost::core::demangle(typeid(Impl).name())){}
         virtual ~plugin(){}

         virtual state get_state()const override         { return _state; }
         virtual const std::string& name()const override { return _name; }

         virtual void register_dependencies() {
            static_cast<Impl*>(this)->plugin_requires([&](auto& plug){});
         }

         virtual void initialize(const variables_map& options) override {
            if(_state == registered) {
               _state = initialized;
               static_cast<Impl*>(this)->plugin_requires([&](auto& plug){ plug.initialize(options); });
               static_cast<Impl*>(this)->plugin_initialize(options);
               //ilog( "initializing plugin ${name}", ("name",name()) );
               app().plugin_initialized(*this);
            }
            assert(_state == initialized); /// if initial state was not registered, final state cannot be initiaized
         }

         virtual void startup() override {
            if(_state == initialized) {
               _state = started;
               static_cast<Impl*>(this)->plugin_requires([&](auto& plug){ plug.startup(); });
               static_cast<Impl*>(this)->plugin_startup();
               app().plugin_started(*this);
            }
            assert(_state == started); // if initial state was not initialized, final state cannot be started
         }

         virtual void shutdown() override {
            if(_state == started) {
               _state = stopped;
               //ilog( "shutting down plugin ${name}", ("name",name()) );
               static_cast<Impl*>(this)->plugin_shutdown();
            }
         }

      protected:
         plugin(const string& name) : _name(name){}

      private:
         state _state = abstract_plugin::registered;
         std::string _name;
   };

EOS插件中比較難理解的是插件模板機(jī)制楼肪,插件用自己的類型傳入模板中去推演自己的父類,導(dǎo)致無(wú)法理解(自己怎么能夠繼承自己呢)惹悄。不理解的原因在于不明白模板的運(yùn)行是在編譯器春叫,只要提供與模板接口一樣就可以,第二、類的聲明和類的定義在編譯器的操作是不一樣的暂殖。類的聲明后就可以創(chuàng)建指針价匠,任何類型的指針都可以編譯器得到其所占空間的大小。而類的定義就需要確定類的實(shí)現(xiàn)具休是什么樣子呛每,編譯器才能在編譯期確定類對(duì)象的大小踩窖,才不使編譯器報(bào)錯(cuò)。

3晨横、舉個(gè)例子-chain_plugin模板實(shí)現(xiàn)

class plugin : public abstract_plugin {
public:
    plugin() :_name(boost::core::demangle(typeid(chain_plugin).name())) {}
    virtual ~plugin() {}

    virtual state get_state()const override { return _state; }
    virtual const std::string& name()const override { return _name; }

    virtual void register_dependencies() {
        static_cast<chain_plugin*>(this)->plugin_requires([&](auto& plug) {});
    }

    virtual void initialize(const variables_map& options) override {
        if (_state == registered) {
            _state = initialized;
            static_cast<chain_plugin*>(this)->plugin_requires([&](auto& plug) { plug.initialize(options); });
            static_cast<chain_plugin*>(this)->plugin_initialize(options);
            //ilog( "initializing plugin ${name}", ("name",name()) );
            app().plugin_initialized(*this);
        }
        assert(_state == initialized); /// if initial state was not registered, final state cannot be initiaized
    }

    virtual void startup() override {
        if (_state == initialized) {
            _state = started;
            static_cast<chain_plugin*>(this)->plugin_requires([&](auto& plug) { plug.startup(); });
            static_cast<chain_plugin*>(this)->plugin_startup();
            app().plugin_started(*this);
        }
        assert(_state == started); // if initial state was not initialized, final state cannot be started
    }

    virtual void shutdown() override {
        if (_state == started) {
            _state = stopped;
            //ilog( "shutting down plugin ${name}", ("name",name()) );
            static_cast<chain_plugin*>(this)->plugin_shutdown();
        }
    }

protected:
    plugin(const string& name) : _name(name) {}

private:
    state _state = abstract_plugin::registered;
    std::string _name;
};

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末洋腮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子手形,更是在濱河造成了極大的恐慌啥供,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件库糠,死亡現(xiàn)場(chǎng)離奇詭異伙狐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)瞬欧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門贷屎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人黍判,你說(shuō)我怎么就攤上這事「萆遥” “怎么了顷帖?”我有些...
    開封第一講書人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)渤滞。 經(jīng)常有香客問(wèn)我贬墩,道長(zhǎng),這世上最難降的妖魔是什么妄呕? 我笑而不...
    開封第一講書人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任陶舞,我火速辦了婚禮,結(jié)果婚禮上绪励,老公的妹妹穿的比我還像新娘肿孵。我一直安慰自己,他們只是感情好疏魏,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開白布停做。 她就那樣靜靜地躺著,像睡著了一般大莫。 火紅的嫁衣襯著肌膚如雪蛉腌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,874評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音烙丛,去河邊找鬼舅巷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛河咽,可吹牛的內(nèi)容都是我干的钠右。 我是一名探鬼主播,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼库北,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼爬舰!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起寒瓦,我...
    開封第一講書人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤情屹,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后杂腰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體垃你,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年喂很,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惜颇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡少辣,死狀恐怖凌摄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情漓帅,我是刑警寧澤锨亏,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站忙干,受9級(jí)特大地震影響器予,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捐迫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一乾翔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧施戴,春花似錦反浓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至懈玻,卻和暖如春巧婶,著一層夾襖步出監(jiān)牢的瞬間乾颁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來(lái)泰國(guó)打工艺栈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留英岭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓湿右,卻偏偏與公主長(zhǎng)得像诅妹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子毅人,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361