EOS插件通信機(jī)制

在上一篇 EOS應(yīng)用程序框架appbase已經(jīng)提到appbase給插件提供了插件之間的通信接口channel和method张抄, 使插件的之間的通信耦合性更加低局扶,一般我們把method看成是函數(shù)調(diào)用接口一般為1對(duì)1,channel為廣播一般有多個(gè)收聽者兰英,不管是method還是channel它們的實(shí)現(xiàn)都是基于boost::signals2::signal(類似QT中的信號(hào)槽)

接口的注冊(cè)

接口的注冊(cè)其實(shí)就是定義一個(gè)method或者channel接口說(shuō)明類型,說(shuō)明調(diào)用的參數(shù)跟返回值,然后任何插件可以實(shí)現(xiàn)該接口并使用厌蔽,eos中chain注冊(cè)的接口:

namespace eosio { namespace chain { namespace plugin_interface {
   using namespace eosio::chain;
   using namespace appbase;

   template<typename T>
   using next_function = std::function<void(const fc::static_variant<fc::exception_ptr, T>&)>;

   struct chain_plugin_interface;

   namespace channels {
      using pre_accepted_block     = channel_decl<struct pre_accepted_block_tag,    signed_block_ptr>;
      using rejected_block         = channel_decl<struct rejected_block_tag,        signed_block_ptr>;
      using accepted_block_header  = channel_decl<struct accepted_block_header_tag, block_state_ptr>;
      using accepted_block         = channel_decl<struct accepted_block_tag,        block_state_ptr>;
      using irreversible_block     = channel_decl<struct irreversible_block_tag,    block_state_ptr>;
      using accepted_transaction   = channel_decl<struct accepted_transaction_tag,  transaction_metadata_ptr>;
      using applied_transaction    = channel_decl<struct applied_transaction_tag,   transaction_trace_ptr>;
      using accepted_confirmation  = channel_decl<struct accepted_confirmation_tag, header_confirmation>;

   }

   namespace methods {
      using get_block_by_number    = method_decl<chain_plugin_interface, signed_block_ptr(uint32_t block_num)>;
      using get_block_by_id        = method_decl<chain_plugin_interface, signed_block_ptr(const block_id_type& block_id)>;
      using get_head_block_id      = method_decl<chain_plugin_interface, block_id_type ()>;
      using get_lib_block_id       = method_decl<chain_plugin_interface, block_id_type ()>;

      using get_last_irreversible_block_number = method_decl<chain_plugin_interface, uint32_t ()>;
   }

   namespace incoming {
      namespace channels {
         using block                 = channel_decl<struct block_tag, signed_block_ptr>;
         using transaction           = channel_decl<struct transaction_tag, packed_transaction_ptr>;
      }

      namespace methods {
         // synchronously push a block/trx to a single provider
         using block_sync            = method_decl<chain_plugin_interface, void(const signed_block_ptr&), first_provider_policy>;
         using transaction_async     = method_decl<chain_plugin_interface, void(const packed_transaction_ptr&, bool, next_function<transaction_trace_ptr>), first_provider_policy>;
      }
   }

   namespace compat {
      namespace channels {
         using transaction_ack       = channel_decl<struct accepted_transaction_tag, std::pair<fc::exception_ptr, packed_transaction_ptr>>;
      }
   }
} } }

1)channel接口using accepted_block_header = channel_decl<struct accepted_block_header_tag, block_state_ptr>; 這里就定義了一個(gè)channel類型的說(shuō)明接口channel_decl<>,其中第一個(gè)類型accepted_block_header_tag這個(gè)我們可以不用管因?yàn)闆](méi)什么用摔癣,第二個(gè)類型block_state_ptr表示該channel接口的參數(shù)為block_state_ptr奴饮,因?yàn)閏hannel沒(méi)有返回值所以這里不需要定義返回值
2)method接口using transaction_async = method_decl<chain_plugin_interface, void(const packed_transaction_ptr&, bool, next_function<transaction_trace_ptr>), first_provider_policy>; 這里就定義了一個(gè)method類型的說(shuō)明接口method_decl<>, 這是一個(gè)處理http接收到的trx的一個(gè)異步方法择浊,其中第一個(gè)類型chain_plugin_interface這個(gè)我們可以不用管因?yàn)闆](méi)什么用拐云,第二個(gè)參數(shù)void(const packed_transaction_ptr&, bool, next_function<transaction_trace_ptr>), first_provider_policy>是一個(gè)接口參數(shù)跟返回類型的定義,該接口的返回類型為void近她,參數(shù)為一共有3個(gè)

