Commit eb95361e authored by neverlord's avatar neverlord

documentation

parent 4d8aa4f0
...@@ -235,3 +235,4 @@ examples/announce_example_3.cpp ...@@ -235,3 +235,4 @@ examples/announce_example_3.cpp
examples/announce_example_4.cpp examples/announce_example_4.cpp
examples/announce_example_5.cpp examples/announce_example_5.cpp
examples/hello_world_example.cpp examples/hello_world_example.cpp
examples/math_actor_example.cpp
...@@ -78,6 +78,10 @@ ...@@ -78,6 +78,10 @@
* each context <i>is</i> an actor. Even main is implicitly * each context <i>is</i> an actor. Even main is implicitly
* converted to an actor if needed, as the following example shows: * converted to an actor if needed, as the following example shows:
* *
* It's recommended to read at least the
* {@link MessageHandling message handling}
* section of this documentation.
*
* @subsection IntroHelloWorld Hello World Example * @subsection IntroHelloWorld Hello World Example
* *
* @include hello_world_example.cpp * @include hello_world_example.cpp
...@@ -157,9 +161,183 @@ ...@@ -157,9 +161,183 @@
* message handling. * message handling.
* *
* A message in @p libcppa is a n-tuple of values (with size >= 1). You can use * A message in @p libcppa is a n-tuple of values (with size >= 1). You can use
* almost every type in messages. * almost every type in a messages.
*
* @section Send Send messages
*
* The function @p send could be used to send a message to an actor.
* The first argument is the receiver of the message followed by any number
* of values. @p send creates a tuple from the given values and enqueues the
* tuple to the receivers mailbox. Thus, send should @b not be used to send
* a message to multiple receivers. You should use the @p enqueue
* member function of the receivers instead as in the following example:
*
* @code
* // spawn some actors
* auto a1 = spawn(...);
* auto a2 = spawn(...);
* auto a3 = spawn(...);
*
* // send a message to a1
* send(a1, atom("hello"), "hello a1!");
*
* // send a message to a1, a2 and a3
* auto msg = make_tuple(atom("compute"), 1, 2, 3);
* auto s = self(); // cache self() pointer
* // note: this is more efficient then using send() three times because
* // send() would create a new tuple each time;
* // this safes both time and memory thanks to libcppa's copy-on-write
* a1->enqueue(s, msg);
* a2->enqueue(s, msg);
* a3->enqueue(s, msg);
*
* // modify msg and send it again
* // (msg becomes detached due to copy-on-write optimization)
* get_ref<1>(msg) = 10; // msg is now { atom("compute"), 10, 2, 3 }
* a1->enqueue(s, msg);
* a2->enqueue(s, msg);
* a3->enqueue(s, msg);
* @endcode
*
* @section Receive Receive messages
*
* The function @p receive takes a @i behavior as argument. The behavior
* is a list of { pattern >> callback } rules.
*
* @code
* receive
* (
* on<atom("hello"), std::string>() >> [](const std::string& msg)
* {
* cout << "received hello message: " << msg << endl;
* },
* on<atom("compute"), int, int, int>() >> [](int i0, int i1, int i2)
* {
* // send our result back to the sender of this messages
* reply(atom("result"), i0 + i1 + i2);
* }
* );
* @endcode
*
* The function @p on creates a pattern.
* It provides two ways of defining patterns:
* either by template parameters (prefixed by up to four atoms) or by arguments.
* The first way matches for types only (exept for the prefixing atoms).
* The second way compares values.
* Use the template function @p val to match for the type only.
*
* This example is equivalent to the previous one but uses the second way
* to define patterns:
*
* @code
* receive
* (
* on(atom("hello"), val<std::string>()) >> [](const std::string& msg)
* {
* cout << "received hello message: " << msg << endl;
* },
* on(atom("compute"), val<int>(), val<int>(), val<int>()>() >> [](int i0, int i1, int i2)
* {
* // send our result back to the sender of this messages
* reply(atom("result"), i0 + i1 + i2);
* }
* );
* @endcode
*
* @section Atoms Atoms
*
* Atoms are a nice way to add semantic informations to a message.
* Assuming an actor wants to provide a "math sevice" for integers. It
* could provide operations such as addition, subtraction, etc.
* This operations all have two operands. Thus, the actor does not know
* what operation the sender of a message wanted by receiving just two integers.
*
* Example actor:
* @code
* void math_actor()
* {
* receive_loop
* (
* on<atom("plus"), int, int>() >> [](int a, int b)
* {
* reply(atom("result"), a + b);
* },
* on<atom("minus"), int, int>() >> [](int a, int b)
* {
* reply(atom("result"), a - b);
* }
* );
* }
* @endcode
*
* @section ReceiveLoops Receive loops
*
* Previous examples using @p receive create behavior on-the-fly.
* This is inefficient in a loop since the argument passed to receive
* is created in each iteration again. Its possible to store the behavior
* in a variable and pass that variable to receive. This fixes the issue
* of re-creation each iteration but rips apart definition and usage.
*
* There are three convenience function implementing receive loops to
* declare patterns and behavior where they belong without unnecessary
* copies: @p receive_loop, @p receive_while and @p do_receive.
*
* @p receive_loop is analogous to @p receive and loops "forever" (until the
* actor finishes execution).
*
* @p receive_while creates a functor evaluating a lambda expression.
* The loop continues until the given returns false. A simple example:
*
* @code
* // receive two ints
* vector<int> received_values;
* receive_while([&]() { return received_values.size() < 2; })
* (
* on<int>() >> [](int value)
* {
* received_values.push_back(value);
* }
* );
* // ...
* @endcode
*
* @p do_receive returns a functor providing the function @p until that
* takes a lambda expression. The loop continues until the given lambda
* returns true. Example:
* *
* @section UsingOwnTypes Using own types in messages * @code
* // receive ints until zero was received
* vector<int> received_values;
* do_receive
* (
* on<int>() >> [](int value)
* {
* received_values.push_back(value);
* }
* )
* .until([&]() { return received_values.back() == 0 });
* // ...
* @endcode
*
* @section FutureSend Send delayed messages
*
* The function @p future_send provides a simple way to delay a message.
* This is particularly useful for recurring events, e.g., periodical polling.
* Usage example:
*
* @code
* future_send(self(), std::chrono::seconds(1), atom("poll"));
* receive_loop
* (
* // ...
* on<atom("poll")>() >> []()
* {
* // ... poll something ...
* // and do it again after 1sec
* future_send(self(), std::chrono::seconds(1), atom("poll"));
* }
* );
* @endcode
* *
* @defgroup ImplicitConversion Implicit type conversions. * @defgroup ImplicitConversion Implicit type conversions.
* *
...@@ -182,7 +360,7 @@ ...@@ -182,7 +360,7 @@
* // sends an std::u16string containing the UTF16 string "hello unicode world!" * // sends an std::u16string containing the UTF16 string "hello unicode world!"
* send(self(), u"hello unicode world!"); * send(self(), u"hello unicode world!");
* *
* // x has the type tuple<std::string, std::string> * // x has the type cppa::tuple<std::string, std::string>
* auto x = make_tuple("hello", "tuple"); * auto x = make_tuple("hello", "tuple");
* *
* receive * receive
......
...@@ -8,7 +8,8 @@ noinst_PROGRAMS = announce_example_1 \ ...@@ -8,7 +8,8 @@ noinst_PROGRAMS = announce_example_1 \
announce_example_3 \ announce_example_3 \
announce_example_4 \ announce_example_4 \
announce_example_5 \ announce_example_5 \
hello_world_example hello_world_example \
math_example
announce_example_1_SOURCES = announce_example_1.cpp announce_example_1_SOURCES = announce_example_1.cpp
announce_example_2_SOURCES = announce_example_2.cpp announce_example_2_SOURCES = announce_example_2.cpp
...@@ -16,6 +17,7 @@ announce_example_3_SOURCES = announce_example_3.cpp ...@@ -16,6 +17,7 @@ announce_example_3_SOURCES = announce_example_3.cpp
announce_example_4_SOURCES = announce_example_4.cpp announce_example_4_SOURCES = announce_example_4.cpp
announce_example_5_SOURCES = announce_example_5.cpp announce_example_5_SOURCES = announce_example_5.cpp
hello_world_example_SOURCES = hello_world_example.cpp hello_world_example_SOURCES = hello_world_example.cpp
math_example_SOURCES = math_example.cpp
EXAMPLES_LIBS = $(BOOST_LDFLAGS) $(BOOST_THREAD_LIB) -L../.libs/ -lcppa EXAMPLES_LIBS = $(BOOST_LDFLAGS) $(BOOST_THREAD_LIB) -L../.libs/ -lcppa
...@@ -25,4 +27,5 @@ announce_example_3_LDADD = $(EXAMPLES_LIBS) ...@@ -25,4 +27,5 @@ announce_example_3_LDADD = $(EXAMPLES_LIBS)
announce_example_4_LDADD = $(EXAMPLES_LIBS) announce_example_4_LDADD = $(EXAMPLES_LIBS)
announce_example_5_LDADD = $(EXAMPLES_LIBS) announce_example_5_LDADD = $(EXAMPLES_LIBS)
hello_world_example_LDADD = $(EXAMPLES_LIBS) hello_world_example_LDADD = $(EXAMPLES_LIBS)
math_example_LDADD = $(EXAMPLES_LIBS)
#include <string>
#include <iostream>
#include "cppa/cppa.hpp"
using namespace cppa;
void math_actor()
{
receive_loop
(
on<atom("plus"), int, int>() >> [](int a, int b)
{
reply(atom("result"), a + b);
},
on<atom("minus"), int, int>() >> [](int a, int b)
{
reply(atom("result"), a - b);
}
);
}
int main()
{
// create a new actor that invokes the function echo_actor
auto ma = spawn(math_actor);
send(ma, atom("plus"), 1, 2);
receive
(
on<atom("result"), int>() >> [](int result)
{
cout << "1 + 2 = " << result << endl;
}
);
send(ma, atom("minus"), 1, 2);
receive
(
on<atom("result"), int>() >> [](int result)
{
cout << "1 - 2 = " << result << endl;
}
);
// force ma to exit
send(ma, atom(":Exit"), exit_reason::user_defined);
// wait until ma exited
await_all_others_done();
// done
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