.. _actor:

Actors
======

Actors in CAF represent a lightweight abstraction for units of computations.
They are active objects in the sense that they own their state and do not allow
others to access it. The only way to modify the state of an actor is sending
messages to it.

CAF provides several actor implementations, each covering a particular use
case. The available implementations differ in three characteristics:

#. dynamically or statically typed
#. class-based or function-based
#. using asynchronous event handlers or blocking receives

These three characteristics can be combined freely, with one exception:
statically typed actors are always event-based. For example, an actor can have
dynamically typed messaging, implement a class, and use blocking receives. The
common base class for all user-defined actors is called ``local_actor``.

Dynamically typed actors are more familiar to developers coming from Erlang or
Akka. They (usually) enable faster prototyping but require extensive unit
testing. Statically typed actors require more source code but enable the
compiler to verify communication between actors. Since CAF supports both,
developers can freely mix both kinds of actors to get the best of both worlds.
A good rule of thumb is to make use of static type checking for actors that are
visible across multiple translation units.

Actors that utilize the blocking receive API always require an exclusive thread
of execution. Event-based actors, on the other hand, are usually scheduled
cooperatively and are very lightweight with a memory footprint of only few
hundred bytes. Developers can exclude (detach) event-based actors that
potentially starve others from the cooperative scheduling while spawning it. A
detached actor lives in its own thread of execution.

.. _actor-system:

Environment / Actor Systems
---------------------------

All actors live in an ``actor_system`` representing an actor environment
including :ref:`scheduler`, :ref:`registry`, and optional components (modules)
such as a :ref:`middleman`. A single process can have multiple ``actor_system``
instances, but this is usually not recommended (a use case for multiple systems
is to strictly separate two or more sets of actors by running them in different
schedulers). For configuration and fine-tuning options of actor systems see
:ref:`system-config`. A distributed CAF application consists of two or more
connected actor systems. We also refer to interconnected ``actor_system``
instances as a *distributed actor system*.

Common Actor Base Types
-----------------------

The following pseudo-UML depicts the class diagram for actors in CAF.
Irrelevant member functions and classes as well as mixins are omitted for
brevity. Selected individual classes are presented in more detail in the
following sections.

.. _actor-types:

.. image:: actor_types.png
   :alt: Actor Types in CAF

Class ``local_actor``
~~~~~~~~~~~~~~~~~~~~~

The class ``local_actor`` is the root type for all user-defined actors
in CAF. It defines all common operations. However, users of the library
usually do not inherit from this class directly. Proper base classes for
user-defined actors are ``event_based_actor`` or
``blocking_actor``. The following table also includes member function
inherited from ``monitorable_actor`` and ``abstract_actor``.

+-------------------------------------+--------------------------------------------------------+
| **Types**                                                                                    |
+-------------------------------------+--------------------------------------------------------+
| ``mailbox_type``                    | A concurrent, many-writers-single-reader queue type.   |
+-------------------------------------+--------------------------------------------------------+
| **Constructors**                                                                             |
+-------------------------------------+--------------------------------------------------------+
| ``(actor_config&)``                 | Constructs the actor using a config.                   |
+-------------------------------------+--------------------------------------------------------+
| **Observers**                                                                                |
+-------------------------------------+--------------------------------------------------------+
| ``actor_addr address()``            | Returns the address of this actor.                     |
+-------------------------------------+--------------------------------------------------------+
| ``actor_system& system()``          | Returns ``context()->system()``.                       |
+-------------------------------------+--------------------------------------------------------+
| ``actor_system& home_system()``     | Returns the system that spawned this actor.            |
+-------------------------------------+--------------------------------------------------------+
| ``execution_unit* context()``       | Returns underlying thread or current scheduler worker. |
+-------------------------------------+--------------------------------------------------------+
| **Customization Points**                                                                     |
+-------------------------------------+--------------------------------------------------------+
| ``on_exit()``                       | Performs cleanup steps.                                |
+-------------------------------------+--------------------------------------------------------+
| ``initialize()``                    | Installs an initial behavior.                          |
+-------------------------------------+--------------------------------------------------------+
| ``const char* name()``              | Returns a debug name for this actor type.              |
+-------------------------------------+--------------------------------------------------------+
| **Actor Management**                                                                         |
+-------------------------------------+--------------------------------------------------------+
| ``link_to(other)``                  | Links to ``other`` (see :ref:`link`).                  |
+-------------------------------------+--------------------------------------------------------+
| ``unlink_from(other)``              | Remove the link to ``other``.                          |
+-------------------------------------+--------------------------------------------------------+
| ``monitor(other)``                  | Adds a monitor to ``other`` (see :ref:`monitor`).      |
+-------------------------------------+--------------------------------------------------------+
| ``demonitor(other)``                | Removes a monitor from ``whom``.                       |
+-------------------------------------+--------------------------------------------------------+
| ``spawn(F fun, xs...)``             | Spawns a new actor from ``fun``.                       |
+-------------------------------------+--------------------------------------------------------+
| ``spawn<T>(xs...)``                 | Spawns a new actor of type ``T``.                      |
+-------------------------------------+--------------------------------------------------------+
| **Message Processing**                                                                       |
+-------------------------------------+--------------------------------------------------------+
| ``T make_response_promise<Ts...>()``| Allows an actor to delay its response message.         |
+-------------------------------------+--------------------------------------------------------+
| ``T response(xs...)``               | Convenience function for creating fulfilled promises.  |
+-------------------------------------+--------------------------------------------------------+

