This example extends the pong example and shows how to receive messages with a timeout, demonstrates registerName/whereisName and how to use lambda functors with Invoker.
#include "acedia/actor.hpp" #include "acedia/acedia.hpp" #include <iostream> #include <boost/cstdint.hpp> #include <boost/function.hpp> #include <boost/lambda/lambda.hpp> typedef boost::int32_t i32; ACEDIA_DECLARE_CASE_TUPLE1((GameBall), hits, boost::int32_t); // This implementation of Ping exits if no message was received within // 100 milliseconds and does not need to get killed by an abnormal exit // of a link or by a special message. class Ping : public acedia::Actor { // See the pong example void returnPass(i32 hits) { std::cout << "Ping: " << lastReceivedMessage().toString().const_str() << std::endl; reply(GameBall(hits+1)); } protected: virtual void act() { using acedia::on; // If you define an invoker with one rule you can pass // this rule to its constructor instead of call "add". acedia::Invoker i(on<GameBall>().unbox() >> method(&Ping::returnPass)); // Receive message until receiveAndInvokeWithin() returns false. while (receiveAndInvokeWithin(i, 100)) { } // We reach this point only if a timeout occurs. std::cout << "Ping: timeout (quit)" << std::endl; } }; // This implementation of Pong overrides only the act() member function // and does not need any data fields or additional member functions. // It uses a lambda functor as callback for acedia::Invoker // and whereisName() to find ping instead of a constructor argument. class Pong : public acedia::Actor { protected: virtual void act() { // Local variables and using delcarations. using acedia::on; using boost::lambda::var; using boost::lambda::_1; i32 hits = -1; // start with -1 because we always add 1 // Get the spawned Ping instance by name. // Note: Names are case sensitive! acedia::ActorRef ping = acedia::whereisName("ping"); // Set the local variable hits to the received value with a // lambda functor; that functor must be converted to // boost::function1<void, i32> because the lambda functor // does not match the >> operator (your compiler yields ambigious // call if you try to pass the lambda functor itself). // Note: This functor does not print the received message to stdout. // You'll see only the output of Ping if you run this example. acedia::Invoker i(on<GameBall>().unbox() >> boost::function1<void,i32>(var(hits) = _1)); // Loop until we received a GameBall with hits >= 10 while (hits < 10) { send(ping, GameBall(hits + 1)); receiveAndInvoke(i); } std::cout << "Pong is done (normal exit)" << std::endl; } }; int main(int, char**) { // spawn a ping and register it as "ping" acedia::registerName("ping", acedia::spawn<Ping>()); // spawn pong and ignore the return value of acedia::spawn (void) acedia::spawn<Pong>(); // wait until game is over and shutdown acedia::waitForAllActorsDone(); acedia::shutdown(); }