Copy-on-write Tuples
Copy-on-write (COW) tuples make passing values around cheap while also making sure that the system copies the actual data only when necessary.
CAF uses copy-on-write for its message
type, which basically is a type-erased
tuple. This allows actors to send the same message to multiple recipients
(usually by sending it to publish/subscribe group) without storing the content
in memory multiple times. CAF also includes cow_tuple
which is a
std::tuple
-like type to wrap potentially expensive data (like strings and
lists) into a single unit that actors can pass around cheaply.
Here is a small example to illustrate the API:
Source Code
auto xs = caf::make_cow_tuple(1, 2, 3);
auto ys = xs;
println("After initializing:");
println("xs: ", xs, " (", std::addressof(xs.data()), ")");
println("ys: ", ys, " (", std::addressof(ys.data()), ")");
ys.unshared() = std::tuple{10, 20, 30};
println("After assigning to ys:");
println("xs: ", xs, " (", std::addressof(xs.data()), ")");
println("ys: ", ys, " (", std::addressof(ys.data()), ")");
Output
After initializing:
xs: [1, 2, 3] (0x7fb091405ae0)
ys: [1, 2, 3] (0x7fb091405ae0)
After assigning to ys:
xs: [1, 2, 3] (0x7fb091405ae0)
ys: [10, 20, 30] (0x7fb091405b00)
By default, cow_tuple
only grants const
access to its elements. With
get<I>(xs)
, users can get access to a single value of xs
at the index I
.
With xs.data()
, users get a const
reference to the internally stored
std::tuple
.
In order to gain mutable access, users may call unshared()
to get a mutable
reference to the std::tuple
. This function makes a deep copy of the data if
there is more than one reference to the data at the moment. In our example
above, ys
initially points to the same data as xs
. After calling
unshared()
on ys
, however, the two tuples point to different data.