for (;;) { receive ( on<int>() >> [](int value) { ... }, on<double>() >> [](double value) { ... }, ... ); }
That's a naive approach, because you define your pattern inside of the loop. Instead of re-using the pattern, you create new objects in each iteration.
This example re-uses the pattern, but the code is more verbose and breaks locality; the pattern is no longer part of the loop and you have to scroll up to see where the pattern is defined.
auto pattern = ( on<int>() >> [](int value) { ... }, on<double>() >> [](double value) { ... }, ... ); for (;;) { receive(pattern); }
Note the syntax auto pattern = ()! Your compiler won't accept the code if you miss the brackets, because he's thinking the comma separates two declarations.
To provide a more elegant, and less error-prone, way to express loops, there are three "predefined" loops in libcppa:
- receive_loop([PATTERN]);
- receive_while([LAMBDA -> bool])([PATTERN]);
- do_receive([PATTERN]).until([LAMBDA -> bool]);
The first one loops forever. The other two use lambda expressions for the loop condition. C++ doesn't have a nicer way to pass a block of code (or even one simple statement) to a function, therefore it's more verbose than the built-in while() loop (yes, Scala does a much better job here...).
Anyway, this is a short but complete example program that uses two of the receive loops:
#include <iostream> #include "cppa/cppa.hpp" using std::cout; using std::endl; using namespace cppa; void ping() { receive_loop ( on<atom("Pong"), int>() >> [](int value) { cout << "ping received { Pong, " << value << " }" << endl; reply(atom("Ping"), value + 1); } ); } void pong(actor_ptr ping_actor) { link(ping_actor); send(ping_actor, atom("Pong"), 0); int last_ping = 0; receive_while([&]() { return last_ping < 9; }) ( on<atom("Ping"), int>() >> [&](int value) { cout << "pong received { Ping, " << value << " }" << endl; last_ping = value; reply(atom("Pong"), value + 1); } ); // non-normal exit reason forces ping_actor to quit quit(exit_reason::user_defined); } int main() { spawn(pong, spawn(ping)); await_all_others_done(); return 0; }And this is the output of the example program:
ping received { Pong, 0 } pong received { Ping, 1 } ping received { Pong, 2 } pong received { Ping, 3 } ping received { Pong, 4 } pong received { Ping, 5 } ping received { Pong, 6 } pong received { Ping, 7 } ping received { Pong, 8 } pong received { Ping, 9 } ping received { Pong, 10 }
I was looking for a small an d easy to use C++ actor library, and libcppa seems to fit, especially in those exemples. I hope it'll get more stable and more documented in the future, as i truly intend to use it for a game project. Go on with it, it looks very nice !
ReplyDeleteThank you! :)
ReplyDeleteDocumentation really needs some updates, but the library almost reached beta state now. The thing that really annoys me, is that there's only one compiler around (GCC >= 4.6.1) that implements enough C++11 features to run libcppa. I really hope VisualStudio 2011 will catch up with GCC, so that I get libcppa running on Windows as well.