Typed Message Views

A message in CAF really is just a type-erased tuple for passing values around. At some point, however, we need to restore the type information to access the stored values. Typed message views are a convenient way to do just that.

For the most part, users can write CAF applications without knowing about message. When sending messages between actors, CAF automatically wraps the content for the message into this type-erased container and then matches each incoming message against the message handlers.

However, there are use cases for message outside of the dispatching logic in CAF. For example, actors can store messages that they currently don't want to (or cannot) process in some cache for processing them later. Or an application could read messages from custom data sources and then deploy on their run-time type.

For such use cases, CAF includes typed message views. On construction, a view performs the necessary type checking. On a match, users can then query individual elements from the view via get<Index>(x), much like the interface offered by std::tuple.

Internally, messages are copy-on-write tuples. Hence, there are two flavors of typed message views: const views that represent read-only access and views with mutable access. The latter forces the message to perform a deep copy of its data if there is more to one reference to the data. To cut a long story short, we recommend sticking to the const version whenever possible.

For both view types, the simplest way of using them is to construct a view object and then check whether it is valid. The const version is called const_typed_message_view:

Source Code

auto msg1 = make_message("hello", "world");
auto msg2 = msg1;
if (auto v = make_const_typed_message_view<std::string, std::string>(msg1))
  println("v: ", get<0>(v), ", ", get<1>(v));
// Both messages still point to the same data.
assert(msg1.cptr() == msg2.cptr());

Output

v: hello, world

The mutable version is simply called typed_message_view, but otherwise has a similar interface:

Source Code

auto msg1 = make_message("hello", "world");
auto msg2 = msg1;
if (auto v = make_typed_message_view<std::string, std::string>(msg1)) {
  get<0>(v) = "bye";
  println("v: ", get<0>(v), ", ", get<1>(v));
}
// The messages no longer point to the same data.
assert(msg1.cptr() != msg2.cptr());

Output

v: bye, world
Next
Next

Message Builders