Class ``scheduled_actor``
~~~~~~~~~~~~~~~~~~~~~~~~~

All scheduled actors inherit from ``scheduled_actor``. This includes
statically and dynamically typed event-based actors as well as brokers
:ref:`broker`.

+-------------------------------+--------------------------------------------------------------------------+
| **Types**                                                                                                |
+-------------------------------+--------------------------------------------------------------------------+
| ``pointer``                   | ``scheduled_actor*``                                                     |
+-------------------------------+--------------------------------------------------------------------------+
| ``exception_handler``         | ``function<error (pointer, std::exception_ptr&)>``                       |
+-------------------------------+--------------------------------------------------------------------------+
| ``default_handler``           | ``function<result<message> (pointer, message_view&)>``                   |
+-------------------------------+--------------------------------------------------------------------------+
| ``error_handler``             | ``function<void (pointer, error&)>``                                     |
+-------------------------------+--------------------------------------------------------------------------+
| ``down_handler``              | ``function<void (pointer, down_msg&)>``                                  |
+-------------------------------+--------------------------------------------------------------------------+
| ``exit_handler``              | ``function<void (pointer, exit_msg&)>``                                  |
+-------------------------------+--------------------------------------------------------------------------+
| **Constructors**                                                                                         |
+-------------------------------+--------------------------------------------------------------------------+
| ``(actor_config&)``           | Constructs the actor using a config.                                     |
+-------------------------------+--------------------------------------------------------------------------+
| **Termination**                                                                                          |
+-------------------------------+--------------------------------------------------------------------------+
| ``quit()``                    | Stops this actor with normal exit reason.                                |
+-------------------------------+--------------------------------------------------------------------------+
| ``quit(error x)``             | Stops this actor with error ``x``.                                       |
+-------------------------------+--------------------------------------------------------------------------+
| **Special-purpose Handlers**                                                                             |
+-------------------------------+--------------------------------------------------------------------------+
| ``set_exception_handler(F f)``| Installs ``f`` for converting exceptions to errors (see :ref:`error`).   |
+-------------------------------+--------------------------------------------------------------------------+
| ``set_down_handler(F f)``     | Installs ``f`` to handle down messages (see :ref:`down-message`).        |
+-------------------------------+--------------------------------------------------------------------------+
| ``set_exit_handler(F f)``     | Installs ``f`` to handle exit messages (see :ref:`exit-message`).        |
+-------------------------------+--------------------------------------------------------------------------+
| ``set_error_handler(F f)``    | Installs ``f`` to handle error messages (see :ref:`error-message`).      |
+-------------------------------+--------------------------------------------------------------------------+
| ``set_default_handler(F f)``  | Installs ``f`` as fallback message handler (see :ref:`default-handler`). |
+-------------------------------+--------------------------------------------------------------------------+

Class ``blocking_actor``
~~~~~~~~~~~~~~~~~~~~~~~~

A blocking actor always lives in its own thread of execution. They are not as
lightweight as event-based actors and thus do not scale up to large numbers.
The primary use case for blocking actors is to use a ``scoped_actor``
for ad-hoc communication to selected actors. Unlike scheduled actors, CAF does
**not** dispatch system messages to special-purpose handlers. A blocking
actors receives *all* messages regularly through its mailbox. A blocking
actor is considered *done* only after it returned from ``act`` (or
from the implementation in function-based actors). A ``scoped_actor``
sends its exit messages as part of its destruction.

