User-Defined Data Types in Messages(用戶自定義類型)
All user-defined types must be explicitly 「announced」 so that CAF can (de)serialize them correctly.ios
以前幹活,一開始不知道CAF自帶序列化,都用boost庫來作序列化,就是變string 類型發送,發現不少STL有些搞搞比較麻煩,發現誒?CAF竟然比boost庫好使!git
那麼就來搞一下看看.github
先看一個例子(也是usermanual 裏惟一的一個例子,呵呵呵~)其餘的例子在github官網裏https://github.com/actor-framework/actor-framework/tree/master/examples/type_system (就五個收益很大)編程
沒看錯就是那麼簡單的使用,announce函數。第一個參數是一個string那麼以後就是他的全部成員。怎麼實現我也不是很懂,上圖函數
大體就是TS 就是參數的類型,能夠是可變長度,而後檢查他們的類型,我第一看到Is_pod 查了一下(pod類型 是plain old data)就是徹底兼容C語言的編程的。(漲姿式了~)ui
還有uniform_type_info是CAF本身的一個關於類型什麼的(沒深究,只知道與RTTI有關)。還有一個重要的地方就是你必須寫明你要發送的結構體的比較函數 ==(下面代碼上有)spa
進入正題。(announce1.cpp)代碼有一點點小長可是信息量很大。code
// POD struct struct foo { std::vector<int> a; int b; }; // announce requires foo to have the equal operator implemented bool operator==(const foo& lhs, const foo& rhs) { return lhs.a == rhs.a && lhs.b == rhs.b; } // a pair of two ints using foo_pair = std::pair<int, int>; // another pair of two ints using foo_pair2 = std::pair<int, int>; // a struct with member vector<vector<...>> struct foo2 { int a; vector<vector<double>> b; }; bool operator==(const foo2& lhs, const foo2& rhs) { return lhs.a == rhs.a && lhs.b == rhs.b; } // receives `remaining` messages void testee(event_based_actor* self, size_t remaining) { auto set_next_behavior = [=] { if (remaining > 1) testee(self, remaining - 1); else self->quit(); }; self->become ( // note: we sent a foo_pair2, but match on foo_pair // that's safe because both are aliases for std::pair<int, int> [=](const foo_pair& val) { cout << "foo_pair(" << val.first << ", " << val.second << ")" << endl; set_next_behavior(); }, [=](const foo& val) { cout << "foo({"; auto i = val.a.begin(); auto end = val.a.end(); if (i != end) { cout << *i; while (++i != end) { cout << ", " << *i; } } cout << "}, " << val.b << ")" << endl; set_next_behavior(); } ); } int main(int, char**) { // announces foo to the libcaf type system; // the function expects member pointers to all elements of foo announce<foo>("foo", &foo::a, &foo::b); // announce foo2 to the libcaf type system, // note that recursive containers are managed automatically by libcaf announce<foo2>("foo2", &foo2::a, &foo2::b); // serialization can throw if types are not announced properly try { // init some test data foo2 vd; vd.a = 5; vd.b.resize(1); vd.b.back().push_back(42); // serialize test data vector<char> buf; binary_serializer bs(std::back_inserter(buf)); bs << vd; // deserialize written test data from buffer binary_deserializer bd(buf.data(), buf.size()); foo2 vd2; uniform_typeid<foo2>()->deserialize(&vd2, &bd); // deserialized data must be equal to original input assert(vd == vd2); // announce std::pair<int, int> to the type system announce<foo_pair>("foo_pair", &foo_pair::first, &foo_pair::second); // libcaf returns the same uniform_type_info // instance for the type aliases foo_pair and foo_pair2 assert(uniform_typeid<foo_pair>() == uniform_typeid<foo_pair2>()); } catch (std::exception& e) { cerr << "error during type (de)serialization: " << e.what() << endl; return -1; } // spawn a testee that receives two messages of user-defined type auto t = spawn(testee, size_t{2}); { // lifetime scope of self scoped_actor self; // send t a foo self->send(t, foo{std::vector<int>{1, 2, 3, 4}, 5}); // send t a foo_pair2 self->send(t, foo_pair2{3, 4}); } await_all_actors_done(); shutdown(); }
一開始看,就是聲明瞭兩種結構體。foo 和foo2,foo2裏面有vector<vector<double>> b(其實這裏就告訴咱們,它不但支持STL,還支持嵌套,並且我親測pair,map都是能夠的。其餘應該也沒問題吧。)orm
而後testee裏定義了接受兩種類型的消息一種是<int,int>(無論別名),一種是結構體foo 是的沒看錯,都不用序列化了,直接傳(// note that recursive containers are managed automatically by libcaf)。blog
真心方便,而後是main函數裏,使用了二進制去序列化類,再使用反序列化,整個過程就像用讀文件很是的方便(注意捕獲異常)。那麼在最後的scoped_actor send也直接把類傳過去很是的方便。
爲了證實好用,支持remote actor我寫了一個很難看的代碼。
#include <vector> #include <iostream> #include "caf/all.hpp" #include "caf/io/all.hpp" using std::cout; using std::endl; using std::vector; using std::map; using std::pair; using namespace caf; struct foo { std::vector<vector<map<int,pair<int,int>>>> a; int b; }; bool operator==(const foo& lhs, const foo& rhs) { return lhs.a == rhs.a && lhs.b == rhs.b; } // receives `remaining` messages void testee(event_based_actor* self) { self->become ( [=](const foo& val) { aout(self)<<"get it"<<endl; } ); } int main(int, char**) { // announce<foo2>("foo2", &foo2::a, &foo2::b); announce<foo>("foo", &foo::a, &foo::b); auto actor = spawn(testee); caf::io::publish(actor,10000); { // lifetime scope of self scoped_actor self; auto remoter = caf::io::remote_actor("localhost", 10000); self->send(remoter, foo{std::vector<vector<map<int,pair<int,int>>>>{},1,}); } await_all_actors_done(); shutdown(); }
結果爲
不得不服仍是很方便的!
碼字不容易,求粉絲~互粉呀~