接口的使用

接口注冊(cè)完成之后可以通過(guò)app().get_method<...>()叉瘩,app().get_channel<...>()來(lái)獲取接口對(duì)象,例如get_method:

template<typename MethodDecl>
auto get_method() -> std::enable_if_t<is_method_decl<MethodDecl>::value, typename MethodDecl::method_type&>
{
     using method_type = typename MethodDecl::method_type;
     auto key = std::type_index(typeid(MethodDecl));
     auto itr = methods.find(key);
     if(itr != methods.end()) {
         return *method_type::get_method(itr->second);
     } else {
         methods.emplace(std::make_pair(key, method_type::make_unique()));
         return  *method_type::get_method(methods.at(key));
    }
}

上述get_method()如果該接口類型已經(jīng)存在直接返回反之則創(chuàng)建粘捎,所以具體的某種類型的接口只會(huì)被創(chuàng)建一次后面返回的都是同一個(gè)接口對(duì)象薇缅,返回類型 std::enable_if_t<is_method_decl<MethodDecl>::value, typename MethodDecl::method_type&>表示如果MethodDecl該接口類型已經(jīng)注冊(cè)則返回MethodDecl::method_type類型對(duì)象危彩,MethodDecl::method_type定義

template< typename Tag, typename FunctionSig, template <typename> class DispatchPolicy = first_success_policy>
   struct method_decl {
      using method_type = method<FunctionSig, DispatchPolicy<FunctionSig>>;
      using tag_type = Tag;
   };

獲取接口對(duì)象

using eosio::chain::plugin_interface::incoming::methods
auto transaction_async_method = app().get_method<transaction_async>();

1)接口的調(diào)用方
上述獲取到接口對(duì)象之后直接調(diào)用

transaction_async_method (pretty_input, true, [this, next](const fc::static_variant<fc::exception_ptr, transaction_trace_ptr>& result) -> void{
         ...
      });

2)接口的被調(diào)用方(接口的實(shí)現(xiàn))
如果沒(méi)有被調(diào)用方,調(diào)用方調(diào)用接口之后會(huì)直接返回泳桦,接口的被調(diào)用方可以通過(guò)register_provider實(shí)現(xiàn)接口

   transaction_async_method.register_provider([this](const packed_transaction_ptr& trx, bool persist_until_expired, next_function<transaction_trace_ptr> next) -> void {
      return my->on_incoming_transaction_async(trx, persist_until_expired, next );
   });

channel接口的使用跟上述method大同小異汤徽,channel接口的接收方/被調(diào)用方通過(guò)channel對(duì)象的subscribe方法注冊(cè),目前method的調(diào)用為同步灸撰,channel的調(diào)用為異步谒府。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市浮毯,隨后出現(xiàn)的幾起案子完疫,更是在濱河造成了極大的恐慌,老刑警劉巖债蓝,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壳鹤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡饰迹,警方通過(guò)查閱死者的電腦和手機(jī)芳誓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)啊鸭,“玉大人锹淌,你說(shuō)我怎么就攤上這事≡疲” “怎么了赂摆?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)憎妙。 經(jīng)常有香客問(wèn)我库正,道長(zhǎng),這世上最難降的妖魔是什么厘唾? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任褥符,我火速辦了婚禮,結(jié)果婚禮上抚垃,老公的妹妹穿的比我還像新娘喷楣。我一直安慰自己,他們只是感情好鹤树,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布铣焊。 她就那樣靜靜地躺著,像睡著了一般罕伯。 火紅的嫁衣襯著肌膚如雪曲伊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音坟募,去河邊找鬼岛蚤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛懈糯,可吹牛的內(nèi)容都是我干的涤妒。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼赚哗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼她紫!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起屿储,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤贿讹,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后扩所,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體围详,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡祖屏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了袁勺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡期丰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吃挑,到底是詐尸還是另有隱情钝荡,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布舶衬,位于F島的核電站埠通,受9級(jí)特大地震影響逛犹,放射性物質(zhì)發(fā)生泄漏端辱。R本人自食惡果不足惜虽画,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一舞蔽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧码撰,春花似錦渗柿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至混槐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間声登,已是汗流浹背狠鸳。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工悯嗓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留件舵,地道東北人脯厨。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓铅祸,卻偏偏與公主長(zhǎng)得像合武,于是被迫代替她去往敵國(guó)和親临梗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344