+-----------------------------------+---------------------------------------------------+
| **Constructors**                                                                      |
+-----------------------------------+---------------------------------------------------+
| ``(actor_config&)``               | Constructs the actor using a config.              |
+-----------------------------------+---------------------------------------------------+
| **Customization Points**                                                              |
+-----------------------------------+---------------------------------------------------+
| ``void act()``                    | Implements the behavior of the actor.             |
+-----------------------------------+---------------------------------------------------+
| **Termination**                                                                       |
+-----------------------------------+---------------------------------------------------+
| ``const error& fail_state()``     | Returns the current exit reason.                  |
+-----------------------------------+---------------------------------------------------+
| ``fail_state(error x)``           | Sets the current exit reason.                     |
+-----------------------------------+---------------------------------------------------+
| **Actor Management**                                                                  |
+-----------------------------------+---------------------------------------------------+
| ``wait_for(Ts... xs)``            | Blocks until all actors ``xs...`` are done.       |
+-----------------------------------+---------------------------------------------------+
| ``await_all_other_actors_done()`` | Blocks until all other actors are done.           |
+-----------------------------------+---------------------------------------------------+
| **Message Handling**              |                                                   |
+-----------------------------------+---------------------------------------------------+
| ``receive(Ts... xs)``             | Receives a message using the callbacks ``xs...``. |
+-----------------------------------+---------------------------------------------------+
| ``receive_for(T& begin, T end)``  | See :ref:`receive-loop`.                          |
+-----------------------------------+---------------------------------------------------+
| ``receive_while(F stmt)``         | See :ref:`receive-loop`.                          |
+-----------------------------------+---------------------------------------------------+
| ``do_receive(Ts... xs)``          | See :ref:`receive-loop`.                          |
+-----------------------------------+---------------------------------------------------+

.. _interface:

Messaging Interfaces
--------------------

Statically typed actors require abstract messaging interfaces to allow the
compiler to type-check actor communication. Interfaces in CAF are defined using
the variadic template ``typed_actor<...>``, which defines the proper
actor handle at the same time. Each template parameter defines one
``input/output`` pair via
``replies_to<X1,...,Xn>::with<Y1,...,Yn>``. For inputs that do not
generate outputs, ``reacts_to<X1,...,Xn>`` can be used as shortcut for
``replies_to<X1,...,Xn>::with<void>``. In the same way functions cannot
be overloaded only by their return type, interfaces cannot accept one input
twice (possibly mapping it to different outputs). The example below defines a
messaging interface for a simple calculator.

.. literalinclude:: /examples/message_passing/calculator.cpp
   :language: C++
   :start-after: --(rst-actor-begin)--
   :end-before: --(rst-actor-end)--

It is not required to create a type alias such as ``calculator_actor``,
but it makes dealing with statically typed actors much easier. Also, a central
alias definition eases refactoring later on.

Interfaces have set semantics. This means the following two type aliases
``i1`` and ``i2`` are equal:

.. code-block:: C++

   using i1 = typed_actor<replies_to<A>::with<B>, replies_to<C>::with<D>>;
   using i2 = typed_actor<replies_to<C>::with<D>, replies_to<A>::with<B>>;

Further, actor handles of type ``A`` are assignable to handles of type
``B`` as long as ``B`` is a subset of ``A``.

For convenience, the class ``typed_actor<...>`` defines the member
types shown below to grant access to derived types.

+------------------------+---------------------------------------------------------------+
| **Types**              |                                                               |
+------------------------+---------------------------------------------------------------+
| ``behavior_type``      | A statically typed set of message handlers.                   |
+------------------------+---------------------------------------------------------------+
| ``base``               | Base type for actors, i.e., ``typed_event_based_actor<...>``. |
+------------------------+---------------------------------------------------------------+
| ``pointer``            | A pointer of type ``base*``.                                  |
+------------------------+---------------------------------------------------------------+
| ``stateful_base<T>``   | See stateful-actor_.                                          |
+------------------------+---------------------------------------------------------------+
| ``stateful_pointer<T>``| A pointer of type ``stateful_base<T>*``.                      |
+------------------------+---------------------------------------------------------------+
| ``extend<Ts...>``      | Extend this typed actor with ``Ts...``.                       |
+------------------------+---------------------------------------------------------------+
| ``extend_with<Other>`` | Extend this typed actor with all cases from ``Other``.        |
+------------------------+---------------------------------------------------------------+

.. _spawn:

Spawning Actors
---------------

Both statically and dynamically typed actors are spawned from an
``actor_system`` using the member function ``spawn``. The
function either takes a function as first argument or a class as first template
parameter. For example, the following functions and classes represent actors.

.. literalinclude:: /examples/message_passing/calculator.cpp
   :language: C++
   :start-after: --(rst-fwd-begin)--
   :end-before: --(rst-fwd-end)--

Spawning an actor for each implementation is illustrated below.

.. literalinclude:: /examples/message_passing/calculator.cpp
   :language: C++
   :start-after: --(rst-spawn-begin)--
   :end-before: --(rst-spawn-end)--

Additional arguments to ``spawn`` are passed to the constructor of a class or
used as additional function arguments, respectively. In the example above, none
of the three functions takes any argument other than the implicit (optional)
``self`` pointer.

.. _function-based:

Function-based Actors
---------------------

When using a function or function object to implement an actor, the first
argument *can* be used to capture a pointer to the actor itself. The type
of this pointer is usually ``event_based_actor*`` or
``blocking_actor*``. The proper pointer type for any
``typed_actor`` handle ``T`` can be obtained via
``T::pointer`` (see :ref:`interface`).

Blocking actors simply implement their behavior in the function body. The actor
is done once it returns from that function.

Event-based actors can either return a ``behavior`` (see :ref:`message-handler`)
that is used to initialize the actor or explicitly set the initial behavior by
calling ``self->become(...)``. Due to the asynchronous, event-based nature of
this kind of actor, the function usually returns immediately after setting a
behavior (message handler) for the *next* incoming message. Hence, variables on
the stack will be out of scope once a message arrives. Managing state in
function-based actors can be done either via rebinding state with ``become``,
using heap-located data referenced via ``std::shared_ptr`` or by using the
*stateful actor* abstraction (see :ref:`stateful-actor`).

The following three functions implement the prototypes shown in spawn_ and
illustrate one blocking actor and two event-based actors (statically and
dynamically typed).

.. literalinclude:: /examples/message_passing/calculator.cpp
   :language: C++
   :start-after: --(rst-funs-begin)--
   :end-before: --(rst-funs-end)--

.. _class-based:

Class-based Actors
------------------

Implementing an actor using a class requires the following:

* Provide a constructor taking a reference of type  ``actor_config&`` as first
  argument, which is forwarded to the base  class. The config is passed
  implicitly to the constructor when calling  ``spawn``, which also forwards any
  number of additional arguments  to the constructor.
* Override ``make_behavior`` for event-based actors and  ``act`` for blocking
  actors.

Implementing actors with classes works for all kinds of actors and allows
simple management of state via member variables. However, composing states via
inheritance can get quite tedious. For dynamically typed actors, composing
states is particularly hard, because the compiler cannot provide much help.

The following three classes implement the prototypes shown in :ref:`spawn` and
again feature one blocking actor and two event-based actors (statically and
dynamically typed).

.. literalinclude:: /examples/message_passing/calculator.cpp
   :language: C++
   :start-after: --(rst-classes-begin)--
   :end-before: --(rst-classes-end)--

.. _stateful-actor:

Stateful Actors
---------------

The stateful actor API makes it easy to maintain state in function-based
actors. It is also safer than putting state in member variables, because the
state ceases to exist after an actor is done and is not delayed until the
destructor runs. For example, if two actors hold a reference to each other via
member variables, they produce a cycle and neither will get destroyed. Using
stateful actors instead breaks the cycle, because references are destroyed when
an actor calls ``self->quit()`` (or is killed externally). The
following example illustrates how to implement stateful actors with static
typing as well as with dynamic typing.

.. literalinclude:: /examples/message_passing/cell.cpp
   :language: C++
   :start-after: --(rst-cell-begin)--
   :end-before: --(rst-cell-end)--

Stateful actors are spawned in the same way as any other function-based actor
(see :ref:`function-based`).

.. _attach:

Attaching Cleanup Code to Actors
--------------------------------

