Messages in CAF are stored in type-erased tuples. The actual message type itself is usually hidden, as actors use pattern matching to decompose messages automatically. However, the classes message and message_builder allow more advanced use cases than only sending data from one actor to another.

The interface type_erased_tuple encapsulates access to arbitrary data. This data can be stored on the heap or on the stack. A message is a type-erased tuple that is always heap-allocated and uses copy-on-write semantics. When dealing with “plain” type-erased tuples, users are required to check if a tuple is referenced by others via type_erased_tuple::shared before modifying its content.

The convenience class message_view holds a reference to either a stack-located type_erased_tuple or a message. The content of the data can be access via message_view::content in both cases, which returns a type_erased_tuple&. The content of the view can be forced into a message object by calling message_view::move_content_to_message. This member function either returns the stored message object or moves the content of a stack-allocated tuple into a new message.

All builtin types in CAF have a non-zero 6-bit type number. All user-defined types are mapped to 0. When querying the run-time type information (RTTI) for individual message or tuple elements, CAF returns a std::pair<uint16_t,conststd::type_info*>. The first value is the 6-bit type number. If the type number is non-zero, the second value is a pointer to the C++ type info, otherwise the second value is null. Additionally, CAF generates 32 bit type tokens. These tokens are type hints that summarizes all types in a type-erased tuple. Two type-erased tuples are of different type if they have different type tokens (the reverse is not true).

The class message includes all member functions of type_erased_tuple. However, calling modifiers is always guaranteed to be safe. A message automatically detaches its content by copying it from the shared data on mutable access. The class further adds the following member functions over type_erased_tuple. Note that apply only detaches the content if a callback takes mutable references as arguments.

ll Observers &

messagedrop(size_tn) & Creates a new message with all but the first n values.

messagedrop_right(size_tn) & Creates a new message with all but the last n values.

messagetake(size_tn) & Creates a new message from the first n values.

messagetake_right(size_tn) & Creates a new message from the last n values.

The member function message::extract removes matched elements from a message. x Messages are filtered by repeatedly applying a message handler to the greatest remaining slice, whereas slices are generated in the sequence [0,size), [0,size-1), ..., [1,size-1), ..., [size-1,size). Whenever a slice is matched, it is removed from the message and the next slice starts at the same index on the reduced message.

Slice 7 is (4), i.e., does not contain the first element, because the match on slice 6 occurred at index position 1. The function extract iterates a message only once, from left to right. The returned message contains the remaining, i.e., unmatched, elements.