\item C++ evaluates comma-separated expressions from left-to-right, using only the last element as return type of the whole expression. This means that message handlers and behaviors must \emph{not} be initialized like this:
\begin{lstlisting}
message_handler wrong = (
[](int i) { /*...*/ },
[](float f) { /*...*/ }
);
\end{lstlisting}
The correct way to initialize message handlers and behaviors is to either use the constructor or the member function \lstinline^assign^:
\begin{lstlisting}
message_handler ok1{
[](int i) { /*...*/ },
[](float f) { /*...*/ }
};
message_handler ok2;
// some place later
ok2.assign(
[](int i) { /*...*/ },
[](float f) { /*...*/ }
);
\end{lstlisting}
\end{itemize}
\subsection{Event-Based API}
\subsection{Event-Based API}
\begin{itemize}
\begin{itemize}
...
@@ -15,7 +41,6 @@ Thus, one should \textit{always} capture by value in lambda expressions, because
...
@@ -15,7 +41,6 @@ Thus, one should \textit{always} capture by value in lambda expressions, because
\item
\item
A handle returned by \lstinline^sync_send^ represents \emph{exactly one} response message.
A handle returned by \lstinline^sync_send^ represents \emph{exactly one} response message.
Therefore, it is not possible to receive more than one response message.
Therefore, it is not possible to receive more than one response message.
%Calling \lstinline^reply^ more than once will result in lost messages and calling \lstinline^handle_response^ or \lstinline^receive_response^ more than once on a future will throw an exception.
\item
\item
The handle returned by \lstinline^sync_send^ is bound to the calling actor.
The handle returned by \lstinline^sync_send^ is bound to the calling actor.
...
@@ -23,6 +48,7 @@ It is not possible to transfer a handle to a response to another actor.
...
@@ -23,6 +48,7 @@ It is not possible to transfer a handle to a response to another actor.
Messages in \lib are type-erased, copy-on-write tuples.
The actual message type itself is usually hidden, as actors use pattern matching to decompose messages automatically.
However, the classes \lstinline^message^ and \lstinline^message_builder^ allow more advanced usage scenarios than only sending data from one actor to another.
\lstinline^message move_to_message()^& Transfers ownership of its data to the new message \textbf{Warning}: this function leaves the builder in an \emph{invalid state}, i.e., calling any member function on it afterwards is undefined behavior \\
\hline
\end{tabular*}
}
\clearpage
\subsection{Filtering}
\label{Sec::Messages::Filter}
Messages are filtered by repeatedly applying a message handler to the greatest remaining slice, whereas slices are generated in the sequence \lstinline^[0, size)^, \lstinline^[0, size-1)^, \lstinline^...^, \lstinline^[1, size-1)^, \lstinline^...^, \lstinline^[size-1, size)^.
Whenever a slice matches, it is removed from the message and the next slice starts at the same index on the reduced message.
For example:
\begin{lstlisting}
auto msg = make_message(1, 2.f, 3.f, 4);
// filter float and integer pairs
auto msg2 = msg.filter({
[](float, float) {},
[](int, int) {}
});
assert(msg2 == make_message(1, 4));
\end{lstlisting}
Step-by-step explanation:
\begin{itemize}
\item Slice 1: \lstinline^(1, 2.f, 3.f, 4)^, no match
\item Slice 2: \lstinline^(1, 2.f, 3.f)^, no match
\item Slice 3: \lstinline^(1, 2.f)^, no match
\item Slice 4: \lstinline^(1)^, no match
\item Slice 5: \lstinline^(2.f, 3.f, 4)^, no match
\item Slice 6: \lstinline^(2.f, 3.f)^, \emph{match}; new message is \lstinline^(1, 4)^
\item Slice 7: \lstinline^(4)^, no match
\end{itemize}
Slice 7 is \lstinline^(4)^, i.e., does not contain the first element, because the match on slice 6 occurred at index position 1. The function filter iterates a message only once, from left to right. The result of \lstinline^message::filter^ is the remainder, i.e., a message consisting of all unmatched elements.
\clearpage
\subsection{Filter and Command Line Arguments}
\label{Sec::Messages::FilterCLI}
The class \lstinline^message^ also contains a convenience interface to \lstinline^filter^ for parsing command line arguments: \lstinline^filter_cli^.
This member function provides a simplistic interface for defining a command line argument parsers:
\begin{lstlisting}
int main(int argc, char** argv) {
uint16_t port;
string host = "localhost";
auto res = message_builder(argv + 1, argv + argc).filter_cli({