Commit 8ee58b35 authored by Dominik Charousset's avatar Dominik Charousset

modified all examples do use event-based API only

parent b490caff
......@@ -17,8 +17,8 @@ add(announce_5 type_system)
add(dancing_kirby message_passing)
add(dining_philosophers message_passing)
add(hello_world .)
add(math_actor message_passing)
add(distributed_math_actor remote_actors)
add(calculator message_passing)
add(distributed_calculator remote_actors)
add(group_server remote_actors)
add(group_chat remote_actors)
......
......@@ -9,8 +9,8 @@ void mirror() {
become (
// invoke this lambda expression if we receive a string
on_arg_match >> [](const std::string& what) {
// prints "Hello World!"
std::cout << what << std::endl;
// prints "Hello World!" via aout (thread-safe wrapper for cout)
aout << what << std::endl;
// replies "!dlroW olleH"
reply(std::string(what.rbegin(), what.rend()));
// terminates this actor
......@@ -20,13 +20,13 @@ void mirror() {
}
void hello_world(const actor_ptr& buddy) {
// send "Hello World!" to the mirror
// send "Hello World!" to our buddy
send(buddy, "Hello World!");
// wait for messages
become (
on_arg_match >> [](const std::string& what) {
// prints "!dlroW olleH"
std::cout << what << std::endl;
aout << what << std::endl;
// terminate this actor
self->quit();
}
......@@ -42,5 +42,4 @@ int main() {
await_all_others_done();
// run cleanup code before exiting main
shutdown();
return 0;
}
......@@ -34,8 +34,7 @@ void blocking_math_fun() {
).until(gref(done));
}
// implementation using the event-based API
void math_fun() {
void calculator() {
// execute this behavior until actor terminates
become (
on(atom("plus"), arg_match) >> [](int a, int b) {
......@@ -44,43 +43,38 @@ void math_fun() {
on(atom("minus"), arg_match) >> [](int a, int b) {
reply(atom("result"), a - b);
},
// the [=] capture copies the 'this' pointer into the lambda
// thus, it has access to all members and member functions
on(atom("quit")) >> [=] {
on(atom("quit")) >> [] {
// terminate actor with normal exit reason
self->quit();
}
);
}
// utility function
int fetch_result(actor_ptr& calculator, atom_value operation, int a, int b) {
// send request
send(calculator, operation, a, b);
// wait for result
int result;
receive(on<atom("result"), int>() >> [&](int r) { result = r; });
// print and return result
cout << a << " " << to_string(operation) << " " << b << " = " << result << endl;
return result;
void tester(const actor_ptr& testee) {
self->link_to(testee);
// will be invoked if we receive an unexpected response message
self->on_sync_failure([] {
aout << "AUT (actor under test) failed" << endl;
self->quit(exit_reason::user_defined);
});
// first test: 2 + 1 = 3
sync_send(testee, atom("plus"), 2, 1).then(
on(atom("result"), 3) >> [=] {
// second test: 2 - 1 = 1
sync_send(testee, atom("minus"), 2, 1).then(
on(atom("result"), 1) >> [=] {
// both tests succeeded
aout << "AUT (actor under test) seems to be ok" << endl;
send(testee, atom("quit"));
}
);
}
);
}
int main() {
// spawn a context-switching actor that invokes math_fun
auto a1 = spawn<blocking_api>(blocking_math_fun);
// spawn an event-based math actor
auto a2 = spawn(math_fun);
// do some testing on both implementations
assert((fetch_result(a1, atom("plus"), 1, 2) == 3));
assert((fetch_result(a2, atom("plus"), 1, 2) == 3));
assert((fetch_result(a1, atom("minus"), 2, 1) == 1));
assert((fetch_result(a2, atom("minus"), 2, 1) == 1));
// tell both actors to terminate
send(a1, atom("quit"));
send(a2, atom("quit"));
// wait until all spawned actors are terminated
spawn(tester, spawn(calculator));
await_all_others_done();
// done
shutdown();
return 0;
}
......
......@@ -25,186 +25,147 @@ using namespace std;
using namespace cppa;
using namespace cppa::placeholders;
// our service provider
struct math_actor : event_based_actor {
void init() {
// execute this behavior until actor terminates
become (
on(atom("plus"), arg_match) >> [](int a, int b) {
reply(atom("result"), a + b);
},
on(atom("minus"), arg_match) >> [](int a, int b) {
reply(atom("result"), a - b);
},
on(atom("quit")) >> [=]() {
quit();
}
);
}
};
inline string& ltrim(string &s) {
s.erase(s.begin(), find_if(s.begin(), s.end(), [](char c) { return !isspace(c); }));
return s;
}
inline string& rtrim(std::string& s) {
s.erase(find_if(s.rbegin(), s.rend(), [](char c) { return !isspace(c); }).base(), s.end());
return s;
// our "service"
void calculator() {
become (
on(atom("plus"), arg_match) >> [](int a, int b) {
reply(atom("result"), a + b);
},
on(atom("minus"), arg_match) >> [](int a, int b) {
reply(atom("result"), a - b);
},
on(atom("quit")) >> [=]() {
self->quit();
}
);
}
inline string& trim(std::string& s) {
return ltrim(rtrim(s));
inline string trim(std::string s) {
auto not_space = [](char c) { return !isspace(c); };
// trim left
s.erase(s.begin(), find_if(s.begin(), s.end(), not_space));
// trim right
s.erase(find_if(s.rbegin(), s.rend(), not_space).base(), s.end());
return std::move(s);
}
option<int> toint(const string& str) {
if (str.empty()) return {};
char* endptr = nullptr;
int result = static_cast<int>(strtol(str.c_str(), &endptr, 10));
if (endptr != nullptr && *endptr == '\0') {
return result;
void client_bhvr(const string& host, uint16_t port, const actor_ptr& server) {
// recover from sync failures by trying to reconnect to server
if (!self->has_sync_failure_handler()) {
self->on_sync_failure([=] {
aout << "*** lost connection to " << host << ":" << port << endl;
client_bhvr(host, port, nullptr);
});
}
return {};
}
template<typename T>
struct project_helper;
template<>
struct project_helper<string> {
template<typename T>
inline option<T> convert(const string& from, typename enable_if<is_integral<T>::value>::type* = 0) {
char* endptr = nullptr;
auto result = static_cast<T>(strtol(from.c_str(), &endptr, 10));
if (endptr != nullptr && *endptr == '\0') return result;
return {};
// connect to server if needed
if (!server) {
aout << "*** try to connect to " << host << ":" << port << endl;
try {
auto new_serv = remote_actor(host, port);
self->monitor(new_serv);
aout << "reconnection succeeded" << endl;
client_bhvr(host, port, new_serv);
return;
}
catch (exception&) {
aout << "connection failed, try again in 3s" << endl;
delayed_send(self, chrono::seconds(3), atom("reconnect"));
}
}
};
template<typename From, typename To>
option<To> projection(const From& from) {
project_helper<From> f;
return f.template convert<To>(from);
become (
on_arg_match.when(_x1.in({atom("plus"), atom("minus")}) && gval(server) != nullptr) >> [=](atom_value op, int lhs, int rhs) {
sync_send_tuple(server, self->last_dequeued()).then(
on(atom("result"), arg_match) >> [=](int result) {
aout << lhs << " "
<< to_string(op) << " "
<< rhs << " = "
<< result << endl;
}
);
},
on(atom("DOWN"), arg_match) >> [=](uint32_t) {
aout << "*** server down, try to reconnect ..." << endl;
client_bhvr(host, port, nullptr);
},
on(atom("rebind"), arg_match) >> [=](const string& host, uint16_t port) {
aout << "*** rebind to new server: " << host << ":" << port << endl;
client_bhvr(host, port, nullptr);
},
on(atom("reconnect")) >> [=] {
client_bhvr(host, port, nullptr);
}
);
}
void client_repl(actor_ptr server, string host, uint16_t port) {
void client_repl(const string& host, uint16_t port) {
typedef cow_tuple<atom_value, int, int> request;
// keeps track of requests and tries to reconnect on server failures
auto client = factory::event_based([=](actor_ptr* serv, vector<request>* q) {
self->monitor(*serv);
auto send_next_request = [=] {
if (!q->empty()) {
*serv << q->front();
}
};
self->become (
on<atom_value, int, int>().when(_x1.in({atom("plus"), atom("minus")})) >> [=] {
if (q->empty()) {
*serv << self->last_dequeued();
}
q->push_back(*tuple_cast<atom_value, int, int>(self->last_dequeued()));
},
on(atom("result"), arg_match) >> [=](int result) {
if (q->empty()) {
aout << "received a result, but didn't send a request\n";
return;
}
ostringstream oss;
auto& r = q->front();
aout << get<1>(r) << " "
<< to_string(get<0>(r)) << " "
<< get<2>(r)
<< " = " << result
<< endl;
q->erase(q->begin());
send_next_request();
},
on(atom("DOWN"), arg_match) >> [=](uint32_t reason) {
if (*serv == self->last_sender()) {
serv->reset(); // sets *serv = nullptr
ostringstream oss;
aout << "*** server exited with reason = " << reason
<< ", try to reconnect"
<< endl;
send(self, atom("reconnect"));
}
},
on(atom("reconnect")) >> [=] {
if (*serv != nullptr) return;
try {
*serv = remote_actor(host, port);
self->monitor(*serv);
aout << "reconnection succeeded" << endl;
send_next_request();
}
catch (exception&) {
delayed_send(self, chrono::seconds(3), atom("reconnect"));
}
},
on(atom("rebind"), arg_match) >> [=](string& host, uint16_t port) {
actor_ptr new_serv;
try {
new_serv = remote_actor(move(host), port);
self->monitor(new_serv);
aout << "rebind succeeded" << endl;
*serv = new_serv;
send_next_request();
}
catch (exception& e) {
aout << "*** rebind failed: "
<< to_verbose_string(e) << endl;
}
},
on(atom("quit")) >> [=] {
self->quit();
},
others() >> [] {
aout << "unexpected message: " << self->last_dequeued() << endl;
}
);
}).spawn(server);
aout << "quit Quit the program\n"
"<x> + <y> Calculate <x>+<y> and print result\n"
"<x> - <y> Calculate <x>-<y> and print result\n"
"connect <host> <port> Reconfigure server"
<< endl;
aout << "Usage:\n"
"quit Quit the program\n"
"<x> + <y> Calculate <x>+<y> and print result\n"
"<x> - <y> Calculate <x>-<y> and print result\n"
"connect <host> <port> Reconfigure server"
<< endl << endl;
string line;
auto client = spawn(client_bhvr, host, port, nullptr);
const char connect[] = "connect ";
while (getline(cin, line)) {
trim(line);
line = trim(std::move(line)); // ignore leading and trailing whitespaces
if (line == "quit") {
send(client, atom("quit"));
// force client to quit
send_exit(client, exit_reason::user_defined);
return;
}
// the STL way of line.starts_with("connect")
else if (equal(begin(connect), end(connect) - 1, begin(line))) {
match_split(line, ' ') (
on("connect", val<string>, projection<string,uint16_t>) >> [&](string& host, uint16_t port) {
send(client, atom("rebind"), move(host), port);
on("connect", arg_match) >> [&](string& host, string& sport) {
try {
auto lport = std::stoul(sport);
if (lport < std::numeric_limits<uint16_t>::max()) {
auto port = static_cast<uint16_t>(lport);
send(client, atom("rebind"), move(host), port);
}
else {
aout << lport << " is not a valid port" << endl;
}
}
catch (std::exception& e) {
aout << "\"" << sport << "\" is not an unsigned integer"
<< endl;
}
},
others() >> [] {
aout << "illegal host/port definition" << endl;
aout << "*** usage: connect <host> <port>" << endl;
}
);
}
else {
auto toint = [](const string& str) -> option<int> {
try { return {std::stoi(str)}; }
catch (std::exception&) {
aout << "\"" << str << "\" is not an integer" << endl;
return {};
}
};
bool success = false;
auto pos = find_if(begin(line), end(line), [](char c) { return c == '+' || c == '-'; });
if (pos != end(line)) {
string lsub(begin(line), pos);
string rsub(pos + 1, end(line));
auto lhs = toint(trim(lsub));
auto rhs = toint(trim(rsub));
auto first = begin(line);
auto last = end(line);
auto pos = find_if(first, last, [](char c) { return c == '+' || c == '-'; });
if (pos != last) {
auto lsub = trim(string(first, pos));
auto rsub = trim(string(pos + 1, last));
auto lhs = toint(lsub);
auto rhs = toint(rsub);
if (lhs && rhs) {
auto op = (*pos == '+') ? atom("plus") : atom("minus");
send(client, op, *lhs, *rhs);
}
else {
if (!lhs) aout << "\"" + lsub + "\" is not an integer" << endl;
if (!rhs) aout << "\"" + rsub + "\" is not an integer" << endl;
}
}
else if (!success) aout << "*** invalid format; use: X +/- Y" << endl;
else if (!success) {
aout << "*** invalid format; usage: <x> [+|-] <y>" << endl;
}
}
}
}
......@@ -237,13 +198,14 @@ int main(int argc, char** argv) {
if (port == 0) cerr << "*** no port specified" << endl;
if (mode.empty()) cerr << "*** no mode specified" << endl;
cerr << endl;
print_desc(&desc, cerr)();
auto description_printer = print_desc(&desc, cerr);
description_printer();
return -1;
}
if (mode == "server") {
try {
// try to publish math actor at given port
publish(spawn<math_actor>(), port);
publish(spawn(calculator), port);
}
catch (exception& e) {
cerr << "*** unable to publish math actor at port " << port << "\n"
......@@ -253,15 +215,7 @@ int main(int argc, char** argv) {
}
else {
if (host.empty()) host = "localhost";
try {
auto server = remote_actor(host, port);
client_repl(server, host, port);
}
catch (exception& e) {
cerr << "unable to connect to remote actor at host \""
<< host << "\" on port " << port << "\n"
<< to_verbose_string(e) << endl;
}
client_repl(host, port);
}
await_all_others_done();
shutdown();
......
......@@ -29,7 +29,7 @@ istream& operator>>(istream& is, line& l) {
return is;
}
string s_last_line;
namespace { string s_last_line; }
any_tuple split_line(const line& l) {
istringstream strs(l.str);
......@@ -42,46 +42,32 @@ any_tuple split_line(const line& l) {
return any_tuple::view(std::move(result));
}
class client : public event_based_actor {
public:
client(string name) : m_name(move(name)) { }
protected:
void init() {
become (
on(atom("broadcast"), arg_match) >> [=](const string& message) {
for(auto& dest : joined_groups()) {
send(dest, m_name + ": " + message);
}
},
on(atom("join"), arg_match) >> [=](const group_ptr& what) {
for (auto g : joined_groups()) {
cout << "*** leave " << to_string(g) << endl;
send(g, m_name + " has left the chatroom");
leave(g);
}
cout << "*** join " << to_string(what) << endl;
join(what);
send(what, m_name + " has entered the chatroom");
},
on<string>() >> [=](const string& txt) {
// don't print own messages
if (last_sender() != this) cout << txt << endl;
},
others() >> [=]() {
cout << "unexpected: " << to_string(last_dequeued()) << endl;
void client(const string& name) {
become (
on(atom("broadcast"), arg_match) >> [=](const string& message) {
for(auto& dest : self->joined_groups()) {
send(dest, name + ": " + message);
}
);
}
private:
string m_name;
};
},
on(atom("join"), arg_match) >> [=](const group_ptr& what) {
for (auto g : self->joined_groups()) {
cout << "*** leave " << to_string(g) << endl;
send(g, name + " has left the chatroom");
self->leave(g);
}
cout << "*** join " << to_string(what) << endl;
self->join(what);
send(what, name + " has entered the chatroom");
},
on<string>() >> [=](const string& txt) {
// don't print own messages
if (self->last_sender() != self) cout << txt << endl;
},
others() >> [=]() {
cout << "unexpected: " << to_string(self->last_dequeued()) << endl;
}
);
}
int main(int argc, char** argv) {
......@@ -105,7 +91,7 @@ int main(int argc, char** argv) {
}
cout << "*** starting client, type '/help' for a list of commands" << endl;
auto client_actor = spawn<client>(name);
auto client_actor = spawn(client, name);
// evaluate group parameters
if (!group_id.empty()) {
......@@ -156,7 +142,7 @@ int main(int argc, char** argv) {
}
);
// force actor to quit
quit_actor(client_actor, exit_reason::user_defined);
send_exit(client_actor, exit_reason::user_defined);
await_all_others_done();
shutdown();
return 0;
......
......@@ -30,7 +30,8 @@ int main(int argc, char** argv) {
}
if (!args_valid) {
// print_desc(&desc) returns a function printing the stored help text
print_desc(&desc)();
auto desc_printer = print_desc(&desc);
desc_printer();
return 1;
}
try {
......
......@@ -41,6 +41,38 @@ bool operator==( const foo2& lhs, const foo2& rhs ) {
return lhs.a == rhs.a && lhs.b == rhs.b;
}
// receives `remaining` messages
void testee(size_t remaining) {
auto set_next_behavior = [=] {
if (remaining > 1) testee(remaining - 1);
else self->quit();
};
become (
// note: we sent a foo_pair2, but match on foo_pair
// that's safe because both are aliases for std::pair<int,int>
on<foo_pair>() >> [=](const foo_pair& val) {
cout << "foo_pair("
<< val.first << ","
<< val.second << ")"
<< endl;
set_next_behavior();
},
on<foo>() >> [=](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 libcppa type system;
......@@ -75,41 +107,18 @@ int main(int, char**) {
// std::pair<int,int> is already announced
assert(announce<foo_pair2>(&foo_pair2::first, &foo_pair2::second) == false);
// send a foo to ourselves
send(self, foo{std::vector<int>{1, 2, 3, 4}, 5});
// send a foo_pair2 to ourselves
send(self, foo_pair2{3, 4});
// quits the program
send(self, atom("done"));
// libcppa returns the same uniform_type_info
// instance for foo_pair and foo_pair2
assert(uniform_typeid<foo_pair>() == uniform_typeid<foo_pair2>());
// receive two messages
int i = 0;
receive_for(i, 2) (
// note: we sent a foo_pair2, but match on foo_pair
// that's safe because both are aliases for std::pair<int,int>
on<foo_pair>() >> [](const foo_pair& val) {
cout << "foo_pair("
<< val.first << ","
<< val.second << ")"
<< endl;
},
on<foo>() >> [](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;
}
);
// spawn a testee that receives two messages
auto t = spawn(testee, 2);
// send t a foo
send(t, foo{std::vector<int>{1, 2, 3, 4}, 5});
// send t a foo_pair2
send(t, foo_pair2{3, 4});
await_all_others_done();
shutdown();
return 0;
}
......
......@@ -35,29 +35,32 @@ class foo {
};
// announce requires foo to have the equal operator implemented
// announce requires foo to be comparable
bool operator==(const foo& lhs, const foo& rhs) {
return lhs.a() == rhs.a()
&& lhs.b() == rhs.b();
}
int main(int, char**) {
// if a class uses getter and setter member functions,
// we pass those to the announce function as { getter, setter } pairs.
announce<foo>(make_pair(&foo::a, &foo::set_a),
make_pair(&foo::b, &foo::set_b));
// send a foo to ourselves ...
send(self, foo{1,2});
receive (
// ... and receive it
void testee() {
become (
on<foo>() >> [](const foo& val) {
cout << "foo("
aout << "foo("
<< val.a() << ","
<< val.b() << ")"
<< endl;
self->quit();
}
);
}
int main(int, char**) {
// if a class uses getter and setter member functions,
// we pass those to the announce function as { getter, setter } pairs.
announce<foo>(make_pair(&foo::a, &foo::set_a),
make_pair(&foo::b, &foo::set_b));
auto t = spawn(testee);
send(t, foo{1,2});
await_all_others_done();
shutdown();
return 0;
}
......
......@@ -46,6 +46,18 @@ typedef int (foo::*foo_getter)() const;
// a member function pointer to set an attribute of foo
typedef void (foo::*foo_setter)(int);
void testee() {
become (
on<foo>() >> [](const foo& val) {
aout << "foo("
<< val.a() << ","
<< val.b() << ")"
<< endl;
self->quit();
}
);
}
int main(int, char**) {
// since the member function "a" is ambiguous, the compiler
// also needs a type to select the correct overload
......@@ -65,17 +77,9 @@ int main(int, char**) {
make_pair(static_cast<foo_getter>(&foo::b),
static_cast<foo_setter>(&foo::b)));
// send a foo to ourselves ...
send(self, foo{1,2});
receive (
// ... and receive it
on<foo>() >> [](const foo& val) {
cout << "foo("
<< val.a() << ","
<< val.b() << ")"
<< endl;
}
);
// spawn a new testee and send it a foo
send(spawn(testee), foo{1,2});
await_all_others_done();
shutdown();
return 0;
}
......
......@@ -78,6 +78,29 @@ bool operator==(const baz& lhs, const baz& rhs) {
&& lhs.b == rhs.b;
}
// receives `remaining` messages
void testee(size_t remaining) {
auto set_next_behavior = [=] {
if (remaining > 1) testee(remaining - 1);
else self->quit();
};
become (
on<bar>() >> [=](const bar& val) {
aout << "bar(foo("
<< val.f.a() << ","
<< val.f.b() << "),"
<< val.i << ")"
<< endl;
set_next_behavior();
},
on<baz>() >> [=](const baz& val) {
// prints: baz ( foo ( 1, 2 ), bar ( foo ( 3, 4 ), 5 ) )
aout << to_string(object::from(val)) << endl;
set_next_behavior();
}
);
}
int main(int, char**) {
// bar has a non-trivial data member f, thus, we have to told
// announce how to serialize/deserialize this member;
......@@ -102,26 +125,11 @@ int main(int, char**) {
make_pair(&foo::b, &foo::set_b)),
&bar::i));
// send a bar to ourselves
send(self, bar{foo{1,2},3});
// send a baz to ourselves
send(self, baz{foo{1,2},bar{foo{3,4},5}});
// receive two messages
int i = 0;
receive_for(i, 2) (
on<bar>() >> [](const bar& val) {
cout << "bar(foo("
<< val.f.a() << ","
<< val.f.b() << "),"
<< val.i << ")"
<< endl;
},
on<baz>() >> [](const baz& val) {
// prints: baz ( foo ( 1, 2 ), bar ( foo ( 3, 4 ), 5 ) )
cout << to_string(object::from(val)) << endl;
}
);
// spawn a testee that receives two messages
auto t = spawn(testee, 2);
send(t, bar{foo{1,2},3});
send(t, baz{foo{1,2},bar{foo{3,4},5}});
await_all_others_done();
shutdown();
return 0;
}
......
......@@ -39,18 +39,18 @@ struct tree_node {
void print() const {
// format is: value { children0, children1, ..., childrenN }
// e.g., 10 { 20 { 21, 22 }, 30 }
cout << value;
aout << value;
if (children.empty() == false) {
cout << " { ";
aout << " { ";
auto begin = children.begin();
auto end = children.end();
for (auto i = begin; i != end; ++i) {
if (i != begin) {
cout << ", ";
aout << ", ";
}
i->print();
}
cout << " } ";
aout << " } ";
}
}
......@@ -62,9 +62,9 @@ struct tree {
// print tree to stdout
void print() const {
cout << "tree::print: ";
aout << "tree::print: ";
root.print();
cout << endl;
aout << endl;
}
};
......@@ -138,17 +138,53 @@ class tree_type_info : public util::abstract_uniform_type_info<tree> {
};
typedef std::vector<tree> tree_vector;
// receives `remaining` messages
void testee(size_t remaining) {
auto set_next_behavior = [=] {
if (remaining > 1) testee(remaining - 1);
else self->quit();
};
become (
on_arg_match >> [=](const tree& tmsg) {
// prints the tree in its serialized format:
// @<> ( { tree ( 0, { 10, { 11, { }, 12, { }, 13, { } }, 20, { 21, { }, 22, { } } } ) } )
aout << "to_string(self->last_dequeued()): "
<< to_string(self->last_dequeued())
<< endl;
// prints the tree using the print member function:
// 0 { 10 { 11, 12, 13 } , 20 { 21, 22 } }
tmsg.print();
set_next_behavior();
},
on_arg_match >> [=](const tree_vector& trees) {
// prints "received 2 trees"
aout << "received " << trees.size() << " trees" << endl;
// prints:
// @<> ( {
// std::vector<tree,std::allocator<tree>> ( {
// tree ( 0, { 10, { 11, { }, 12, { }, 13, { } }, 20, { 21, { }, 22, { } } } ),
// tree ( 0, { 10, { 11, { }, 12, { }, 13, { } }, 20, { 21, { }, 22, { } } } )
// )
// } )
aout << "to_string: " << to_string(self->last_dequeued()) << endl;
set_next_behavior();
}
);
}
int main() {
// the tree_type_info is owned by libcppa after this function call
announce(typeid(tree), new tree_type_info);
tree t; // create a tree and fill it with some data
tree t0; // create a tree and fill it with some data
t.root.add_child(10);
t.root.children.back().add_child(11).add_child(12).add_child(13);
t0.root.add_child(10);
t0.root.children.back().add_child(11).add_child(12).add_child(13);
t.root.add_child(20);
t.root.children.back().add_child(21).add_child(22);
t0.root.add_child(20);
t0.root.children.back().add_child(21).add_child(22);
/*
tree t is now:
......@@ -162,44 +198,20 @@ int main() {
11 12 13 21 22
*/
// send a tree to ourselves ...
send(self, t);
// spawn a testee that receives two messages
auto t = spawn(testee, 2);
// send a vector of trees to ourselves
typedef std::vector<tree> tree_vector;
// send a tree
send(t, t0);
// send a vector of trees
announce<tree_vector>();
tree_vector tvec;
tvec.push_back(t);
tvec.push_back(t);
send(self, tvec);
// receive both messages
int i = 0;
receive_for(i, 2) (
// ... and receive it
on<tree>() >> [](const tree& tmsg) {
// prints the tree in its serialized format:
// @<> ( { tree ( 0, { 10, { 11, { }, 12, { }, 13, { } }, 20, { 21, { }, 22, { } } } ) } )
cout << "to_string(self->last_dequeued()): "
<< to_string(self->last_dequeued())
<< endl;
// prints the tree using the print member function:
// 0 { 10 { 11, 12, 13 } , 20 { 21, 22 } }
tmsg.print();
},
on<tree_vector>() >> [](const tree_vector& trees) {
// prints "received 2 trees"
cout << "received " << trees.size() << " trees" << endl;
// prints:
// @<> ( {
// std::vector<tree,std::allocator<tree>> ( {
// tree ( 0, { 10, { 11, { }, 12, { }, 13, { } }, 20, { 21, { }, 22, { } } } ),
// tree ( 0, { 10, { 11, { }, 12, { }, 13, { } }, 20, { 21, { }, 22, { } } } )
// )
// } )
cout << "to_string: " << to_string(self->last_dequeued()) << endl;
}
);
tvec.push_back(t0);
tvec.push_back(t0);
send(t, tvec);
await_all_others_done();
shutdown();
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment