Commit 82a6511b authored by Dominik Charousset's avatar Dominik Charousset

Fix namespaces and minor mistakes

This patch closes #223 (still using `cppa` namespace) and closes #224 (error in
lambda expression).
parent 3af15a6e
......@@ -18,7 +18,7 @@ self->trap_exit(true);
self->link_to(worker);
// wait until worker exited
self->become (
[](const exit_msg& e) >> [=] {
[=](const exit_msg& e) {
if (e.reason == exit_reason::normal) {
// worker finished computation
else {
......@@ -54,8 +54,8 @@ self->become (
\subsection{Error Codes}
All error codes are defined in the namespace \lstinline^cppa::exit_reason^.
To obtain a string representation of an error code, use \lstinline^cppa::exit_reason::as_string(uint32_t)^.
All error codes are defined in the namespace \lstinline^caf::exit_reason^.
To obtain a string representation of an error code, use \lstinline^caf::exit_reason::as_string(uint32_t)^.
\begin{tabular*}{\textwidth}{m{0.35\textwidth}m{0.08\textwidth}m{0.5\textwidth}}
\hline
......@@ -81,23 +81,24 @@ To obtain a string representation of an error code, use \lstinline^cppa::exit_re
Actors can attach cleanup code to other actors.
This code is executed immediately if the actor has already exited.
Keep in mind that \lstinline^self^ refers to the currently running actor.
Thus, \lstinline^self^ refers to the terminating actor and not to the actor that attached a functor to it.
\begin{lstlisting}
auto worker = spawn(...);
actor observer = self;
// "monitor" spawned actor
worker->attach_functor([observer](std::uint32_t reason) {
// this callback is invoked from worker
anon_send(observer, atom("DONE"));
});
// wait until worker exited
self->become (
on(atom("DONE")) >> [] {
// worker terminated
}
);
using done_atom = atom_constant<atom("done")>;
behavior supervisor(event_based_actor* self, actor worker) {
actor observer = self;
// "monitor" spawned actor
worker->attach_functor([observer](std::uint32_t reason) {
// this callback is invoked from worker
anon_send(observer, done_atom::value);
});
// wait until worker exited
return {
[](done_atom) {
// ... worker terminated ...
}
};
}
\end{lstlisting}
\textbf{Note}: It is possible to attach code to remote actors, but the cleanup code will run on the local machine.
......@@ -3,7 +3,7 @@
\subsection{Class \texttt{option}}
\label{Appendix::Option}
Defined in header \lstinline^"cppa/option.hpp"^.
Defined in header \lstinline^"caf/option.hpp"^.
\begin{lstlisting}
template<typename T>
......@@ -56,8 +56,8 @@ Represents an optional value.
When using \lstinline^cout^ from multiple actors, output often appears interleaved.
Moreover, using \lstinline^cout^ from multiple actors -- and thus from multiple threads -- in parallel should be avoided regardless, since the standard does not guarantee a thread-safe implementation.
By replacing \texttt{std::cout} with \texttt{cppa::aout}, actors can achieve a concurrency-safe text output.
The header \lstinline^cppa/cppa.hpp^ also defines overloads for \texttt{std::endl} and \texttt{std::flush} for \lstinline^aout^, but does not support the full range of ostream operations (yet).
By replacing \texttt{std::cout} with \texttt{caf::aout}, actors can achieve a concurrency-safe text output.
The header \lstinline^caf/all.hpp^ also defines overloads for \texttt{std::endl} and \texttt{std::flush} for \lstinline^aout^, but does not support the full range of ostream operations (yet).
Each write operation to \texttt{aout} sends a message to a `hidden' actor (keep in mind, sending messages from actor constructors is not safe).
This actor only prints lines, unless output is forced using \lstinline^flush^.
The example below illustrates printing of lines of text from multiple actors (in random order).
......@@ -66,9 +66,9 @@ The example below illustrates printing of lines of text from multiple actors (in
#include <chrono>
#include <cstdlib>
#include <iostream>
#include "cppa/cppa.hpp"
#include "caf/all.hpp"
using namespace cppa;
using namespace caf;
using std::endl;
int main() {
......
......@@ -7,11 +7,13 @@ All functions shown in this section can be accessed by including the header \lst
\subsection{Publishing of Actors}
\begin{lstlisting}
uint16_t publish(actor whom, uint16_t port, const char* addr = 0, bool reuse_addr = false)
uint16_t publish(actor whom, uint16_t port,
const char* addr = nullptr,
bool reuse_addr = false)
\end{lstlisting}
The function \lstinline^publish^ binds an actor to a given port.
To choose the next high-level port available available for binding, one can specify \lstinline^port == 0^ and retrieves the bound port as return value.
To choose the next high-level port available for binding, one can specify \lstinline^port == 0^ and retrieves the bound port as return value.
The return value is equal to \lstinline^port^ if \lstinline^port != 0^.
The function throws \lstinline^network_error^ if socket related errors occur or \lstinline^bind_failure^ if the specified port is already in use.
The optional \lstinline^addr^ parameter can be used to listen only to the given address.
......@@ -32,12 +34,14 @@ self->become (
);
\end{lstlisting}
To close a socket, e.g., to allow other actors to be published at the port, the function \lstinline^unpublish^ can be used:
To close a socket, e.g., to allow other actors to be published at the port, the function \lstinline^unpublish^ can be used.
This function is called implicitly if a published actor terminates.
\begin{lstlisting}
void unpublish(caf::actor whom, uint16_t port)
\end{lstlisting}
\clearpage
\subsection{Connecting to Remote Actors}
\begin{lstlisting}
......
\section{Spawning Actors}
Actors are created using the function \lstinline^spawn^.
%The arguments passed to \lstinline^spawn^ depend on the actor's implementation.
%\subsection{Using \lstinline^spawn^ to Create Actors from Functors or Classes}
The easiest way to implement actors is to use functors, e.g., a free function or lambda expression.
The easiest way to implement actors is to use functors, e.g., a free function or a lambda expression.
The arguments to the functor are passed to \lstinline^spawn^ as additional arguments.
The function \lstinline^spawn^ also takes optional flags as template parameter.
%The optional template parameter of \lstinline^spawn^ decides whether an actor should run in its own thread or takes place in the cooperative scheduling.
The flag \lstinline^detached^ causes \lstinline^spawn^ to create a thread-mapped actor (opt-out of the cooperative scheduling), the flag \lstinline^linked^ links the newly created actor to its parent -- not available on top-level spawn -- and the flag \lstinline^monitored^ automatically adds a monitor to the new actor.
Actors that make use of the blocking API (see Section \ref{Sec::BlockingAPI}) must be spawned using the flag \lstinline^blocking_api^.
The flag \lstinline^detached^ causes \lstinline^spawn^ to assign a dedicated thread to the actor, i.e., to opt-out of the cooperative scheduling.
Convenience flags like \lstinline^linked^ or \lstinline^monitored^ automatically link or monitor to the newly created actor.
Naturally, these two flags are not available on ``top-level'' spawns.
Actors that make use of the blocking API---see Section \ref{Sec::BlockingAPI}---must be spawned using the flag \lstinline^blocking_api^.
Flags are concatenated using the operator \lstinline^+^, as shown in the examples below.
\begin{lstlisting}
#include "cppa/cppa.hpp"
using namespace cppa;
#include "caf/all.hpp"
using namespace caf;
void my_actor1();
void my_actor2(event_based_actor*, int arg1, const std::string& arg2);
void ugly_duckling();
void ugly_duckling(blocking_actor*);
class my_actor3 : public event_based_actor { /* ... */ };
class my_actor4 : public sb_actor<my_actor4> {
class my_actor4 : public event_based_actor {
public: my_actor4(int some_value) { /* ... */ }
/* ... */
};
......@@ -30,26 +29,26 @@ class my_actor4 : public sb_actor<my_actor4> {
// we have to spawn it using the self pointer, otherwise
// we can use the free function 'spawn' (top-level spawn)
void server(event_based_actor* self) {
// spawn function-based actors
auto a0 = spawn(my_actor1);
// spawn functor-based actors
auto a0 = self->spawn(my_actor1);
auto a1 = self->spawn<linked>(my_actor2, 42, "hello actor");
auto a2 = self->spawn<monitored>([] { /* ... */ });
auto a3 = spawn([](int) { /* ... */ }, 42);
auto a3 = self->spawn([](int) { /* ... */ }, 42);
// spawn thread-mapped actors
auto a4 = spawn<detached>(my_actor1);
auto a4 = self->spawn<detached>(my_actor1);
auto a5 = self->spawn<detached + linked>([] { /* ... */ });
auto a6 = spawn<detached>(my_actor2, 0, "zero");
auto a6 = self->spawn<detached>(my_actor2, 0, "zero");
// spawn class-based actors
auto a7 = spawn<my_actor3>();
auto a7 = self->spawn<my_actor3>();
auto a8 = self->spawn<my_actor4, monitored>(42);
// spawn thread-mapped actors using a class
auto a9 = spawn<my_actor4, detached>(42);
// spawn and detach class-based actors
auto a9 = self->spawn<my_actor4, detached>(42);
// spawn actors that need access to the blocking API
auto aa = self->spawn<blocking_api>(ugly_duckling);
// compiler error: my_actor2 captures the implicit
// self pointer as event_based_actor* and thus cannot
// be spawned using blocking_api flag
/*-auto ab = self->spawn<blocking_api>(my_actor2);-*/
// be spawned using the `blocking_api` flag
// --- auto ab = self->spawn<blocking_api>(my_actor2);
}
\end{lstlisting}
......
......@@ -10,10 +10,13 @@ Unlike \lstinline^std::type_info::name()^, \lstinline^uniform_type_info::name()^
\begin{lstlisting}
// creates a signed, 32 bit integer
cppa::object i = cppa::uniform_typeid<int>()->create();
uniform_value i = uniform_typeid<int>()->create();
\end{lstlisting}
However, you should rarely if ever need to use \lstinline^object^ or \lstinline^uniform_type_info^.
You should rarely, if ever, need to use \lstinline^uniform_value^ or \lstinline^uniform_type_info^.
The type \lstinline^uniform_value^ stores a type-erased pointer along with the associated \lstinline^uniform_type_info^.
The sole purpose of this simple abstraction is to enable the pattern matching engine of \lib to query the type information and then dispatch the value to a message handler.
When using a \lstinline^message_builder^, each element is stored as a \lstinline^uniform_value^.
\subsection{User-Defined Data Types in Messages}
\label{Sec::TypeSystem::UserDefined}
......@@ -21,20 +24,18 @@ However, you should rarely if ever need to use \lstinline^object^ or \lstinline^
All user-defined types must be explicitly ``announced'' so that \lib can (de)serialize them correctly, as shown in the example below.
\begin{lstlisting}
#include "cppa/cppa.hpp"
using namespace cppa;
#include "caf/all.hpp"
struct foo { int a; int b; };
int main() {
announce<foo>("foo", &foo::a, &foo::b);
caf::announce<foo>("foo", &foo::a, &foo::b);
// ... foo can now safely be used in messages ...
}
\end{lstlisting}
Without the \lstinline^announce^ function call, the example program would terminate with an exception, because \lib rejects all types without available runtime type information.
\lstinline^announce()^ takes the class as template parameter.
Without announcing \lstinline^foo^, \lib is not able to (de)serialize instances of it.
The function \lstinline^announce()^ takes the class as template parameter.
The first argument to the function always is the type name followed by pointers to all members (or getter/setter pairs).
This works for all primitive data types and STL compliant containers.
See the announce examples 1 -- 4 of the standard distribution for more details.
......
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