Commit b26c3212 authored by Dominik Charousset's avatar Dominik Charousset

Update manual: {cppa => caf} and fix examples

parent 4be71478
\section{Management \& Error Detection}
\libcppa adapts Erlang's well-established fault propagation model.
\lib adapts Erlang's well-established fault propagation model.
It allows to build actor subsystem in which either all actors are alive or have collectively failed.
\subsection{Links}
......
\section{Actors}
\libcppa provides several actor implementations, each covering a particular use case.
\lib provides several actor implementations, each covering a particular use case.
The class \lstinline^local_actor^ is the base class for all implementations, except for (remote) proxy actors.
Hence, \lstinline^local_actor^ provides a common interface for actor operations like trapping exit messages or finishing execution.
The default actor implementation in \libcppa is event-based.
The default actor implementation in \lib is event-based.
Event-based actors have a very small memory footprint and are thus very lightweight and scalable.
Context-switching actors are used for actors that make use of the blocking API (see Section \ref{Sec::BlockingAPI}), but do not need to run in a separate thread.
Context-switching and event-based actors are scheduled cooperatively in a thread pool.
......@@ -53,9 +53,9 @@ class local_actor;
\hline
\lstinline^void on_sync_timeout(auto fun)^ & Sets a handler, i.e., a functor taking no arguments, for \lstinline^timed_sync_send^ timeout messages (default action is to kill the actor for reason \lstinline^unhandled_sync_timeout^) \\
\hline
\lstinline^void monitor(actor_ptr whom)^ & Adds a unidirectional monitor to \lstinline^whom^ (see Section \ref{Sec::Management::Monitors}) \\
\lstinline^void monitor(actor whom)^ & Adds a unidirectional monitor to \lstinline^whom^ (see Section \ref{Sec::Management::Monitors}) \\
\hline
\lstinline^void demonitor(actor_ptr whom)^ & Removes a monitor from \lstinline^whom^ \\
\lstinline^void demonitor(actor whom)^ & Removes a monitor from \lstinline^whom^ \\
\hline
\lstinline^bool has_sync_failure_handler()^ & Checks wheter this actor has a user-defined sync failure handler \\
\hline
......
......@@ -91,4 +91,35 @@ int main() {
shutdown();
return 0;
}
\end{lstlisting}
\ No newline at end of file
\end{lstlisting}
\clearpage
\subsection{Migration Guides}
The guides in this section document all possibly breaking changes in the library for that last versions of \lib.
\subsubsection{0.8 $\Rightarrow$ 0.9}
\paragraph{\lstinline^self^ has been removed}
~
This is the biggest library change since the initial release.
The major problem with this keyword-like identifier is that it must have a single type as it's implemented as a thread-local variable.
Since there are so many different kinds of actors (event-based or blocking, untyped or typed), \lstinline^self^ needs to perform type erasure at some point, rendering it ultimately useless.
Instead of a thread-local pointer, you can now use the first argument in functor-based actors to "catch" the self pointer with proper type information.
\paragraph{\lstinline^actor_ptr^ has been replaced}
~
\lib now distinguishes between handles to actors, i.e., \lstinline^typed_actor<...>^ or simply \lstinline^actor^, and \emph{addresses} of actors, i.e., \lstinline^actor_addr^. The reason for this change is that each actor has a logical, (network-wide) unique address, which is used by the networking layer of \lib. Furthermore, for monitoring or linking, the address is all you need. However, the address is not sufficient for sending messages, because it doesn't have any type information. The function \lstinline^last_sender()^ now returns the \emph{address} of the sender.
This means that previously valid code such as \lstinline^send(last_sender(), ...)^ will cause a compiler error.
However, the recommended way of replying to messages is to return the result from the message handler.
\paragraph{The API for typed actors is now similar to the API for untyped actors}
~
The APIs of typed and untyped actors have been harmonized.
Typed actors can now be published in the network and also use all operations untyped actors can.
\section{Blocking API}
\label{Sec::BlockingAPI}
Besides event-based actors (the default implementation), \libcppa also provides context-switching and thread-mapped actors that can make use of the blocking API.
Besides event-based actors (the default implementation), \lib also provides context-switching and thread-mapped actors that can make use of the blocking API.
Those actor implementations are intended to ease migration of existing applications or to implement actors that need to have access to blocking receive primitives for other reasons.
Event-based actors differ in receiving messages from context-switching and thread-mapped actors: the former define their behavior as a message handler that is invoked whenever a new messages arrives in the actor's mailbox (by using \lstinline^become^), whereas the latter use an explicit, blocking receive function.
......@@ -21,7 +21,7 @@ self->receive (
The code snippet above illustrates the use of \lstinline^receive^.
Note that the partial function passed to \lstinline^receive^ is a temporary object at runtime.
Hence, using receive inside a loop would cause creation of a new partial function on each iteration.
\libcppa provides three predefined receive loops to provide a more efficient but yet convenient way of defining receive loops.
\lib provides three predefined receive loops to provide a more efficient but yet convenient way of defining receive loops.
\begin{tabular*}{\textwidth}{p{0.47\textwidth}|p{0.47\textwidth}}
\lstinline^// DON'T^ & \lstinline^// DO^ \\
......
......@@ -44,7 +44,7 @@ However, sharing \textit{data} between actors is fine, as long as the data is \t
The simplest way to meet the lifetime guarantee is by storing the data in smart pointers such as \lstinline^std::shared_ptr^.
Nevertheless, the recommended way of sharing informations is message passing.
Sending data to multiple actors does not necessarily result in copying the data several times.
Read Section \ref{Sec::Tuples} to learn more about \libcppa's copy-on-write optimization for tuples.
Read Section \ref{Sec::Tuples} to learn more about \lib's copy-on-write optimization for tuples.
\end{itemize}
\subsection{Constructors of Class-based Actors}
......
\section{Copy-On-Write Tuples}
\label{Sec::Tuples}
The message passing implementation of \libcppa uses tuples with call-by-value semantic.
Hence, it is not necessary to declare message types, though, \libcppa allows users to use user-defined types in messages (see Section \ref{Sec::TypeSystem::UserDefined}).
The message passing implementation of \lib uses tuples with call-by-value semantic.
Hence, it is not necessary to declare message types, though, \lib allows users to use user-defined types in messages (see Section \ref{Sec::TypeSystem::UserDefined}).
A call-by-value semantic would cause multiple copies of a tuple if it is send to multiple actors.
To avoid unnecessary copying overhead, \libcppa uses a copy-on-write tuple implementation.
To avoid unnecessary copying overhead, \lib uses a copy-on-write tuple implementation.
A tuple is implicitly shared between any number of actors, as long as all actors demand only read access.
Whenever an actor demands write access, it has to copy the data first if more than one reference to it exists.
Thus, race conditions cannot occur and each tuple is copied only if necessary.
......@@ -30,7 +30,7 @@ assert(&get<0>(x1) != &get<0>(x2)); // no longer the same
The class \lstinline^any_tuple^ represents a tuple without static type information.
All messages send between actors use this tuple type.
The type information can be either explicitly accessed for each element or the original tuple, or a subtuple of it, can be restored using \lstinline^tuple_cast^.
Users of \libcppa usually do not need to know about
Users of \lib usually do not need to know about
\lstinline^any_tuple^, since it is used ``behind the scenes''.
However, \lstinline^any_tuple^ can be created from a \lstinline^cow_tuple^
or by using \lstinline^make_any_tuple^, as shown below.
......
......@@ -4,11 +4,11 @@
%\subsection{Some Terminology}
To compile \libcppa, you will need CMake and a C++11 compiler. To get and compile the sources, open a terminal (on Linux or Mac OS X) and type:
To compile \lib, you will need CMake and a C++11 compiler. To get and compile the sources, open a terminal (on Linux or Mac OS X) and type:
\begin{verbatim}
git clone git://github.com/Neverlord/libcppa.git
cd libcppa
git clone https://github.com/actor-framework/actor-framework
cd lib
./configure
make
make install [as root, optional]
......@@ -47,9 +47,9 @@ Please submit a bug report that includes (a) your compiler version, (b) your OS,
\item Linux
\item Mac OS X
\item \textit{Note for MS Windows}:
\libcppa relies on C++11 features such as unrestricted unions.
\lib relies on C++11 features such as unrestricted unions.
We will support this platform as soon as Microsoft's compiler implements all required C++11 features.
In the meantime, libcppa can be used with MinGW.
In the meantime, \lib can be used with MinGW.
\end{itemize*}
\clearpage
......
\section{Group Communication}
\label{Sec::Group}
\libcppa supports publish/subscribe-based group communication.
\lib supports publish/subscribe-based group communication.
Actors can join and leave groups and send messages to groups.
\begin{lstlisting}
......
\section{Introduction}
Before diving into the API of \libcppa, we would like to take the opportunity to discuss the concepts behind \libcppa and to explain the terminology used in this manual.
Before diving into the API of \lib, we would like to take the opportunity to discuss the concepts behind \lib and to explain the terminology used in this manual.
\subsection{Actor Model}
......@@ -15,19 +15,19 @@ Additionally, mutex-based implementations can cause queueing and unmindful acces
The actor model has gained momentum over the last decade due to its high level of abstraction and its ability to make efficient use of multicore and multiprocessor machines.
However, the actor model has not yet been widely adopted in the native programming domain.
With \libcppa, we contribute a library for actor programming in C++ as open source software to ease native development of concurrent as well as distributed systems.
In this regard, \libcppa follows the C++ philosophy ``building the highest abstraction possible without sacrificing performance''.
With \lib, we contribute a library for actor programming in C++ as open source software to ease native development of concurrent as well as distributed systems.
In this regard, \lib follows the C++ philosophy ``building the highest abstraction possible without sacrificing performance''.
\subsection{Terminology}
You will find that \libcppa has not simply adopted exiting implementations based on the actor model such as Erlang or the Akka library.
Instead, \libcppa aims to provide a modern C++ API allowing for type-safe as well as dynamically typed messaging.
You will find that \lib has not simply adopted exiting implementations based on the actor model such as Erlang or the Akka library.
Instead, \lib aims to provide a modern C++ API allowing for type-safe as well as dynamically typed messaging.
Hence, most aspects of our system are familiar to developers having experience with other actor systems, but there are also slight differences in terminology.
However, neither \libcppa nor this manual require any foreknowledge.
However, neither \lib nor this manual require any foreknowledge.
\subsubsection{Actor Address}
In \libcppa, each actor has a (network-wide) unique logical address that can be used to identify and monitor it.
In \lib, each actor has a (network-wide) unique logical address that can be used to identify and monitor it.
However, the address can \emph{not} be used to send a message to an actor.
This limitation is due to the fact that the address does not contain any type information about the actor.
Hence, it would not be safe to send it any message, because the actor might use a strictly typed messaging interface not accepting the given message.
......@@ -36,7 +36,7 @@ Hence, it would not be safe to send it any message, because the actor might use
An actor handle contains the address of an actor along with its type information.
In order to send an actor a message, one needs to have a handle to it -- the address alone is not sufficient.
The distinction between handles and addresses -- which is unique to \libcppa when comparing it to other actor systems -- is a consequence of the design decision to support both untyped and typed actors.
The distinction between handles and addresses -- which is unique to \lib when comparing it to other actor systems -- is a consequence of the design decision to support both untyped and typed actors.
\subsubsection{Untyped Actors}
......@@ -67,4 +67,4 @@ Each actor sends an ``exit message'' to all of its links as part of its terminat
Unlike down messages (cf. \ref{sec:monitoring}), the default behavior for received exit messages causes the receiving actor to terminate for the same reason if the link has failed, i.e., terminated with a non-normal exit reason.
This allows developers to create a set of actors with the guarantee that either all or no actors are alive.
The default behavior can be overridden, i.e., exit message can be ``trapped''.
When trapping exit messages, they are received as any other ordinary message and can be handled by the actor.
\ No newline at end of file
When trapping exit messages, they are received as any other ordinary message and can be handled by the actor.
......@@ -2,7 +2,7 @@
\label{Sec::NetworkIO}
When communicating to other services in the network, sometimes low-level socket IO is inevitable.
For this reason, \libcppa provides \emph{brokers}.
For this reason, \lib provides \emph{brokers}.
A broker is an event-based actor running in the middleman that multiplexes socket IO.
It can maintain any number of acceptors and connections.
Since the broker runs in the middleman, implementations should be careful to consume as little time as possible in message handlers.
......
\section{OpenCL-based Actors}
\libcppa supports transparent integration of OpenCL functions.
\lib supports transparent integration of OpenCL functions.
\begin{lstlisting}
......
\section{Pattern Matching}
\label{Sec::PatternMatching}
C++ does not provide pattern matching facilities.
A general pattern matching solution for arbitrary data structures would require a language extension.
Hence, we decided to restrict our implementation to tuples, to be able to use an internal domain-specific language approach.
Actor programming implies a message passing paradigm.
This means that defining message handlers is a recurring task.
The easiest and most natural way to specify such message handlers is pattern matching.
Unfortunately, C++ does not provide any pattern matching facilities.
%A general pattern matching solution for arbitrary data structures would require a language extension.
Hence, we provide an internal domain-specific language to match incoming messages.
\subsection{Basics}
\label{Sec::PatternMatching::Basics}
......@@ -88,7 +91,7 @@ It cannot determine an operation, such as multiply or add, by receiving two oper
Thus, the operation must be encoded into the message.
The Erlang programming language introduced an approach to use non-numerical
constants, so-called \textit{atoms}, which have an unambiguous, special-purpose type and do not have the runtime overhead of string constants.
Atoms are mapped to integer values at compile time in \libcppa.
Atoms are mapped to integer values at compile time in \lib.
This mapping is guaranteed to be collision-free and invertible, but limits atom literals to ten characters and prohibits special characters.
Legal characters are ``\lstinline[language=C++]^_0-9A-Za-z^'' and the whitespace character.
Atoms are created using the \lstinline^constexpr^ function \lstinline^atom^, as the following example illustrates.
......
......@@ -3,7 +3,7 @@
The current \textit{behavior} of an actor is its response to the \textit{next} incoming message and includes (a) sending messages to other actors, (b) creation of more actors, and (c) setting a new behavior.
An event-based actor, i.e., the default implementation in \libcppa, uses \lstinline^become^ to set its behavior.
An event-based actor, i.e., the default implementation in \lib, uses \lstinline^become^ to set its behavior.
The given behavior is then executed until it is replaced by another call to \lstinline^become^ or the actor finishes execution.
\subsection{Class-based actors}
......@@ -15,7 +15,7 @@ class printer : public event_based_actor {
behavior make_behavior() override {
return {
others() >> [] {
cout << to_string(last_received()) << endl;
cout << to_string(last_dequeued()) << endl;
}
};
}
......@@ -29,7 +29,7 @@ This base class simply returns \lstinline^init_state^ (defined in the subclass)
struct printer : sb_actor<printer> {
behavior init_state {
others() >> [] {
cout << to_string(last_received()) << endl;
cout << to_string(last_dequeued()) << endl;
}
};
};
......@@ -58,12 +58,14 @@ class fixed_stack : public sb_actor<fixed_stack> {
public:
fixed_stack(size_t max) : max_size(max) {
assert(max_size > 0);
full = (
on(atom("push"), arg_match) >> [=](int) { /* discard */ },
on(atom("pop")) >> [=]() -> cow_tuple<atom_value, int> {
on(atom("pop")) >> [=]() -> tuple<atom_value, int> {
auto result = data.back();
data.pop_back();
become(filled);
if (data.empty()) become(empty);
else become(filled);
return {atom("ok"), result};
}
);
......@@ -72,7 +74,7 @@ class fixed_stack : public sb_actor<fixed_stack> {
data.push_back(what);
if (data.size() == max_size) become(full);
},
on(atom("pop")) >> [=]() -> cow_tuple<atom_value, int> {
on(atom("pop")) >> [=]() -> tuple<atom_value, int> {
auto result = data.back();
data.pop_back();
if (data.empty()) become(empty);
......@@ -82,7 +84,8 @@ class fixed_stack : public sb_actor<fixed_stack> {
empty = (
on(atom("push"), arg_match) >> [=](int what) {
data.push_back(what);
become(filled);
if (data.size() == max_size) become(full);
else become(filled);
},
on(atom("pop")) >> [=] {
return atom("failure");
......@@ -125,7 +128,7 @@ An event-based actor finishes execution with normal exit reason if the behavior
The default policy of \lstinline^become^ is \lstinline^discard_behavior^ that causes an actor to override its current behavior.
The policy flag must be the first argument of \lstinline^become^.
\textbf{Note}: the message handling in \libcppa is consistent among all actor implementations: unmatched messages are \textit{never} implicitly discarded if no suitable handler was found.
\textbf{Note}: the message handling in \lib is consistent among all actor implementations: unmatched messages are \textit{never} implicitly discarded if no suitable handler was found.
Hence, the order of arrival is not important in the example above.
This is unlike other event-based implementations of the actor model such as Akka for instance.
......@@ -143,14 +146,14 @@ But often, we need to be able to recover if an expected messages does not arrive
#include <iostream>
#include "cppa/cppa.hpp"
using std::endl;
using endl;
behavior eager_actor(event_based_actor* self) {
return {
[](int i) { /* ... */ },
[](float i) { /* ... */ },
others() >> [] { /* ... */ },
after(std::chrono::seconds(10)) >> [] {
after(chrono::seconds(10)) >> [] {
aout(self) << "received nothing within 10 seconds..." << endl;
// ...
}
......@@ -162,14 +165,14 @@ Callbacks given as timeout handler must have zero arguments.
Any number of patterns can precede the timeout definition, but ``\lstinline^after^'' must always be the final statement.
Using a zero-duration timeout causes the actor to scan its mailbox once and then invoke the timeout immediately if no matching message was found.
\libcppa supports timeouts using \lstinline^minutes^, \lstinline^seconds^, \lstinline^milliseconds^ and \lstinline^microseconds^.
\lib supports timeouts using \lstinline^minutes^, \lstinline^seconds^, \lstinline^milliseconds^ and \lstinline^microseconds^.
However, note that the precision depends on the operating system and your local work load.
Thus, you should not depend on a certain clock resolution.
\clearpage
\subsection{Skipping Messages}
Unmatched messages are skipped automatically by \libcppa's runtime system.
Unmatched messages are skipped automatically by \lib's runtime system.
This is true for \textit{all} actor implementations.
To allow actors to skip messages manually, \lstinline^skip_message^ can be used.
This is in particular useful whenever an actor switches between behaviors, but wants to use a default rule created by \lstinline^others()^ to filter messages that are not handled by any of its behaviors.
......
......@@ -92,4 +92,4 @@ The following diagram illustrates forwarding of a synchronous message from actor
\end{footnotesize}
The forwarding is completely transparent to actor \texttt{C}, since it will see actor \texttt{A} as sender of the message.
However, actor \texttt{A} will see actor \texttt{C} as sender of the response message instead of actor \texttt{B} and thus could recognize the forwarding by evaluating \lstinline^self->last_sender()^.
\ No newline at end of file
However, actor \texttt{A} will see actor \texttt{C} as sender of the response message instead of actor \texttt{B} and thus could recognize the forwarding by evaluating \lstinline^self->last_sender()^.
......@@ -12,7 +12,7 @@ All functions for message passing, linking and monitoring are overloaded to acce
\label{sec:strong:spawn}
Typed actors are spawned using the function \lstinline^spawn_typed^.
The argument to this function call \emph{must} be a match expression as shown in the example below, because the runtime of libcppa needs to evaluate the signature of each message handler.
The argument to this function call \emph{must} be a match expression as shown in the example below, because the runtime of \lib needs to evaluate the signature of each message handler.
\begin{lstlisting}
auto p0 = spawn_typed(
......@@ -24,18 +24,18 @@ auto p0 = spawn_typed(
}
);
// assign to identical type
using full_type = typed_actor_ptr<
using full_type = typed_actor<
replies_to<int, int>::with<double>,
replies_to<double, double>::with<double, double>
>;
full_type p1 = p0;
// assign to subtype
using subtype1 = typed_actor_ptr<
using subtype1 = typed_actor<
replies_to<int, int>::with<double>
>;
subtype1 p2 = p0;
// assign to another subtype
using subtype2 = typed_actor_ptr<
using subtype2 = typed_actor<
replies_to<double, double>::with<double, double>
>;
subtype2 p3 = p0;
......
\section{Synchronous Communication}
\label{Sec::Sync}
\libcppa supports both asynchronous and synchronous communication.
\lib supports both asynchronous and synchronous communication.
The member functions \lstinline^sync_send^ and \lstinline^sync_send_tuple^ send synchronous request messages.
\begin{lstlisting}
template<typename... Args>
__unspecified__ sync_send(actor_ptr whom, Args&&... what);
__unspecified__ sync_send(actor whom, Args&&... what);
__unspecified__ sync_send_tuple(actor_ptr whom, any_tuple what);
__unspecified__ sync_send_tuple(actor whom, any_tuple what);
template<typename Duration, typename... Args>
__unspecified__ timed_sync_send(actor_ptr whom,
__unspecified__ timed_sync_send(actor whom,
Duration timeout,
Args&&... what);
template<typename Duration, typename... Args>
__unspecified__ timed_sync_send_tuple(actor_ptr whom,
__unspecified__ timed_sync_send_tuple(actor whom,
Duration timeout,
any_tuple what);
\end{lstlisting}
......@@ -30,7 +30,7 @@ When using \lstinline^timed_sync_send^ function, \lstinline^after(...)^ statemen
\subsection{Error Messages}
When using synchronous messaging, \libcppa's runtime environment will send ...
When using synchronous messaging, \lib's runtime environment will send ...
\begin{itemize}
\item if the receiver is not alive:\newline\lstinline^sync_exited_msg { actor_addr source; std::uint32_t reason; };^
......@@ -90,7 +90,7 @@ void foo(event_based_actor* self, actor testee) {
\clearpage
\subsubsection{Continuations for Event-based Actors}
\libcppa supports continuations to enable chaining of send/receive statements.
\lib supports continuations to enable chaining of send/receive statements.
The functions \lstinline^then^ returns a helper object offering the member function \lstinline^continue_with^, which takes a functor $f$ without arguments.
After receiving a message, $f$ is invoked if and only if the received messages was handled successfully, i.e., neither \lstinline^sync_failure^ nor \lstinline^sync_timeout^ occurred.
......
\section{Platform-Independent Type System}
\label{Sec::TypeSystem}
\libcppa provides a fully network transparent communication between actors.
Thus, \libcppa needs to serialize and deserialize messages.
\lib provides a fully network transparent communication between actors.
Thus, \lib needs to serialize and deserialize messages.
Unfortunately, this is not possible using the RTTI system of C++.
\libcppa uses its own RTTI based on the class \lstinline^uniform_type_info^, since it is not possible to extend \lstinline^std::type_info^.
\lib uses its own RTTI based on the class \lstinline^uniform_type_info^, since it is not possible to extend \lstinline^std::type_info^.
Unlike \lstinline^std::type_info::name()^, \lstinline^uniform_type_info::name()^ is guaranteed to return the same name on all supported platforms. Furthermore, it allows to create an instance of a type by name.
......@@ -18,7 +18,7 @@ However, you should rarely if ever need to use \lstinline^object^ or \lstinline^
\subsection{User-Defined Data Types in Messages}
\label{Sec::TypeSystem::UserDefined}
All user-defined types must be explicitly ``announced'' so that \libcppa can (de)serialize them correctly, as shown in the example below.
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"
......@@ -32,7 +32,7 @@ int main() {
}
\end{lstlisting}
Without the \lstinline^announce^ function call, the example program would terminate with an exception, because \libcppa rejects all types without available runtime type information.
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 and pointers to all members (or getter/setter pairs) as arguments.
This works for all primitive data types and STL compliant containers.
......@@ -40,4 +40,4 @@ See the announce examples 1 -- 4 of the standard distribution for more details.
Obviously, there are limitations.
You have to implement serialize/deserialize by yourself if your class does implement an unsupported data structure.
See \lstinline^announce_example_5.cpp^ in the examples folder.
\ No newline at end of file
See \lstinline^announce_example_5.cpp^ in the examples folder.
......@@ -37,15 +37,15 @@
\definecolor{darkblue}{rgb}{0,0,0.5}
\definecolor{darkgreen}{rgb}{0,0.5,0}
\newcommand{\libcppa}{\textit{libcppa}\xspace}
\pagenumbering{arabic}
\input{variables}
\title{%
%BEGIN LATEX
\texttt{\huge{\textbf{libcppa}}}\\~\\A C++ library for actor programming\\~\\~\\~\\%
\libtitle
%END LATEX
User Manual\\\normalsize{\texttt{libcppa} version 0.9.4}\vfill}
\libsubtitle}
\author{Dominik Charousset}
......@@ -114,7 +114,6 @@ User Manual\\\normalsize{\texttt{libcppa} version 0.9.4}\vfill}
% content
\include{Introduction}
\include{FirstSteps}
\include{CopyOnWriteTuples}
\include{PatternMatching}
\include{Actors}
\include{SendingMessages}
......
\newcommand{\lib}{\texttt{libcaf}\xspace}
\newcommand{\libtitle}{%
\texttt{\huge{\textbf{\lib}}}\\~\\A C++ library for actor programming\\~\\~\\~\\%
}
\newcommand{\libsubtitle}{%
User Manual\\\normalsize{\lib version 0.10}\vfill%
}
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