Skip to content

Unifying serialize and to_string #470

Description

@Neverlord

CAF is currently littered with redundant code to enable serialization and
string conversion for its custom types.

Current Approach

Currently, CAF requires serializable types to provide a free function
serialize. Any type convertible to string is required to provide a free
to_string function:

/// Stores a flow-control configuration.
struct named_actor_config {
  atom_value strategy;
  size_t low_watermark;
  size_t max_pending;
};

template <class Processor>
void serialize(Processor& proc, named_actor_config& x, const unsigned int) {
  proc & x.strategy;
  proc & x.low_watermark;
  proc & x.max_pending;
}

inline std::string to_string(const named_actor_config& x) {
  return "named_actor_config"
         + deep_to_string_as_tuple(x.strategy, x.low_watermark, x.max_pending);
}

Both of these function inspect an object and expose state to the caller.

Generalized Approach

When extending the current system with new type concepts such as parseable,
developers are required to implement one free function per concept per type.
This clearly does not scale. This proposal suggests a general-purpose reflect
function that allows a "mirror" object to visit state as well as meta
information. Different mirrors can ignore meta information in contexts where
they are not required. For example, a serializer can ignore meta information
that is always equal for all instances of an object such as class names.

The reflect function replacing serialize and to_string from the example
above would look as follows.

template <class Mirror>
void reflect(Mirror& mirror, named_actor_config& x, const unsigned int) {
  mirror & meta::type_name("named_actor_config");
  mirror & x.strategy;
  mirror & x.low_watermark;
  mirror & x.max_pending;
}

With:

namespace meta {

struct type_name { const char* value; };

} // namespace meta

Serializers should still fall back to serialize functions and prefer
serialize over reflect. First, to guarantee backward-compatibility as well
as compatibility to other frameworks such as Boost.Serialize. Second, because
some types cannot provide a general-purpose reflect function that is suitable
for serialization (for example actors).

Open Questions

  • What additional meta information do we need to support?
  • Can/should we inject std::ostream<< operators for types supporting reflect

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions