CAF(C++ actor framework)(序列化之結構體,任意嵌套STL)(一)

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();
}

結果爲

不得不服仍是很方便的!

碼字不容易,求粉絲~互粉呀~

相關文章
相關標籤/搜索