Users can attach cleanup code to actors. This code is executed immediately if
the actor has already exited. Otherwise, the actor will execute it as part of
its termination. The following example attaches a function object to actors for
printing a custom string on exit.

.. literalinclude:: /examples/broker/simple_broker.cpp
   :language: C++
   :start-after: --(rst-attach-begin)--
   :end-before: --(rst-attach-end)--

It is possible to attach code to remote actors. However, the cleanup code will
run on the local machine.

.. _blocking-actor:

Blocking Actors
---------------

Blocking actors always run in a separate thread and are not scheduled by CAF.
Unlike event-based actors, blocking actors have explicit, blocking *receive*
functions. Further, blocking actors do not handle system messages automatically
via special-purpose callbacks (see :ref:`special-handler`). This gives users
full control over the behavior of blocking actors. However, blocking actors
still should follow conventions of the actor system. For example, actors should
unconditionally terminate after receiving an ``exit_msg`` with reason
``exit_reason::kill``.

Receiving Messages
~~~~~~~~~~~~~~~~~~

The function ``receive`` sequentially iterates over all elements in the
mailbox beginning with the first. It takes a message handler that is applied to
the elements in the mailbox until an element was matched by the handler. An
actor calling ``receive`` is blocked until it successfully dequeued a
message from its mailbox or an optional timeout occurs. Messages that are not
matched by the behavior are automatically skipped and remain in the mailbox.

.. code-block:: C++

   self->receive (
     [](int x) { /* ... */ }
   );

.. _catch-all:

Catch-all Receive Statements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Blocking actors can use inline catch-all callbacks instead of setting a default
handler (see :ref:`default-handler`). A catch-all case must be the last callback
before the optional timeout, as shown in the example below.

.. code-block:: C++

   self->receive(
     [&](float x) {
       // ...
     },
     [&](const down_msg& x) {
       // ...
     },
     [&](const exit_msg& x) {
       // ...
     },
     others >> [](message_view& x) -> result<message> {
       // report unexpected message back to client
       return sec::unexpected_message;
     }
   );

.. _receive-loop:

Receive Loops
~~~~~~~~~~~~~

Message handler passed to ``receive`` are temporary object at runtime.
Hence, calling ``receive`` inside a loop creates an unnecessary amount
of short-lived objects. CAF provides predefined receive loops to allow for
more efficient code.

.. code-block:: C++

   // BAD
   std::vector<int> results;
   for (size_t i = 0; i < 10; ++i)
     receive (
       [&](int value) {
         results.push_back(value);
       }
     );

   // GOOD
   std::vector<int> results;
   size_t i = 0;
   receive_for(i, 10) (
     [&](int value) {
       results.push_back(value);
     }
   );


.. code-block:: C++

   // BAD
   size_t received = 0;
   while (received < 10) {
     receive (
       [&](int) {
         ++received;
       }
     );
   } ;

   // GOOD
   size_t received = 0;
   receive_while([&] { return received < 10; }) (
     [&](int) {
       ++received;
     }
   );

.. code-block:: C++

   // BAD
   size_t received = 0;
   do {
     receive (
       [&](int) {
         ++received;
       }
     );
   } while (received < 10);

   // GOOD
   size_t received = 0;
   do_receive (
     [&](int) {
       ++received;
     }
   ).until([&] { return received >= 10; });

The examples above illustrate the correct usage of the three loops
``receive_for``, ``receive_while`` and ``do_receive(...).until``. It is possible
to nest receives and receive loops.

.. code-block:: C++

   bool running = true;
   self->receive_while([&] { return running; }) (
     [&](int value1) {
       self->receive (
         [&](float value2) {
           aout(self) << value1 << " => " << value2 << endl;
         }
       );
     },
     // ...
   );

.. _scoped-actors:

Scoped Actors
~~~~~~~~~~~~~

The class ``scoped_actor`` offers a simple way of communicating with CAF actors
from non-actor contexts. It overloads ``operator->`` to return a
``blocking_actor*``. Hence, it behaves like the implicit ``self`` pointer in
functor-based actors, only that it ceases to exist at scope end.

.. code-block:: C++

   void test(actor_system& system) {
     scoped_actor self{system};
     // spawn some actor
     auto aut = self->spawn(my_actor_impl);
     self->send(aut, "hi there");
     // self will be destroyed automatically here; any
     // actor monitoring it will receive down messages etc.
   }
