\section{Synchronous Communication}
\label{Sec::Sync}

\lib supports both asynchronous and synchronous communication. The latter is provided by the member function \lstinline^sync_send^.

\begin{lstlisting}
template<typename... Args>
__unspecified__ sync_send(actor whom, Args&&... what);
\end{lstlisting}

A synchronous message is sent to the receiving actor's mailbox like any other (asynchronous) message. Only the response message is treated separately.

\subsection{Additional Error Messages}

\begin{lstlisting}
struct sync_exited_msg {
  actor_addr source;
  uint32_t reason;
};
\end{lstlisting}

When using synchronous messaging, \lib's runtime will send a \lstinline^sync_exited_msg^ message if the receiver is not alive. This is in addition to exit and down messages caused by linking or monitoring.

\subsection{Receive Response Messages}

When sending a synchronous message, the response handler can be passed by either using \lstinline^then^ (event-based actors) or \lstinline^await^ (blocking actors).

\begin{lstlisting}
void foo(event_based_actor* self, actor testee) {
  // testee replies with a string to 'get'
  self->sync_send(testee, get_atom::value).then(
    [=](const std::string& str) {
      // handle str
    },
    after(std::chrono::seconds(30)) >> [=]() {
      // handle error
    }
  );
);
\end{lstlisting}

Similar to \lstinline^become^, the \lstinline^then^ function modifies an actor's behavior stack.
However, it is used as ``one-shot handler'' and automatically returns to the previous behavior afterwards.

\clearpage
\subsection{Synchronous Failures and Error Handlers}

An unexpected response message, i.e., a message that is not handled by the ``one-shot-handler'', is considered as an error. The runtime will invoke the actor's \lstinline^on_sync_failure^, which kills the actor by calling \lstinline^self->quit(exit_reason::unhandled_sync_failure)^ per default. The error handler can be overridden by calling \lstinline^self->on_sync_failure(...)^ as shown below.

\begin{lstlisting}
void foo(event_based_actor* self, actor testee) {
  // set handler for unexpected messages
  self->on_sync_failure([=] {
    aout(self) << "received unexpected synchronous response: "
               << to_string(self->last_dequeued()) << endl;
  });
  // set response handler by using "then"
  sync_send(testee, get_atom::value).then(
    [=](const std::string& str) {
      /* handle str */
    }
    // any other result will call the on_sync_failure handler
  );
}
\end{lstlisting}
