Unverified Commit d893c05d authored by Joseph Noir's avatar Joseph Noir Committed by GitHub

Merge pull request #1100

Use type IDs for error code enums
parents bb2f6ae5 0ba1ca56
...@@ -42,6 +42,14 @@ is based on [Keep a Changelog](https://keepachangelog.com). ...@@ -42,6 +42,14 @@ is based on [Keep a Changelog](https://keepachangelog.com).
losing connection to the monitored node. losing connection to the monitored node.
- In preparation of potential future API additions/changes, CAF now includes an - In preparation of potential future API additions/changes, CAF now includes an
RFC4122-compliant `uuid` class. RFC4122-compliant `uuid` class.
- The new trait class `is_error_code_enum` allows users to enable conversion of
custom error code enums to `error` and `error_code`.
### Deprecated
- The `to_string` output for `error` now renders the error code enum by default.
This renders the member functions `actor_system::render` and
`actor_system_config::render` obsolete.
### Changed ### Changed
......
...@@ -30,8 +30,7 @@ using kickoff_atom = atom_constant<atom("kickoff")>; ...@@ -30,8 +30,7 @@ using kickoff_atom = atom_constant<atom("kickoff")>;
// utility function to print an exit message with custom name // utility function to print an exit message with custom name
void print_on_exit(scheduled_actor* self, const std::string& name) { void print_on_exit(scheduled_actor* self, const std::string& name) {
self->attach_functor([=](const error& reason) { self->attach_functor([=](const error& reason) {
aout(self) << name << " exited: " << self->home_system().render(reason) aout(self) << name << " exited: " << to_string(reason) << endl;
<< endl;
}); });
} }
...@@ -174,8 +173,8 @@ void run_server(actor_system& system, const config& cfg) { ...@@ -174,8 +173,8 @@ void run_server(actor_system& system, const config& cfg) {
auto server_actor = system.middleman().spawn_server(server, cfg.port, auto server_actor = system.middleman().spawn_server(server, cfg.port,
pong_actor); pong_actor);
if (!server_actor) if (!server_actor)
cerr << "unable to spawn server: " cerr << "unable to spawn server: " << to_string(server_actor.error())
<< system.render(server_actor.error()) << endl; << endl;
} }
void run_client(actor_system& system, const config& cfg) { void run_client(actor_system& system, const config& cfg) {
...@@ -184,8 +183,8 @@ void run_client(actor_system& system, const config& cfg) { ...@@ -184,8 +183,8 @@ void run_client(actor_system& system, const config& cfg) {
auto io_actor = system.middleman().spawn_client(protobuf_io, cfg.host, auto io_actor = system.middleman().spawn_client(protobuf_io, cfg.host,
cfg.port, ping_actor); cfg.port, ping_actor);
if (!io_actor) { if (!io_actor) {
cout << "cannot connect to " << cfg.host << " at port " << cfg.port cout << "cannot connect to " << cfg.host << " at port " << cfg.port << ": "
<< ": " << system.render(io_actor.error()) << endl; << to_string(io_actor.error()) << endl;
return; return;
} }
send_as(*io_actor, ping_actor, kickoff_atom::value, *io_actor); send_as(*io_actor, ping_actor, kickoff_atom::value, *io_actor);
......
...@@ -192,8 +192,8 @@ void run_server(actor_system& system, const config& cfg) { ...@@ -192,8 +192,8 @@ void run_server(actor_system& system, const config& cfg) {
auto server_actor = system.middleman().spawn_server(server, cfg.port, auto server_actor = system.middleman().spawn_server(server, cfg.port,
pong_actor); pong_actor);
if (!server_actor) { if (!server_actor) {
std::cerr << "failed to spawn server: " std::cerr << "failed to spawn server: " << to_string(server_actor.error())
<< system.render(server_actor.error()) << endl; << endl;
return; return;
} }
print_on_exit(*server_actor, "server"); print_on_exit(*server_actor, "server");
...@@ -205,7 +205,7 @@ void run_client(actor_system& system, const config& cfg) { ...@@ -205,7 +205,7 @@ void run_client(actor_system& system, const config& cfg) {
auto io_actor = system.middleman().spawn_client(broker_impl, cfg.host, auto io_actor = system.middleman().spawn_client(broker_impl, cfg.host,
cfg.port, ping_actor); cfg.port, ping_actor);
if (!io_actor) { if (!io_actor) {
std::cerr << "failed to spawn client: " << system.render(io_actor.error()) std::cerr << "failed to spawn client: " << to_string(io_actor.error())
<< endl; << endl;
return; return;
} }
......
...@@ -77,8 +77,8 @@ public: ...@@ -77,8 +77,8 @@ public:
void caf_main(actor_system& system, const config& cfg) { void caf_main(actor_system& system, const config& cfg) {
auto server_actor = system.middleman().spawn_server(server, cfg.port); auto server_actor = system.middleman().spawn_server(server, cfg.port);
if (!server_actor) { if (!server_actor) {
cerr << "*** cannot spawn server: " cerr << "*** cannot spawn server: " << to_string(server_actor.error())
<< system.render(server_actor.error()) << endl; << endl;
return; return;
} }
cout << "*** listening on port " << cfg.port << endl; cout << "*** listening on port " << cfg.port << endl;
......
...@@ -96,14 +96,14 @@ void caf_main(actor_system& sys) { ...@@ -96,14 +96,14 @@ void caf_main(actor_system& sys) {
binary_serializer bs{sys, buf}; binary_serializer bs{sys, buf};
auto e = bs(f1); auto e = bs(f1);
if (e) { if (e) {
std::cerr << "*** unable to serialize foo2: " << sys.render(e) << std::endl; std::cerr << "*** unable to serialize foo2: " << to_string(e) << '\n';
return; return;
} }
// read f2 back from buffer // read f2 back from buffer
binary_deserializer bd{sys, buf}; binary_deserializer bd{sys, buf};
e = bd(f2); e = bd(f2);
if (e) { if (e) {
std::cerr << "*** unable to serialize foo2: " << sys.render(e) << std::endl; std::cerr << "*** unable to serialize foo2: " << to_string(e) << '\n';
return; return;
} }
// must be equal // must be equal
......
...@@ -37,7 +37,7 @@ void caf_main(actor_system& system) { ...@@ -37,7 +37,7 @@ void caf_main(actor_system& system) {
: "server\n"); : "server\n");
}, },
[&](error& err) { [&](error& err) {
aout(self) << "received error " << system.render(err) << " from " aout(self) << "received error " << to_string(err) << " from "
<< (self->current_sender() == worker ? "worker\n" << (self->current_sender() == worker ? "worker\n"
: "server\n"); : "server\n");
}); });
......
...@@ -101,8 +101,7 @@ template <class Handle, class... Ts> ...@@ -101,8 +101,7 @@ template <class Handle, class... Ts>
void tester(scoped_actor& self, const Handle& hdl, int32_t x, int32_t y, void tester(scoped_actor& self, const Handle& hdl, int32_t x, int32_t y,
Ts&&... xs) { Ts&&... xs) {
auto handle_err = [&](const error& err) { auto handle_err = [&](const error& err) {
aout(self) << "AUT (actor under test) failed: " aout(self) << "AUT (actor under test) failed: " << to_string(err) << endl;
<< self->system().render(err) << endl;
}; };
// first test: x + y = z // first test: x + y = z
self->request(hdl, infinite, add_atom_v, x, y) self->request(hdl, infinite, add_atom_v, x, y)
......
...@@ -27,24 +27,13 @@ std::string to_string(math_error x) { ...@@ -27,24 +27,13 @@ std::string to_string(math_error x) {
} }
} }
namespace caf { CAF_BEGIN_TYPE_ID_BLOCK(divider, first_custom_type_id)
template <> CAF_ADD_TYPE_ID(divider, (math_error))
struct error_category<math_error> {
static constexpr uint8_t value = 101;
};
} // namespace caf CAF_END_TYPE_ID_BLOCK(divider)
class config : public actor_system_config { CAF_ERROR_CODE_ENUM(math_error)
public:
config() {
auto renderer = [](uint8_t x, const message&) {
return to_string(static_cast<math_error>(x));
};
add_error_category(caf::error_category<math_error>::value, renderer);
}
};
using divider = typed_actor<result<double>(div_atom, double, double)>; using divider = typed_actor<result<double>(div_atom, double, double)>;
...@@ -58,7 +47,7 @@ divider::behavior_type divider_impl() { ...@@ -58,7 +47,7 @@ divider::behavior_type divider_impl() {
}; };
} }
void caf_main(actor_system& system, const config&) { void caf_main(actor_system& system) {
double x; double x;
double y; double y;
cout << "x: " << flush; cout << "x: " << flush;
...@@ -72,8 +61,8 @@ void caf_main(actor_system& system, const config&) { ...@@ -72,8 +61,8 @@ void caf_main(actor_system& system, const config&) {
[&](double z) { aout(self) << x << " / " << y << " = " << z << endl; }, [&](double z) { aout(self) << x << " / " << y << " = " << z << endl; },
[&](const error& err) { [&](const error& err) {
aout(self) << "*** cannot compute " << x << " / " << y << " => " aout(self) << "*** cannot compute " << x << " / " << y << " => "
<< system.render(err) << endl; << to_string(err) << endl;
}); });
} }
CAF_MAIN() CAF_MAIN(id_block::divider)
...@@ -3,30 +3,25 @@ ...@@ -3,30 +3,25 @@
#include <cstdint> #include <cstdint>
#include <iostream> #include <iostream>
enum class fixed_stack_errc : uint8_t {
push_to_full = 1,
pop_from_empty,
};
CAF_BEGIN_TYPE_ID_BLOCK(fixed_stack, first_custom_type_id) CAF_BEGIN_TYPE_ID_BLOCK(fixed_stack, first_custom_type_id)
CAF_ADD_TYPE_ID(fixed_stack, (fixed_stack_errc))
CAF_ADD_ATOM(fixed_stack, pop_atom) CAF_ADD_ATOM(fixed_stack, pop_atom)
CAF_ADD_ATOM(fixed_stack, push_atom) CAF_ADD_ATOM(fixed_stack, push_atom)
CAF_END_TYPE_ID_BLOCK(fixed_stack) CAF_END_TYPE_ID_BLOCK(fixed_stack)
CAF_ERROR_CODE_ENUM(fixed_stack_errc)
using std::endl; using std::endl;
using namespace caf; using namespace caf;
enum class fixed_stack_errc : uint8_t {
push_to_full = 1,
pop_from_empty,
};
namespace caf {
template <>
struct error_category<fixed_stack_errc> {
static constexpr uint8_t value = 100;
};
} // namespace caf
class fixed_stack : public event_based_actor { class fixed_stack : public event_based_actor {
public: public:
fixed_stack(actor_config& cfg, size_t stack_size) fixed_stack(actor_config& cfg, size_t stack_size)
......
...@@ -56,8 +56,7 @@ void blocking_testee(blocking_actor* self, vector<cell> cells) { ...@@ -56,8 +56,7 @@ void blocking_testee(blocking_actor* self, vector<cell> cells) {
aout(self) << "cell #" << x.id() << " -> " << y << endl; aout(self) << "cell #" << x.id() << " -> " << y << endl;
}, },
[&](error& err) { [&](error& err) {
aout(self) << "cell #" << x.id() << " -> " aout(self) << "cell #" << x.id() << " -> " << to_string(err) << endl;
<< self->system().render(err) << endl;
}); });
} }
......
...@@ -54,8 +54,8 @@ void tester(event_based_actor* self, const calculator_type& testee) { ...@@ -54,8 +54,8 @@ void tester(event_based_actor* self, const calculator_type& testee) {
}); });
}, },
[=](const error& err) { [=](const error& err) {
aout(self) << "AUT (actor under test) failed: " aout(self) << "AUT (actor under test) failed: " << to_string(err)
<< self->system().render(err) << endl; << endl;
self->quit(exit_reason::user_shutdown); self->quit(exit_reason::user_shutdown);
}); });
} }
......
...@@ -79,7 +79,7 @@ void ChatWidget::sendChatMessage() { ...@@ -79,7 +79,7 @@ void ChatWidget::sendChatMessage() {
auto x = system().groups().get(mod, g); auto x = system().groups().get(mod, g);
if (! x) if (! x)
print("*** error: " print("*** error: "
+ QString::fromUtf8(system().render(x.error()).c_str())); + QString::fromUtf8(to_string(x.error()).c_str()));
else else
self()->send(self(), atom("join"), std::move(*x)); self()->send(self(), atom("join"), std::move(*x));
}, },
...@@ -128,7 +128,7 @@ void ChatWidget::joinGroup() { ...@@ -128,7 +128,7 @@ void ChatWidget::joinGroup() {
string gid = gname.midRef(pos+1).toUtf8().constData(); string gid = gname.midRef(pos+1).toUtf8().constData();
auto x = system().groups().get(mod, gid); auto x = system().groups().get(mod, gid);
if (! x) if (! x)
QMessageBox::critical(this, "Error", system().render(x.error()).c_str()); QMessageBox::critical(this, "Error", to_string(x.error()).c_str());
else else
self()->send(self(), join_atom::value, std::move(*x)); self()->send(self(), join_atom::value, std::move(*x));
} }
......
...@@ -59,9 +59,8 @@ int main(int argc, char** argv) { ...@@ -59,9 +59,8 @@ int main(int argc, char** argv) {
auto group_uri = cfg.group_id.substr(p + 1); auto group_uri = cfg.group_id.substr(p + 1);
auto g = system.groups().get(module, group_uri); auto g = system.groups().get(module, group_uri);
if (! g) { if (! g) {
cerr << "*** unable to get group " << group_uri cerr << "*** unable to get group " << group_uri << " from module "
<< " from module " << module << ": " << module << ": " << to_string(g.error()) << endl;
<< system.render(g.error()) << endl;
return -1; return -1;
} }
grp = std::move(*g); grp = std::move(*g);
......
...@@ -145,7 +145,7 @@ void connecting(stateful_actor<state>* self, const std::string& host, ...@@ -145,7 +145,7 @@ void connecting(stateful_actor<state>* self, const std::string& host,
}, },
[=](const error& err) { [=](const error& err) {
aout(self) << R"(*** cannot connect to ")" << host << R"(":)" << port aout(self) << R"(*** cannot connect to ")" << host << R"(":)" << port
<< " => " << self->system().render(err) << endl; << " => " << to_string(err) << endl;
self->become(unconnected(self)); self->become(unconnected(self));
}); });
} }
...@@ -286,7 +286,7 @@ void run_server(actor_system& system, const config& cfg) { ...@@ -286,7 +286,7 @@ void run_server(actor_system& system, const config& cfg) {
cout << "*** try publish at port " << cfg.port << endl; cout << "*** try publish at port " << cfg.port << endl;
auto expected_port = io::publish(calc, cfg.port); auto expected_port = io::publish(calc, cfg.port);
if (!expected_port) { if (!expected_port) {
std::cerr << "*** publish failed: " << system.render(expected_port.error()) std::cerr << "*** publish failed: " << to_string(expected_port.error())
<< endl; << endl;
return; return;
} }
......
...@@ -85,7 +85,7 @@ void run_server(actor_system& system, const config& cfg) { ...@@ -85,7 +85,7 @@ void run_server(actor_system& system, const config& cfg) {
auto res = system.middleman().publish_local_groups(cfg.port); auto res = system.middleman().publish_local_groups(cfg.port);
if (!res) { if (!res) {
std::cerr << "*** publishing local groups failed: " std::cerr << "*** publishing local groups failed: "
<< system.render(res.error()) << std::endl; << to_string(res.error()) << std::endl;
return; return;
} }
std::cout << "*** listening at port " << *res << std::endl std::cout << "*** listening at port " << *res << std::endl
...@@ -112,7 +112,7 @@ void run_client(actor_system& system, const config& cfg) { ...@@ -112,7 +112,7 @@ void run_client(actor_system& system, const config& cfg) {
anon_send(client_actor, join_atom_v, std::move(*tmp)); anon_send(client_actor, join_atom_v, std::move(*tmp));
else else
std::cerr << R"(*** failed to parse ")" << uri << R"(" as group URI: )" std::cerr << R"(*** failed to parse ")" << uri << R"(" as group URI: )"
<< system.render(tmp.error()) << std::endl; << to_string(tmp.error()) << std::endl;
} }
std::istream_iterator<line> eof; std::istream_iterator<line> eof;
std::vector<std::string> words; std::vector<std::string> words;
......
...@@ -115,7 +115,7 @@ struct config : actor_system_config { ...@@ -115,7 +115,7 @@ struct config : actor_system_config {
void server(actor_system& system, const config& cfg) { void server(actor_system& system, const config& cfg) {
auto res = system.middleman().open(cfg.port); auto res = system.middleman().open(cfg.port);
if (!res) { if (!res) {
cerr << "*** cannot open port: " << system.render(res.error()) << endl; cerr << "*** cannot open port: " << to_string(res.error()) << endl;
return; return;
} }
cout << "*** running on port: " << *res << endl cout << "*** running on port: " << *res << endl
...@@ -127,7 +127,7 @@ void server(actor_system& system, const config& cfg) { ...@@ -127,7 +127,7 @@ void server(actor_system& system, const config& cfg) {
void client(actor_system& system, const config& cfg) { void client(actor_system& system, const config& cfg) {
auto node = system.middleman().connect(cfg.host, cfg.port); auto node = system.middleman().connect(cfg.host, cfg.port);
if (!node) { if (!node) {
cerr << "*** connect failed: " << system.render(node.error()) << endl; cerr << "*** connect failed: " << to_string(node.error()) << endl;
return; return;
} }
auto type = "calculator"; // type of the actor we wish to spawn auto type = "calculator"; // type of the actor we wish to spawn
...@@ -136,8 +136,7 @@ void client(actor_system& system, const config& cfg) { ...@@ -136,8 +136,7 @@ void client(actor_system& system, const config& cfg) {
auto worker = system.middleman().remote_spawn<calculator>(*node, type, args, auto worker = system.middleman().remote_spawn<calculator>(*node, type, args,
tout); tout);
if (!worker) { if (!worker) {
cerr << "*** remote spawn failed: " << system.render(worker.error()) cerr << "*** remote spawn failed: " << to_string(worker.error()) << endl;
<< endl;
return; return;
} }
// start using worker in main loop // start using worker in main loop
......
...@@ -242,7 +242,8 @@ public: ...@@ -242,7 +242,8 @@ public:
actor_registry& registry(); actor_registry& registry();
/// Returns a string representation for `err`. /// Returns a string representation for `err`.
std::string render(const error& x) const; [[deprecated("please use to_string() on the error")]] std::string
render(const error& x) const;
/// Returns the system-wide group manager. /// Returns the system-wide group manager.
group_manager& groups(); group_manager& groups();
......
...@@ -67,10 +67,6 @@ public: ...@@ -67,10 +67,6 @@ public:
using portable_name_map = hash_map<std::type_index, std::string>; using portable_name_map = hash_map<std::type_index, std::string>;
using error_renderer = std::function<std::string(uint8_t, const message&)>;
using error_renderer_map = hash_map<uint8_t, error_renderer>;
using group_module_factory = std::function<group_module*()>; using group_module_factory = std::function<group_module*()>;
using group_module_factory_vector = std::vector<group_module_factory>; using group_module_factory_vector = std::vector<group_module_factory>;
...@@ -154,29 +150,6 @@ public: ...@@ -154,29 +150,6 @@ public:
return add_actor_factory(std::move(name), make_actor_factory(std::move(f))); return add_actor_factory(std::move(name), make_actor_factory(std::move(f)));
} }
/// Enables the actor system to convert errors of this error category
/// to human-readable strings via `renderer`.
actor_system_config& add_error_category(uint8_t category, error_renderer f);
/// Enables the actor system to convert errors of this error category
/// to human-readable strings via `to_string(T)`.
template <class T>
actor_system_config&
add_error_category(uint8_t category, string_view category_name) {
auto f = [=](uint8_t val, const std::string& ctx) -> std::string {
std::string result{category_name.begin(), category_name.end()};
result += ": ";
result += to_string(static_cast<T>(val));
if (!ctx.empty()) {
result += " (";
result += ctx;
result += ")";
}
return result;
};
return add_error_category(category, error_renderer{f});
}
/// Loads module `T` with optional template parameters `Ts...`. /// Loads module `T` with optional template parameters `Ts...`.
template <class T, class... Ts> template <class T, class... Ts>
actor_system_config& load() { actor_system_config& load() {
...@@ -272,10 +245,6 @@ public: ...@@ -272,10 +245,6 @@ public:
/// @note Has no effect unless building CAF with CAF_ENABLE_ACTOR_PROFILER. /// @note Has no effect unless building CAF with CAF_ENABLE_ACTOR_PROFILER.
tracing_data_factory* tracing_context = nullptr; tracing_data_factory* tracing_context = nullptr;
// -- rendering of user-defined types ----------------------------------------
error_renderer_map error_renderers;
// -- parsing parameters ----------------------------------------------------- // -- parsing parameters -----------------------------------------------------
/// Configures the file path for the INI file, `caf-application.ini` per /// Configures the file path for the INI file, `caf-application.ini` per
...@@ -291,13 +260,8 @@ public: ...@@ -291,13 +260,8 @@ public:
// -- default error rendering functions -------------------------------------- // -- default error rendering functions --------------------------------------
static std::string render(const error& err); [[deprecated("please use to_string() on the error")]] static std::string
render(const error& err);
static std::string render_sec(uint8_t, const message&);
static std::string render_exit_reason(uint8_t, const message&);
static std::string render_pec(uint8_t, const message&);
// -- config file parsing ---------------------------------------------------- // -- config file parsing ----------------------------------------------------
......
// Deprecated include. The next CAF release won't include this header.
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* | |___ / ___ \| _| Framework * * | |___ / ___ \| _| Framework *
* \____/_/ \_|_| * * \____/_/ \_|_| *
* * * *
* Copyright 2011-2019 Dominik Charousset * * Copyright 2011-2020 Dominik Charousset *
* * * *
* Distributed under the terms and conditions of the BSD 3-Clause License or * * Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software * * (at your option) under the terms and conditions of the Boost Software *
...@@ -18,13 +18,19 @@ ...@@ -18,13 +18,19 @@
#pragma once #pragma once
#include <cstdint> #include <type_traits>
namespace caf { namespace caf::detail {
/// Customization point for enabling conversion from an enum type to an template <class T, std::size_t = sizeof(T)>
/// @ref error. std::true_type is_complete_impl(T*);
std::false_type is_complete_impl(...);
/// Checks whether T is a complete type. For example, passing a forward
/// declaration or undefined template specialization evaluates to `false`.
template <class T> template <class T>
struct error_category; constexpr bool is_complete
= decltype(is_complete_impl(std::declval<T*>()))::value;
} // namespace caf } // namespace caf::detail
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "caf/detail/is_complete.hpp"
#include "caf/detail/is_one_of.hpp" #include "caf/detail/is_one_of.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
...@@ -741,17 +742,6 @@ struct is_stl_tuple_type { ...@@ -741,17 +742,6 @@ struct is_stl_tuple_type {
template <class T> template <class T>
constexpr bool is_stl_tuple_type_v = is_stl_tuple_type<T>::value; constexpr bool is_stl_tuple_type_v = is_stl_tuple_type<T>::value;
template <class T, std::size_t = sizeof(T)>
std::true_type is_complete_impl(T*);
std::false_type is_complete_impl(...);
/// Checks whether T is a complete type. For example, passing a forward
/// declaration or undefined template specialization evaluates to `false`.
template <class T>
constexpr bool is_complete
= decltype(is_complete_impl(std::declval<T*>()))::value;
} // namespace caf::detail } // namespace caf::detail
#undef CAF_HAS_MEMBER_TRAIT #undef CAF_HAS_MEMBER_TRAIT
......
...@@ -19,20 +19,21 @@ ...@@ -19,20 +19,21 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <functional> #include <memory>
#include <utility> #include <utility>
#include "caf/detail/comparable.hpp" #include "caf/detail/comparable.hpp"
#include "caf/detail/core_export.hpp" #include "caf/detail/core_export.hpp"
#include "caf/error_category.hpp"
#include "caf/error_code.hpp" #include "caf/error_code.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/is_error_code_enum.hpp"
#include "caf/message.hpp" #include "caf/message.hpp"
#include "caf/meta/load_callback.hpp" #include "caf/meta/load_callback.hpp"
#include "caf/meta/omittable_if_empty.hpp" #include "caf/meta/omittable_if_empty.hpp"
#include "caf/meta/save_callback.hpp" #include "caf/meta/save_callback.hpp"
#include "caf/meta/type_name.hpp" #include "caf/meta/type_name.hpp"
#include "caf/none.hpp" #include "caf/none.hpp"
#include "caf/type_id.hpp"
namespace caf { namespace caf {
...@@ -60,46 +61,39 @@ namespace caf { ...@@ -60,46 +61,39 @@ namespace caf {
/// ///
/// # Why is there no `string()` member function? /// # Why is there no `string()` member function?
/// ///
/// The C++ standard library uses category singletons and virtual dispatching /// The C++ standard library uses category singletons and virtual dispatching to
/// to correlate error codes to descriptive strings. However, singletons are /// correlate error codes to descriptive strings. However, singletons are a poor
/// a poor choice when it comes to serialization. CAF uses atoms for /// choice when it comes to serialization. CAF uses type IDs and meta objects
/// categories instead and requires users to register custom error categories /// instead.
/// to the actor system. This makes the actor system the natural instance for
/// rendering error messages via `actor_system::render(const error&)`.
class CAF_CORE_EXPORT error : detail::comparable<error> { class CAF_CORE_EXPORT error : detail::comparable<error> {
public: public:
// -- member types -----------------------------------------------------------
using inspect_fun
= std::function<error(meta::type_name_t, uint8_t&, uint8_t&,
meta::omittable_if_empty_t, message&)>;
// -- constructors, destructors, and assignment operators -------------------- // -- constructors, destructors, and assignment operators --------------------
error() noexcept; error() noexcept = default;
error(none_t) noexcept; error(none_t) noexcept;
error(error&&) noexcept; error(error&&) noexcept = default;
error& operator=(error&&) noexcept; error& operator=(error&&) noexcept = default;
error(const error&); error(const error&);
error& operator=(const error&); error& operator=(const error&);
error(uint8_t x, uint8_t y); template <class Enum, class = std::enable_if_t<is_error_code_enum_v<Enum>>>
error(Enum code) : error(static_cast<uint8_t>(code), type_id_v<Enum>) {
error(uint8_t x, uint8_t y, message z); // nop
}
template <class Enum, uint8_t Category = error_category<Enum>::value> template <class Enum, class = std::enable_if_t<is_error_code_enum_v<Enum>>>
error(Enum error_value) : error(static_cast<uint8_t>(error_value), Category) { error(Enum code, message context)
: error(static_cast<uint8_t>(code), type_id_v<Enum>, std::move(context)) {
// nop // nop
} }
template <class Enum> template <class Enum>
error(error_code<Enum> code) error(error_code<Enum> code) : error(to_integer(code), type_id_v<Enum>) {
: error(static_cast<uint8_t>(code.value()), error_category<Enum>::value) {
// nop // nop
} }
...@@ -115,21 +109,25 @@ public: ...@@ -115,21 +109,25 @@ public:
return *this = code.value(); return *this = code.value();
} }
~error(); // -- properties -------------------------------------------------------------
// -- observers --------------------------------------------------------------
/// Returns the category-specific error code, whereas `0` means "no error". /// Returns the category-specific error code, whereas `0` means "no error".
/// @pre `*this != none` /// @pre `*this != none`
uint8_t code() const noexcept; uint8_t code() const noexcept {
return data_->code;
}
/// Returns the category of this error. /// Returns the ::type_id of the category for this error.
/// @pre `*this != none` /// @pre `*this != none`
uint8_t category() const noexcept; type_id_t category() const noexcept {
return data_->category;
}
/// Returns context information to this error. /// Returns context information to this error.
/// @pre `*this != none` /// @pre `*this != none`
const message& context() const noexcept; const message& context() const noexcept {
return data_->context;
}
/// Returns `*this != none`. /// Returns `*this != none`.
explicit operator bool() const noexcept { explicit operator bool() const noexcept {
...@@ -143,23 +141,14 @@ public: ...@@ -143,23 +141,14 @@ public:
int compare(const error&) const noexcept; int compare(const error&) const noexcept;
int compare(uint8_t x, uint8_t y) const noexcept; int compare(uint8_t code, type_id_t category) const noexcept;
// -- modifiers --------------------------------------------------------------
/// Returns context information to this error.
/// @pre `*this != none`
message& context() noexcept;
/// Sets the error code to 0.
void clear() noexcept;
// -- static convenience functions ------------------------------------------- // -- static convenience functions -------------------------------------------
/// @cond PRIVATE /// @cond PRIVATE
static error eval() { static error eval() {
return none; return error{};
} }
template <class F, class... Fs> template <class F, class... Fs>
...@@ -185,36 +174,39 @@ public: ...@@ -185,36 +174,39 @@ public:
uint8_t code = 0; uint8_t code = 0;
auto cb = meta::load_callback([&] { auto cb = meta::load_callback([&] {
if (code == 0) { if (code == 0) {
x.clear(); x.data_.reset();
if constexpr (std::is_same<result_type, void>::value) if constexpr (std::is_same<result_type, void>::value)
return; return;
else else
return result_type{}; return result_type{};
} }
x.init(); if (!x.data_)
x.code_ref() = code; x.data_.reset(new data);
return f(x.category_ref(), x.context()); x.data_->code = code;
return f(x.data_->category, x.data_->context);
}); });
return f(code, cb); return f(code, cb);
} }
} }
private: private:
// -- inspection support ----------------------------------------------------- // -- constructors, destructors, and assignment operators --------------------
uint8_t& code_ref() noexcept;
uint8_t& category_ref() noexcept; error(uint8_t code, type_id_t category);
void init(); error(uint8_t code, type_id_t category, message context);
// -- nested classes --------------------------------------------------------- // -- nested classes ---------------------------------------------------------
struct data; struct data {
uint8_t code;
type_id_t category;
message context;
};
// -- member variables ------------------------------------------------------- // -- member variables -------------------------------------------------------
data* data_; std::unique_ptr<data> data_;
}; };
/// @relates error /// @relates error
...@@ -222,15 +214,15 @@ CAF_CORE_EXPORT std::string to_string(const error& x); ...@@ -222,15 +214,15 @@ CAF_CORE_EXPORT std::string to_string(const error& x);
/// @relates error /// @relates error
template <class Enum> template <class Enum>
error make_error(Enum code) { std::enable_if_t<is_error_code_enum_v<Enum>, error> make_error(Enum code) {
return error{static_cast<uint8_t>(code), error_category<Enum>::value}; return error{code};
} }
/// @relates error /// @relates error
template <class Enum, class T, class... Ts> template <class Enum, class T, class... Ts>
error make_error(Enum code, T&& x, Ts&&... xs) { std::enable_if_t<is_error_code_enum_v<Enum>, error>
return error{static_cast<uint8_t>(code), error_category<Enum>::value, make_error(Enum code, T&& x, Ts&&... xs) {
make_message(std::forward<T>(x), std::forward<Ts>(xs)...)}; return error{code, make_message(std::forward<T>(x), std::forward<Ts>(xs)...)};
} }
/// @relates error /// @relates error
...@@ -244,15 +236,18 @@ inline bool operator==(none_t, const error& x) { ...@@ -244,15 +236,18 @@ inline bool operator==(none_t, const error& x) {
} }
/// @relates error /// @relates error
template <class Enum, uint8_t Category = error_category<Enum>::value> template <class Enum>
bool operator==(const error& x, Enum y) { std::enable_if_t<is_error_code_enum_v<Enum>, bool>
operator==(const error& x, Enum y) {
auto code = static_cast<uint8_t>(y); auto code = static_cast<uint8_t>(y);
return code == 0 ? !x : x && x.category() == Category && x.code() == code; return code == 0 ? !x
: x && x.code() == code && x.category() == type_id_v<Enum>;
} }
/// @relates error /// @relates error
template <class Enum, uint8_t Category = error_category<Enum>::value> template <class Enum>
bool operator==(Enum x, const error& y) { std::enable_if_t<is_error_code_enum_v<Enum>, bool>
operator==(Enum x, const error& y) {
return y == x; return y == x;
} }
...@@ -267,14 +262,16 @@ inline bool operator!=(none_t, const error& x) { ...@@ -267,14 +262,16 @@ inline bool operator!=(none_t, const error& x) {
} }
/// @relates error /// @relates error
template <class Enum, uint8_t Category = error_category<Enum>::value> template <class Enum>
bool operator!=(const error& x, Enum y) { std::enable_if_t<is_error_code_enum_v<Enum>, bool>
operator!=(const error& x, Enum y) {
return !(x == y); return !(x == y);
} }
/// @relates error /// @relates error
template <class Enum, uint8_t Category = error_category<Enum>::value> template <class Enum>
bool operator!=(Enum x, const error& y) { std::enable_if_t<is_error_code_enum_v<Enum>, bool>
operator!=(Enum x, const error& y) {
return !(x == y); return !(x == y);
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <type_traits> #include <type_traits>
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/is_error_code_enum.hpp"
#include "caf/none.hpp" #include "caf/none.hpp"
namespace caf { namespace caf {
...@@ -32,7 +33,11 @@ class error_code { ...@@ -32,7 +33,11 @@ class error_code {
public: public:
using enum_type = Enum; using enum_type = Enum;
using underlying_type = std::underlying_type_t<enum_type>; using underlying_type = std::underlying_type_t<Enum>;
static_assert(is_error_code_enum_v<Enum>);
static_assert(std::is_same<underlying_type, uint8_t>::value);
constexpr error_code() noexcept : value_(static_cast<Enum>(0)) { constexpr error_code() noexcept : value_(static_cast<Enum>(0)) {
// nop // nop
...@@ -63,6 +68,10 @@ public: ...@@ -63,6 +68,10 @@ public:
return value_; return value_;
} }
friend constexpr underlying_type to_integer(error_code x) noexcept {
return static_cast<std::underlying_type_t<Enum>>(x.value());
}
private: private:
enum_type value_; enum_type value_;
}; };
......
...@@ -92,8 +92,8 @@ int exec_main(F fun, int argc, char** argv, ...@@ -92,8 +92,8 @@ int exec_main(F fun, int argc, char** argv,
// Pass CLI options to config. // Pass CLI options to config.
typename helper::config cfg; typename helper::config cfg;
if (auto err = cfg.parse(argc, argv, config_file_name)) { if (auto err = cfg.parse(argc, argv, config_file_name)) {
std::cerr << "error while parsing CLI and file options: " std::cerr << "error while parsing CLI and file options: " << to_string(err)
<< actor_system_config::render(err) << std::endl; << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Return immediately if a help text was printed. // Return immediately if a help text was printed.
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <string> #include <string>
#include "caf/detail/core_export.hpp" #include "caf/detail/core_export.hpp"
#include "caf/error_category.hpp" #include "caf/is_error_code_enum.hpp"
namespace caf { namespace caf {
...@@ -52,12 +52,9 @@ enum class exit_reason : uint8_t { ...@@ -52,12 +52,9 @@ enum class exit_reason : uint8_t {
unreachable unreachable
}; };
/// Returns a string representation of given exit reason. /// @relates exit_reason
CAF_CORE_EXPORT std::string to_string(exit_reason); CAF_CORE_EXPORT std::string to_string(exit_reason);
template <>
struct error_category<exit_reason> {
static constexpr uint8_t value = 3;
};
} // namespace caf } // namespace caf
CAF_ERROR_CODE_ENUM(exit_reason)
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include "caf/deep_to_string.hpp" #include "caf/deep_to_string.hpp"
#include "caf/error.hpp" #include "caf/error.hpp"
#include "caf/error_category.hpp" #include "caf/is_error_code_enum.hpp"
#include "caf/unifyn.hpp" #include "caf/unifyn.hpp"
#include "caf/unit.hpp" #include "caf/unit.hpp"
...@@ -81,9 +81,9 @@ public: ...@@ -81,9 +81,9 @@ public:
construct(other); construct(other);
} }
template <class Enum, uint8_t Category = error_category<Enum>::value> template <class Enum, class = std::enable_if_t<is_error_code_enum_v<Enum>>>
expected(Enum code) : engaged_(false) { expected(Enum code) : engaged_(false) {
new (std::addressof(error_)) caf::error(make_error(code)); new (std::addressof(error_)) caf::error(code);
} }
expected(expected&& other) noexcept(nothrow_move) { expected(expected&& other) noexcept(nothrow_move) {
...@@ -157,7 +157,7 @@ public: ...@@ -157,7 +157,7 @@ public:
return *this; return *this;
} }
template <class Enum, uint8_t Category = error_category<Enum>::value> template <class Enum, class = std::enable_if_t<is_error_code_enum_v<Enum>>>
expected& operator=(Enum code) { expected& operator=(Enum code) {
return *this = make_error(code); return *this = make_error(code);
} }
...@@ -298,14 +298,16 @@ bool operator==(const error& x, const expected<T>& y) { ...@@ -298,14 +298,16 @@ bool operator==(const error& x, const expected<T>& y) {
} }
/// @relates expected /// @relates expected
template <class T, class Enum, uint8_t = error_category<Enum>::value> template <class T, class Enum>
bool operator==(const expected<T>& x, Enum y) { std::enable_if_t<is_error_code_enum_v<Enum>, bool>
operator==(const expected<T>& x, Enum y) {
return x == make_error(y); return x == make_error(y);
} }
/// @relates expected /// @relates expected
template <class Enum, class T, uint8_t = error_category<Enum>::value> template <class T, class Enum>
bool operator==(Enum x, const expected<T>& y) { std::enable_if_t<is_error_code_enum_v<Enum>, bool>
operator==(Enum x, const expected<T>& y) {
return y == make_error(x); return y == make_error(x);
} }
...@@ -341,14 +343,16 @@ bool operator!=(const error& x, const expected<T>& y) { ...@@ -341,14 +343,16 @@ bool operator!=(const error& x, const expected<T>& y) {
} }
/// @relates expected /// @relates expected
template <class T, class Enum, uint8_t = error_category<Enum>::value> template <class T, class Enum>
bool operator!=(const expected<T>& x, Enum y) { std::enable_if_t<is_error_code_enum_v<Enum>, bool>
operator!=(const expected<T>& x, Enum y) {
return !(x == y); return !(x == y);
} }
/// @relates expected /// @relates expected
template <class T, class Enum, uint8_t = error_category<Enum>::value> template <class T, class Enum>
bool operator!=(Enum x, const expected<T>& y) { std::enable_if_t<is_error_code_enum_v<Enum>, bool>
operator!=(Enum x, const expected<T>& y) {
return !(x == y); return !(x == y);
} }
...@@ -375,7 +379,7 @@ public: ...@@ -375,7 +379,7 @@ public:
// nop // nop
} }
template <class Enum, uint8_t = error_category<Enum>::value> template <class Enum, class = std::enable_if_t<is_error_code_enum_v<Enum>>>
expected(Enum code) : error_(code) { expected(Enum code) : error_(code) {
// nop // nop
} }
......
...@@ -181,10 +181,11 @@ config_option make_config_option(T& storage, string_view category, ...@@ -181,10 +181,11 @@ config_option make_config_option(T& storage, string_view category,
// -- enums -------------------------------------------------------------------- // -- enums --------------------------------------------------------------------
enum class byte : uint8_t; enum class byte : uint8_t;
enum class exit_reason : uint8_t;
enum class invoke_message_result;
enum class pec : uint8_t; enum class pec : uint8_t;
enum class sec : uint8_t; enum class sec : uint8_t;
enum class stream_priority; enum class stream_priority;
enum class invoke_message_result;
// -- aliases ------------------------------------------------------------------ // -- aliases ------------------------------------------------------------------
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
namespace caf {
/// Customization point for enabling conversion from an enum type to an
/// @ref error or @ref error_code.
template <class T>
struct is_error_code_enum {
static constexpr bool value = false;
};
/// @relates is_error_code_enum
template <class T>
constexpr bool is_error_code_enum_v = is_error_code_enum<T>::value;
} // namespace caf
#define CAF_ERROR_CODE_ENUM(type_name) \
namespace caf { \
template <> \
struct is_error_code_enum<type_name> { \
static constexpr bool value = true; \
}; \
}
// Deprecated include. The next CAF release won't include this header.
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
#include <string> #include <string>
#include "caf/detail/core_export.hpp" #include "caf/detail/core_export.hpp"
#include "caf/error_category.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/is_error_code_enum.hpp"
namespace caf { namespace caf {
...@@ -79,9 +79,6 @@ enum class pec : uint8_t { ...@@ -79,9 +79,6 @@ enum class pec : uint8_t {
CAF_CORE_EXPORT std::string to_string(pec); CAF_CORE_EXPORT std::string to_string(pec);
template <>
struct error_category<pec> {
static constexpr uint8_t value = 1;
};
} // namespace caf } // namespace caf
CAF_ERROR_CODE_ENUM(pec)
...@@ -62,7 +62,7 @@ public: ...@@ -62,7 +62,7 @@ public:
result_base& operator=(const result_base&) = default; result_base& operator=(const result_base&) = default;
template <class Enum, uint8_t = error_category<Enum>::value> template <class Enum, class = std::enable_if_t<is_error_code_enum_v<Enum>>>
result_base(Enum x) : content_(make_error(x)) { result_base(Enum x) : content_(make_error(x)) {
// nop // nop
} }
......
...@@ -26,8 +26,8 @@ ...@@ -26,8 +26,8 @@
#include <string> #include <string>
#include "caf/detail/core_export.hpp" #include "caf/detail/core_export.hpp"
#include "caf/error_category.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/is_error_code_enum.hpp"
namespace caf { namespace caf {
...@@ -147,11 +147,9 @@ enum class sec : uint8_t { ...@@ -147,11 +147,9 @@ enum class sec : uint8_t {
all_requests_failed, all_requests_failed,
}; };
/// @relates sec
CAF_CORE_EXPORT std::string to_string(sec); CAF_CORE_EXPORT std::string to_string(sec);
template <>
struct error_category<sec> {
static constexpr uint8_t value = 0;
};
} // namespace caf } // namespace caf
CAF_ERROR_CODE_ENUM(sec)
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <utility> #include <utility>
#include "caf/detail/core_export.hpp" #include "caf/detail/core_export.hpp"
#include "caf/detail/is_complete.hpp"
#include "caf/detail/pp.hpp" #include "caf/detail/pp.hpp"
#include "caf/detail/squashed_int.hpp" #include "caf/detail/squashed_int.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
...@@ -83,6 +84,10 @@ constexpr const char* type_name_v = type_name<T>::value; ...@@ -83,6 +84,10 @@ constexpr const char* type_name_v = type_name<T>::value;
/// The first type ID not reserved by CAF and its modules. /// The first type ID not reserved by CAF and its modules.
constexpr type_id_t first_custom_type_id = 200; constexpr type_id_t first_custom_type_id = 200;
/// Checks whether `type_id` is specialized for `T`.
template <class T>
constexpr bool has_type_id = detail::is_complete<type_id<T>>;
} // namespace caf } // namespace caf
/// Starts a code block for registering custom types to CAF. Stores the first ID /// Starts a code block for registering custom types to CAF. Stores the first ID
...@@ -243,6 +248,7 @@ CAF_BEGIN_TYPE_ID_BLOCK(core_module, 0) ...@@ -243,6 +248,7 @@ CAF_BEGIN_TYPE_ID_BLOCK(core_module, 0)
CAF_ADD_TYPE_ID(core_module, (caf::downstream_msg)) CAF_ADD_TYPE_ID(core_module, (caf::downstream_msg))
CAF_ADD_TYPE_ID(core_module, (caf::error)) CAF_ADD_TYPE_ID(core_module, (caf::error))
CAF_ADD_TYPE_ID(core_module, (caf::exit_msg)) CAF_ADD_TYPE_ID(core_module, (caf::exit_msg))
CAF_ADD_TYPE_ID(core_module, (caf::exit_reason))
CAF_ADD_TYPE_ID(core_module, (caf::group)) CAF_ADD_TYPE_ID(core_module, (caf::group))
CAF_ADD_TYPE_ID(core_module, (caf::group_down_msg)) CAF_ADD_TYPE_ID(core_module, (caf::group_down_msg))
CAF_ADD_TYPE_ID(core_module, (caf::message)) CAF_ADD_TYPE_ID(core_module, (caf::message))
...@@ -250,6 +256,8 @@ CAF_BEGIN_TYPE_ID_BLOCK(core_module, 0) ...@@ -250,6 +256,8 @@ CAF_BEGIN_TYPE_ID_BLOCK(core_module, 0)
CAF_ADD_TYPE_ID(core_module, (caf::node_down_msg)) CAF_ADD_TYPE_ID(core_module, (caf::node_down_msg))
CAF_ADD_TYPE_ID(core_module, (caf::node_id)) CAF_ADD_TYPE_ID(core_module, (caf::node_id))
CAF_ADD_TYPE_ID(core_module, (caf::open_stream_msg)) CAF_ADD_TYPE_ID(core_module, (caf::open_stream_msg))
CAF_ADD_TYPE_ID(core_module, (caf::pec))
CAF_ADD_TYPE_ID(core_module, (caf::sec))
CAF_ADD_TYPE_ID(core_module, (caf::strong_actor_ptr)) CAF_ADD_TYPE_ID(core_module, (caf::strong_actor_ptr))
CAF_ADD_TYPE_ID(core_module, (caf::timeout_msg)) CAF_ADD_TYPE_ID(core_module, (caf::timeout_msg))
CAF_ADD_TYPE_ID(core_module, (caf::timespan)) CAF_ADD_TYPE_ID(core_module, (caf::timespan))
......
...@@ -364,12 +364,6 @@ actor_registry& actor_system::registry() { ...@@ -364,12 +364,6 @@ actor_registry& actor_system::registry() {
} }
std::string actor_system::render(const error& x) const { std::string actor_system::render(const error& x) const {
if (!x)
return to_string(x);
auto& xs = config().error_renderers;
auto i = xs.find(x.category());
if (i != xs.end())
return i->second(x.code(), x.context());
return to_string(x); return to_string(x);
} }
......
...@@ -136,10 +136,6 @@ actor_system_config::actor_system_config() ...@@ -136,10 +136,6 @@ actor_system_config::actor_system_config()
"path to an OpenSSL-style directory of trusted certificates") "path to an OpenSSL-style directory of trusted certificates")
.add<string>(openssl_cafile, "cafile", .add<string>(openssl_cafile, "cafile",
"path to a file of concatenated PEM-formatted certificates"); "path to a file of concatenated PEM-formatted certificates");
// add renderers for default error categories
add_error_category(error_category<sec>::value, render_sec);
add_error_category(error_category<pec>::value, render_pec);
add_error_category(error_category<exit_reason>::value, render_exit_reason);
} }
settings actor_system_config::dump_content() const { settings actor_system_config::dump_content() const {
...@@ -358,14 +354,8 @@ actor_system_config& actor_system_config::add_actor_factory(std::string name, ...@@ -358,14 +354,8 @@ actor_system_config& actor_system_config::add_actor_factory(std::string name,
return *this; return *this;
} }
actor_system_config& actor_system_config::add_error_category(uint8_t x, actor_system_config& actor_system_config::set_impl(string_view name,
error_renderer y) { config_value value) {
error_renderers[x] = y;
return *this;
}
actor_system_config&
actor_system_config::set_impl(string_view name, config_value value) {
if (name == "middleman.app-identifier") { if (name == "middleman.app-identifier") {
// TODO: Print a warning with 0.18 and remove this code with 0.19. // TODO: Print a warning with 0.18 and remove this code with 0.19.
value.convert_to_list(); value.convert_to_list();
...@@ -393,39 +383,9 @@ timespan actor_system_config::stream_tick_duration() const noexcept { ...@@ -393,39 +383,9 @@ timespan actor_system_config::stream_tick_duration() const noexcept {
stream_max_batch_delay.count()); stream_max_batch_delay.count());
return timespan{ns_count}; return timespan{ns_count};
} }
std::string actor_system_config::render(const error& x) {
if (!x)
return "none";
switch (x.category()) {
case error_category<sec>::value:
return render_sec(x.code(), x.context());
case error_category<exit_reason>::value:
return render_exit_reason(x.code(), x.context());
case error_category<pec>::value:
return render_pec(x.code(), x.context());
default:
return deep_to_string(meta::type_name("error"), x.code(), x.category(),
meta::omittable_if_empty(), x.context());
}
}
std::string actor_system_config::render_sec(uint8_t x, const message& xs) { std::string actor_system_config::render(const error& x) {
auto tmp = static_cast<sec>(x); return to_string(x);
return deep_to_string(meta::type_name("system_error"), tmp,
meta::omittable_if_empty(), xs);
}
std::string actor_system_config::render_exit_reason(uint8_t x,
const message& xs) {
auto tmp = static_cast<exit_reason>(x);
return deep_to_string(meta::type_name("exit_reason"), tmp,
meta::omittable_if_empty(), xs);
}
std::string actor_system_config::render_pec(uint8_t x, const message& xs) {
auto tmp = static_cast<pec>(x);
return deep_to_string(meta::type_name("parser_error"), tmp,
meta::omittable_if_empty(), xs);
} }
expected<settings> expected<settings>
......
...@@ -157,7 +157,7 @@ auto config_option_set::parse(settings& config, argument_iterator first, ...@@ -157,7 +157,7 @@ auto config_option_set::parse(settings& config, argument_iterator first,
auto val = opt.parse(slice); auto val = opt.parse(slice);
if (!val) { if (!val) {
auto& err = val.error(); auto& err = val.error();
if (err.category() == error_category<pec>::value) if (err.category() == type_id_v<pec>)
return static_cast<pec>(err.code()); return static_cast<pec>(err.code());
return pec::invalid_argument; return pec::invalid_argument;
} }
......
...@@ -22,155 +22,70 @@ ...@@ -22,155 +22,70 @@
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/deep_to_string.hpp" #include "caf/deep_to_string.hpp"
#include "caf/deserializer.hpp" #include "caf/deserializer.hpp"
#include "caf/detail/meta_object.hpp"
#include "caf/message.hpp" #include "caf/message.hpp"
#include "caf/serializer.hpp" #include "caf/serializer.hpp"
namespace caf { namespace caf {
// -- nested classes -----------------------------------------------------------
struct error::data {
uint8_t code;
uint8_t category;
message context;
};
// -- constructors, destructors, and assignment operators ---------------------- // -- constructors, destructors, and assignment operators ----------------------
error::error() noexcept : data_(nullptr) {
// nop
}
error::error(none_t) noexcept : data_(nullptr) { error::error(none_t) noexcept : data_(nullptr) {
// nop // nop
} }
error::error(error&& x) noexcept : data_(x.data_) {
if (data_ != nullptr)
x.data_ = nullptr;
}
error& error::operator=(error&& x) noexcept {
if (this != &x)
std::swap(data_, x.data_);
return *this;
}
error::error(const error& x) : data_(x ? new data(*x.data_) : nullptr) { error::error(const error& x) : data_(x ? new data(*x.data_) : nullptr) {
// nop // nop
} }
error& error::operator=(const error& x) { error& error::operator=(const error& x) {
if (this == &x)
return *this;
if (x) { if (x) {
if (data_ == nullptr) if (data_ == nullptr)
data_ = new data(*x.data_); data_.reset(new data(*x.data_));
else else
*data_ = *x.data_; *data_ = *x.data_;
} else { } else {
clear(); data_.reset();
} }
return *this; return *this;
} }
error::error(uint8_t x, uint8_t y) error::error(uint8_t code, type_id_t category)
: data_(x != 0 ? new data{x, y, message{}} : nullptr) { : error(code, category, message{}) {
// nop // nop
} }
error::error(uint8_t x, uint8_t y, message z) error::error(uint8_t code, type_id_t category, message context)
: data_(x != 0 ? new data{x, y, std::move(z)} : nullptr) { : data_(code != 0 ? new data{code, category, std::move(context)} : nullptr) {
// nop // nop
} }
error::~error() {
delete data_;
}
// -- observers ---------------------------------------------------------------- // -- observers ----------------------------------------------------------------
uint8_t error::code() const noexcept {
CAF_ASSERT(data_ != nullptr);
return data_->code;
}
uint8_t error::category() const noexcept {
CAF_ASSERT(data_ != nullptr);
return data_->category;
}
const message& error::context() const noexcept {
CAF_ASSERT(data_ != nullptr);
return data_->context;
}
int error::compare(const error& x) const noexcept { int error::compare(const error& x) const noexcept {
uint8_t x_code; return x ? compare(x.data_->code, x.data_->category) : compare(0, 0);
uint8_t x_category;
if (x) {
x_code = x.data_->code;
x_category = x.data_->category;
} else {
x_code = 0;
x_category = 0;
}
return compare(x_code, x_category);
}
int error::compare(uint8_t x, uint8_t y) const noexcept {
uint8_t mx;
uint8_t my;
if (data_ != nullptr) {
mx = data_->code;
my = data_->category;
} else {
mx = 0;
my = 0;
}
// all errors with default value are considered no error -> equal
if (mx == x && x == 0)
return 0;
if (my < y)
return -1;
if (my > y)
return 1;
return static_cast<int>(mx) - x;
}
// -- modifiers --------------------------------------------------------------
message& error::context() noexcept {
CAF_ASSERT(data_ != nullptr);
return data_->context;
} }
void error::clear() noexcept { int error::compare(uint8_t code, type_id_t category) const noexcept {
if (data_ != nullptr) { int x = 0;
delete data_; if (data_ != nullptr)
data_ = nullptr; x = (data_->code << 16) | data_->category;
} return x - int{(code << 16) | category};
} }
// -- inspection support ----------------------------------------------------- // -- inspection support -----------------------------------------------------
uint8_t& error::code_ref() noexcept {
CAF_ASSERT(data_ != nullptr);
return data_->code;
}
uint8_t& error::category_ref() noexcept {
CAF_ASSERT(data_ != nullptr);
return data_->category;
}
void error::init() {
if (data_ == nullptr)
data_ = new data;
}
std::string to_string(const error& x) { std::string to_string(const error& x) {
return actor_system_config::render(x); if (!x)
return "none";
std::string result;
auto code = x.code();
auto mobj = detail::global_meta_object(x.category());
mobj->stringify(result, &code);
auto ctx = x.context();
if (ctx)
result += to_string(ctx);
return result;
} }
} // namespace caf } // namespace caf
...@@ -54,11 +54,11 @@ CAF_TEST(serialization roundtrips go through the registry) { ...@@ -54,11 +54,11 @@ CAF_TEST(serialization roundtrips go through the registry) {
byte_buffer buf; byte_buffer buf;
binary_serializer sink{sys, buf}; binary_serializer sink{sys, buf};
if (auto err = sink(hdl)) if (auto err = sink(hdl))
CAF_FAIL("serialization failed: " << sys.render(err)); CAF_FAIL("serialization failed: " << to_string(err));
actor hdl2; actor hdl2;
binary_deserializer source{sys, buf}; binary_deserializer source{sys, buf};
if (auto err = source(hdl2)) if (auto err = source(hdl2))
CAF_FAIL("serialization failed: " << sys.render(err)); CAF_FAIL("serialization failed: " << to_string(err));
CAF_CHECK_EQUAL(hdl, hdl2); CAF_CHECK_EQUAL(hdl, hdl2);
anon_send_exit(hdl, exit_reason::user_shutdown); anon_send_exit(hdl, exit_reason::user_shutdown);
} }
......
...@@ -71,7 +71,7 @@ struct fixture { ...@@ -71,7 +71,7 @@ struct fixture {
cfg.remainder.clear(); cfg.remainder.clear();
std::istringstream ini{file_content}; std::istringstream ini{file_content};
if (auto err = cfg.parse(std::move(args), ini)) if (auto err = cfg.parse(std::move(args), ini))
CAF_FAIL("parse() failed: " << cfg.render(err)); CAF_FAIL("parse() failed: " << err);
} }
}; };
......
...@@ -49,8 +49,7 @@ struct fixture { ...@@ -49,8 +49,7 @@ struct fixture {
auto result = T{}; auto result = T{};
binary_deserializer source{nullptr, buf}; binary_deserializer source{nullptr, buf};
if (auto err = source(result)) if (auto err = source(result))
CAF_FAIL("binary_deserializer failed to load: " CAF_FAIL("binary_deserializer failed to load: " << err);
<< actor_system_config::render(err));
return result; return result;
} }
...@@ -58,8 +57,7 @@ struct fixture { ...@@ -58,8 +57,7 @@ struct fixture {
void load(const std::vector<byte>& buf, Ts&... xs) { void load(const std::vector<byte>& buf, Ts&... xs) {
binary_deserializer source{nullptr, buf}; binary_deserializer source{nullptr, buf};
if (auto err = source(xs...)) if (auto err = source(xs...))
CAF_FAIL("binary_deserializer failed to load: " CAF_FAIL("binary_deserializer failed to load: " << err);
<< actor_system_config::render(err));
} }
}; };
......
...@@ -49,8 +49,7 @@ struct fixture { ...@@ -49,8 +49,7 @@ struct fixture {
byte_buffer result; byte_buffer result;
binary_serializer sink{nullptr, result}; binary_serializer sink{nullptr, result};
if (auto err = sink(xs...)) if (auto err = sink(xs...))
CAF_FAIL("binary_serializer failed to save: " CAF_FAIL("binary_serializer failed to save: " << err);
<< actor_system_config::render(err));
return result; return result;
} }
...@@ -58,8 +57,7 @@ struct fixture { ...@@ -58,8 +57,7 @@ struct fixture {
void save_to_buf(byte_buffer& data, const Ts&... xs) { void save_to_buf(byte_buffer& data, const Ts&... xs) {
binary_serializer sink{nullptr, data}; binary_serializer sink{nullptr, data};
if (auto err = sink(xs...)) if (auto err = sink(xs...))
CAF_FAIL("binary_serializer failed to save: " CAF_FAIL("binary_serializer failed to save: " << err);
<< actor_system_config::render(err));
} }
}; };
......
...@@ -221,7 +221,7 @@ CAF_TEST(adaptor access from actor system config - file input) { ...@@ -221,7 +221,7 @@ CAF_TEST(adaptor access from actor system config - file input) {
test_config cfg; test_config cfg;
std::istringstream in{config_text}; std::istringstream in{config_text};
if (auto err = cfg.parse(0, nullptr, in)) if (auto err = cfg.parse(0, nullptr, in))
CAF_FAIL("cfg.parse failed: " << cfg.render(err)); CAF_FAIL("cfg.parse failed: " << err);
CAF_CHECK_EQUAL(cfg.max_delay, my_duration::from_s(123)); CAF_CHECK_EQUAL(cfg.max_delay, my_duration::from_s(123));
} }
...@@ -232,7 +232,7 @@ CAF_TEST(adaptor access from actor system config - file input and arguments) { ...@@ -232,7 +232,7 @@ CAF_TEST(adaptor access from actor system config - file input and arguments) {
test_config cfg; test_config cfg;
std::istringstream in{config_text}; std::istringstream in{config_text};
if (auto err = cfg.parse(std::move(args), in)) if (auto err = cfg.parse(std::move(args), in))
CAF_FAIL("cfg.parse failed: " << cfg.render(err)); CAF_FAIL("cfg.parse failed: " << err);
CAF_CHECK_EQUAL(cfg.max_delay, my_duration::from_ms(20)); CAF_CHECK_EQUAL(cfg.max_delay, my_duration::from_ms(20));
} }
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include "caf/all.hpp" #include "caf/all.hpp"
#define ERROR_HANDLER [&](error& err) { CAF_FAIL(system.render(err)); } #define ERROR_HANDLER [&](error& err) { CAF_FAIL(err); }
using namespace caf; using namespace caf;
......
...@@ -345,9 +345,7 @@ CAF_TEST(ranges can use signed integers) { ...@@ -345,9 +345,7 @@ CAF_TEST(ranges can use signed integers) {
if (auto res = r(expr)) { \ if (auto res = r(expr)) { \
CAF_FAIL("expected expression to produce to an error"); \ CAF_FAIL("expected expression to produce to an error"); \
} else { \ } else { \
auto& err = res.error(); \ CAF_CHECK_EQUAL(res.error(), enum_value); \
CAF_CHECK(err.category() == error_category<pec>::value); \
CAF_CHECK_EQUAL(err.code(), static_cast<uint8_t>(enum_value)); \
} }
CAF_TEST(the parser rejects invalid step values) { CAF_TEST(the parser rejects invalid step values) {
......
...@@ -40,7 +40,7 @@ struct fixture : test_coordinator_fixture<> { ...@@ -40,7 +40,7 @@ struct fixture : test_coordinator_fixture<> {
byte_buffer buf; byte_buffer buf;
binary_serializer sink{sys, buf}; binary_serializer sink{sys, buf};
if (auto err = sink(xs...)) if (auto err = sink(xs...))
CAF_FAIL("failed to serialize data: " << sys.render(err)); CAF_FAIL("failed to serialize data: " << err);
return buf.size(); return buf.size();
} }
}; };
......
...@@ -30,13 +30,13 @@ CAF_TEST(default constructed errors evaluate to false) { ...@@ -30,13 +30,13 @@ CAF_TEST(default constructed errors evaluate to false) {
} }
CAF_TEST(error code zero is not an error) { CAF_TEST(error code zero is not an error) {
CAF_CHECK(!error(0, error_category<sec>::value)); CAF_CHECK(!error(sec::none));
CAF_CHECK(!make_error(sec::none)); CAF_CHECK(!make_error(sec::none));
CAF_CHECK(!error{error_code<sec>(sec::none)}); CAF_CHECK(!error{error_code<sec>(sec::none)});
} }
CAF_TEST(error codes that are not zero are errors) { CAF_TEST(error codes that are not zero are errors) {
CAF_CHECK(error(1, error_category<sec>::value)); CAF_CHECK(error(sec::unexpected_message));
CAF_CHECK(make_error(sec::unexpected_message)); CAF_CHECK(make_error(sec::unexpected_message));
CAF_CHECK(error{error_code<sec>(sec::unexpected_message)}); CAF_CHECK(error{error_code<sec>(sec::unexpected_message)});
} }
......
...@@ -55,11 +55,11 @@ struct fixture { ...@@ -55,11 +55,11 @@ struct fixture {
byte_buffer buf; byte_buffer buf;
binary_serializer sink(sys, buf); binary_serializer sink(sys, buf);
if (auto err = sink(x)) if (auto err = sink(x))
CAF_FAIL("serialization failed: " << sys.render(err)); CAF_FAIL("serialization failed: " << err);
binary_deserializer source(sys, make_span(buf)); binary_deserializer source(sys, make_span(buf));
T y; T y;
if (auto err = source(y)) if (auto err = source(y))
CAF_FAIL("deserialization failed: " << sys.render(err)); CAF_FAIL("deserialization failed: " << err);
return y; return y;
} }
}; };
......
...@@ -55,11 +55,11 @@ struct fixture { ...@@ -55,11 +55,11 @@ struct fixture {
byte_buffer buf; byte_buffer buf;
binary_serializer sink(sys, buf); binary_serializer sink(sys, buf);
if (auto err = sink(x)) if (auto err = sink(x))
CAF_FAIL("serialization failed: " << sys.render(err)); CAF_FAIL("serialization failed: " << err);
binary_deserializer source(sys, make_span(buf)); binary_deserializer source(sys, make_span(buf));
T y; T y;
if (auto err = source(y)) if (auto err = source(y))
CAF_FAIL("deserialization failed: " << sys.render(err)); CAF_FAIL("deserialization failed: " << err);
return y; return y;
} }
}; };
......
...@@ -291,7 +291,7 @@ CAF_TEST(object access from actor system config - file input) { ...@@ -291,7 +291,7 @@ CAF_TEST(object access from actor system config - file input) {
test_config cfg; test_config cfg;
std::istringstream in{config_text}; std::istringstream in{config_text};
if (auto err = cfg.parse(0, nullptr, in)) if (auto err = cfg.parse(0, nullptr, in))
CAF_FAIL("cfg.parse failed: " << cfg.render(err)); CAF_FAIL("cfg.parse failed: " << err);
CAF_CHECK_EQUAL(cfg.fb.foo, 42); CAF_CHECK_EQUAL(cfg.fb.foo, 42);
CAF_CHECK_EQUAL(cfg.fb.bar, "Don't panic!"); CAF_CHECK_EQUAL(cfg.fb.bar, "Don't panic!");
CAF_CHECK_EQUAL(cfg.fbfb.x.foo, 1); CAF_CHECK_EQUAL(cfg.fbfb.x.foo, 1);
...@@ -308,7 +308,7 @@ CAF_TEST(object access from actor system config - file input and arguments) { ...@@ -308,7 +308,7 @@ CAF_TEST(object access from actor system config - file input and arguments) {
test_config cfg; test_config cfg;
std::istringstream in{config_text}; std::istringstream in{config_text};
if (auto err = cfg.parse(std::move(args), in)) if (auto err = cfg.parse(std::move(args), in))
CAF_FAIL("cfg.parse failed: " << cfg.render(err)); CAF_FAIL("cfg.parse failed: " << err);
CAF_CHECK_EQUAL(cfg.fb.foo, 42); CAF_CHECK_EQUAL(cfg.fb.foo, 42);
CAF_CHECK_EQUAL(cfg.fb.bar, "Don't panic!"); CAF_CHECK_EQUAL(cfg.fb.bar, "Don't panic!");
CAF_CHECK_EQUAL(cfg.fbfb.x.foo, 10); CAF_CHECK_EQUAL(cfg.fbfb.x.foo, 10);
......
...@@ -74,7 +74,7 @@ struct fixture : test_coordinator_fixture<> { ...@@ -74,7 +74,7 @@ struct fixture : test_coordinator_fixture<> {
} // namespace } // namespace
#define ERROR_HANDLER [&](error& err) { CAF_FAIL(sys.render(err)); } #define ERROR_HANDLER [&](error& err) { CAF_FAIL(err); }
#define SUBTEST(message) \ #define SUBTEST(message) \
*result = none; \ *result = none; \
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include "caf/all.hpp" #include "caf/all.hpp"
#define ERROR_HANDLER [&](error& err) { CAF_FAIL(system.render(err)); } #define ERROR_HANDLER [&](error& err) { CAF_FAIL(err); }
using namespace caf; using namespace caf;
......
...@@ -46,9 +46,7 @@ struct fixture : test_coordinator_fixture<> { ...@@ -46,9 +46,7 @@ struct fixture : test_coordinator_fixture<> {
} }
std::function<void(const error&)> make_error_handler() { std::function<void(const error&)> make_error_handler() {
return [this](const error& err) { return [](const error& err) { CAF_FAIL("unexpected error: " << err); };
CAF_FAIL("unexpected error: " << sys.render(err));
};
} }
std::function<void(const error&)> make_counting_error_handler(size_t* count) { std::function<void(const error&)> make_counting_error_handler(size_t* count) {
......
...@@ -44,9 +44,7 @@ struct fixture : test_coordinator_fixture<> { ...@@ -44,9 +44,7 @@ struct fixture : test_coordinator_fixture<> {
} }
auto make_error_handler() { auto make_error_handler() {
return [this](const error& err) { return [](const error& err) { CAF_FAIL("unexpected error: " << err); };
CAF_FAIL("unexpected error: " << sys.render(err));
};
} }
auto make_counting_error_handler(size_t* count) { auto make_counting_error_handler(size_t* count) {
......
...@@ -71,8 +71,6 @@ CAF_TEST(test_serial_reply) { ...@@ -71,8 +71,6 @@ CAF_TEST(test_serial_reply) {
CAF_MESSAGE("ID of main: " << self->id()); CAF_MESSAGE("ID of main: " << self->id());
self->request(master, infinite, hi_atom::value) self->request(master, infinite, hi_atom::value)
.receive([](ho_atom) { CAF_MESSAGE("received 'ho'"); }, .receive([](ho_atom) { CAF_MESSAGE("received 'ho'"); },
[&](const error& err) { [&](const error& err) { CAF_ERROR("Error: " << to_string(err)); });
CAF_ERROR("Error: " << self->system().render(err));
});
CAF_REQUIRE(self->mailbox().empty()); CAF_REQUIRE(self->mailbox().empty());
} }
...@@ -107,7 +107,7 @@ struct fixture : test_coordinator_fixture<> { ...@@ -107,7 +107,7 @@ struct fixture : test_coordinator_fixture<> {
binary_serializer sink{sys, buf}; binary_serializer sink{sys, buf};
if (auto err = sink(xs...)) if (auto err = sink(xs...))
CAF_FAIL("serialization failed: " CAF_FAIL("serialization failed: "
<< sys.render(err) << err
<< ", data: " << deep_to_string(std::forward_as_tuple(xs...))); << ", data: " << deep_to_string(std::forward_as_tuple(xs...)));
return buf; return buf;
} }
...@@ -116,7 +116,7 @@ struct fixture : test_coordinator_fixture<> { ...@@ -116,7 +116,7 @@ struct fixture : test_coordinator_fixture<> {
void deserialize(const byte_buffer& buf, Ts&... xs) { void deserialize(const byte_buffer& buf, Ts&... xs) {
binary_deserializer source{sys, buf}; binary_deserializer source{sys, buf};
if (auto err = source(xs...)) if (auto err = source(xs...))
CAF_FAIL("deserialization failed: " << sys.render(err)); CAF_FAIL("deserialization failed: " << err);
} }
// serializes `x` and then deserializes and returns the serialized value // serializes `x` and then deserializes and returns the serialized value
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
# include "caf/all.hpp" # include "caf/all.hpp"
# define ERROR_HANDLER [&](error& err) { CAF_FAIL(sys.render(err)); } # define ERROR_HANDLER [&](error& err) { CAF_FAIL(err); }
using std::string; using std::string;
......
...@@ -95,12 +95,12 @@ using v20 = variant<i01, i02, i03, i04, i05, i06, i07, i08, i09, i10, ...@@ -95,12 +95,12 @@ using v20 = variant<i01, i02, i03, i04, i05, i06, i07, i08, i09, i10,
byte_buffer buf; \ byte_buffer buf; \
binary_serializer sink{sys.dummy_execution_unit(), buf}; \ binary_serializer sink{sys.dummy_execution_unit(), buf}; \
if (auto err = sink(x3)) \ if (auto err = sink(x3)) \
CAF_FAIL("failed to serialize data: " << sys.render(err)); \ CAF_FAIL("failed to serialize data: " << err); \
CAF_CHECK_EQUAL(x3, i##n{0x##n}); \ CAF_CHECK_EQUAL(x3, i##n{0x##n}); \
v20 tmp; \ v20 tmp; \
binary_deserializer source{sys.dummy_execution_unit(), buf}; \ binary_deserializer source{sys.dummy_execution_unit(), buf}; \
if (auto err = source(tmp)) \ if (auto err = source(tmp)) \
CAF_FAIL("failed to deserialize data: " << sys.render(err)); \ CAF_FAIL("failed to deserialize data: " << err); \
CAF_CHECK_EQUAL(tmp, i##n{0x##n}); \ CAF_CHECK_EQUAL(tmp, i##n{0x##n}); \
CAF_CHECK_EQUAL(tmp, x3); \ CAF_CHECK_EQUAL(tmp, x3); \
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "caf/meta/load_callback.hpp" #include "caf/meta/load_callback.hpp"
#include "caf/meta/save_callback.hpp" #include "caf/meta/save_callback.hpp"
#include "caf/meta/type_name.hpp" #include "caf/meta/type_name.hpp"
#include "caf/sec.hpp"
struct sockaddr; struct sockaddr;
struct sockaddr_storage; struct sockaddr_storage;
......
...@@ -318,7 +318,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl, ...@@ -318,7 +318,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
std::set<std::string> sigs; std::set<std::string> sigs;
if (auto err = bd(source_node, app_ids, aid, sigs)) { if (auto err = bd(source_node, app_ids, aid, sigs)) {
CAF_LOG_WARNING("unable to deserialize payload of server handshake:" CAF_LOG_WARNING("unable to deserialize payload of server handshake:"
<< ctx->system().render(err)); << to_string(err));
return serializing_basp_payload_failed; return serializing_basp_payload_failed;
} }
// Check the application ID. // Check the application ID.
...@@ -367,7 +367,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl, ...@@ -367,7 +367,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
node_id source_node; node_id source_node;
if (auto err = bd(source_node)) { if (auto err = bd(source_node)) {
CAF_LOG_WARNING("unable to deserialize payload of client handshake:" CAF_LOG_WARNING("unable to deserialize payload of client handshake:"
<< ctx->system().render(err)); << to_string(err));
return serializing_basp_payload_failed; return serializing_basp_payload_failed;
} }
// Drop repeated handshakes. // Drop repeated handshakes.
...@@ -391,7 +391,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl, ...@@ -391,7 +391,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
if (auto err = bd(source_node, dest_node)) { if (auto err = bd(source_node, dest_node)) {
CAF_LOG_WARNING( CAF_LOG_WARNING(
"unable to deserialize source and destination for routed message:" "unable to deserialize source and destination for routed message:"
<< ctx->system().render(err)); << to_string(err));
return serializing_basp_payload_failed; return serializing_basp_payload_failed;
} }
if (dest_node != this_node_) { if (dest_node != this_node_) {
...@@ -449,7 +449,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl, ...@@ -449,7 +449,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
node_id dest_node; node_id dest_node;
if (auto err = bd(source_node, dest_node)) { if (auto err = bd(source_node, dest_node)) {
CAF_LOG_WARNING("unable to deserialize payload of monitor message:" CAF_LOG_WARNING("unable to deserialize payload of monitor message:"
<< ctx->system().render(err)); << to_string(err));
return serializing_basp_payload_failed; return serializing_basp_payload_failed;
} }
if (dest_node == this_node_) if (dest_node == this_node_)
...@@ -465,8 +465,8 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl, ...@@ -465,8 +465,8 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
node_id dest_node; node_id dest_node;
error fail_state; error fail_state;
if (auto err = bd(source_node, dest_node, fail_state)) { if (auto err = bd(source_node, dest_node, fail_state)) {
CAF_LOG_WARNING("unable to deserialize payload of down message:" CAF_LOG_WARNING(
<< ctx->system().render(err)); "unable to deserialize payload of down message:" << to_string(err));
return serializing_basp_payload_failed; return serializing_basp_payload_failed;
} }
if (dest_node == this_node_) { if (dest_node == this_node_) {
......
...@@ -161,7 +161,7 @@ public: ...@@ -161,7 +161,7 @@ public:
byte_buffer buf; byte_buffer buf;
binary_serializer bs{mpx_, buf}; binary_serializer bs{mpx_, buf};
if (auto err = bs(const_cast<message&>(msg))) if (auto err = bs(const_cast<message&>(msg)))
CAF_FAIL("returned to serialize message: " << sys.render(err)); CAF_FAIL("returned to serialize message: " << err);
return static_cast<uint32_t>(buf.size()); return static_cast<uint32_t>(buf.size());
} }
...@@ -219,7 +219,7 @@ public: ...@@ -219,7 +219,7 @@ public:
void to_payload(byte_buffer& buf, const Ts&... xs) { void to_payload(byte_buffer& buf, const Ts&... xs) {
binary_serializer sink{mpx_, buf}; binary_serializer sink{mpx_, buf};
if (auto err = sink(xs...)) if (auto err = sink(xs...))
CAF_FAIL("failed to serialize payload: " << sys.render(err)); CAF_FAIL("failed to serialize payload: " << err);
} }
void to_buf(byte_buffer& buf, basp::header& hdr, payload_writer* writer) { void to_buf(byte_buffer& buf, basp::header& hdr, payload_writer* writer) {
...@@ -347,8 +347,7 @@ public: ...@@ -347,8 +347,7 @@ public:
{ // lifetime scope of source { // lifetime scope of source
binary_deserializer source{this_->mpx(), ob}; binary_deserializer source{this_->mpx(), ob};
if (auto err = source(hdr)) if (auto err = source(hdr))
CAF_FAIL("unable to deserialize header: " CAF_FAIL("unable to deserialize header: " << err);
<< actor_system_config::render(err));
} }
byte_buffer payload; byte_buffer payload;
if (hdr.payload_len > 0) { if (hdr.payload_len > 0) {
...@@ -485,7 +484,7 @@ CAF_TEST(non_empty_server_handshake) { ...@@ -485,7 +484,7 @@ CAF_TEST(non_empty_server_handshake) {
std::set<std::string> ifs{"caf::replies_to<@u16>::with<@u16>"}; std::set<std::string> ifs{"caf::replies_to<@u16>::with<@u16>"};
binary_serializer sink{nullptr, expected_payload}; binary_serializer sink{nullptr, expected_payload};
if (auto err = sink(instance().this_node(), app_ids, self()->id(), ifs)) if (auto err = sink(instance().this_node(), app_ids, self()->id(), ifs))
CAF_FAIL("serializing handshake failed: " << sys.render(err)); CAF_FAIL("serializing handshake failed: " << err);
CAF_CHECK_EQUAL(hexstr(payload), hexstr(expected_payload)); CAF_CHECK_EQUAL(hexstr(payload), hexstr(expected_payload));
} }
...@@ -608,7 +607,7 @@ CAF_TEST(remote_actor_and_send) { ...@@ -608,7 +607,7 @@ CAF_TEST(remote_actor_and_send) {
CAF_REQUIRE(proxy == res); CAF_REQUIRE(proxy == res);
result = actor_cast<actor>(res); result = actor_cast<actor>(res);
}, },
[&](error& err) { CAF_FAIL("error: " << sys.render(err)); }); [&](error& err) { CAF_FAIL("error: " << err); });
CAF_MESSAGE("send message to proxy"); CAF_MESSAGE("send message to proxy");
anon_send(actor_cast<actor>(result), 42); anon_send(actor_cast<actor>(result), 42);
mpx()->flush_runnables(); mpx()->flush_runnables();
......
...@@ -50,7 +50,7 @@ struct fixture : test_coordinator_fixture<> { ...@@ -50,7 +50,7 @@ struct fixture : test_coordinator_fixture<> {
byte_buffer buf; byte_buffer buf;
binary_serializer sink{sys, buf}; binary_serializer sink{sys, buf};
if (auto err = sink(x, xs...)) if (auto err = sink(x, xs...))
CAF_FAIL("serialization failed: " << sys.render(err)); CAF_FAIL("serialization failed: " << err);
return buf; return buf;
} }
...@@ -58,7 +58,7 @@ struct fixture : test_coordinator_fixture<> { ...@@ -58,7 +58,7 @@ struct fixture : test_coordinator_fixture<> {
void deserialize(const Buffer& buf, T& x, Ts&... xs) { void deserialize(const Buffer& buf, T& x, Ts&... xs) {
binary_deserializer source{sys, buf}; binary_deserializer source{sys, buf};
if (auto err = source(x, xs...)) if (auto err = source(x, xs...))
CAF_FAIL("serialization failed: " << sys.render(err)); CAF_FAIL("serialization failed: " << err);
} }
}; };
......
...@@ -109,7 +109,7 @@ CAF_TEST(deliver serialized message) { ...@@ -109,7 +109,7 @@ CAF_TEST(deliver serialized message) {
std::vector<strong_actor_ptr> stages; std::vector<strong_actor_ptr> stages;
binary_serializer sink{sys, payload}; binary_serializer sink{sys, payload};
if (auto err = sink(stages, make_message(ok_atom_v))) if (auto err = sink(stages, make_message(ok_atom_v)))
CAF_FAIL("unable to serialize message: " << sys.render(err)); CAF_FAIL("unable to serialize message: " << err);
io::basp::header hdr{io::basp::message_type::direct_message, io::basp::header hdr{io::basp::message_type::direct_message,
0, 0,
static_cast<uint32_t>(payload.size()), static_cast<uint32_t>(payload.size()),
......
...@@ -646,9 +646,7 @@ struct test_coordinator_fixture_fetch_helper { ...@@ -646,9 +646,7 @@ struct test_coordinator_fixture_fetch_helper {
operator()(caf::response_handle<Self, Policy<Interface>>& from) const { operator()(caf::response_handle<Self, Policy<Interface>>& from) const {
std::tuple<Ts...> result; std::tuple<Ts...> result;
from.receive([&](Ts&... xs) { result = std::make_tuple(std::move(xs)...); }, from.receive([&](Ts&... xs) { result = std::make_tuple(std::move(xs)...); },
[&](caf::error& err) { [&](caf::error& err) { CAF_FAIL(err); });
FAIL(from.self()->system().render(err));
});
return result; return result;
} }
}; };
...@@ -659,9 +657,7 @@ struct test_coordinator_fixture_fetch_helper<T> { ...@@ -659,9 +657,7 @@ struct test_coordinator_fixture_fetch_helper<T> {
T operator()(caf::response_handle<Self, Policy<Interface>>& from) const { T operator()(caf::response_handle<Self, Policy<Interface>>& from) const {
T result; T result;
from.receive([&](T& x) { result = std::move(x); }, from.receive([&](T& x) { result = std::move(x); },
[&](caf::error& err) { [&](caf::error& err) { CAF_FAIL(err); });
FAIL(from.self()->system().render(err));
});
return result; return result;
} }
}; };
...@@ -845,7 +841,7 @@ public: ...@@ -845,7 +841,7 @@ public:
caf::byte_buffer buf; caf::byte_buffer buf;
caf::binary_serializer sink{sys, buf}; caf::binary_serializer sink{sys, buf};
if (auto err = sink(xs...)) if (auto err = sink(xs...))
CAF_FAIL("serialization failed: " << sys.render(err)); CAF_FAIL("serialization failed: " << err);
return buf; return buf;
} }
...@@ -853,7 +849,7 @@ public: ...@@ -853,7 +849,7 @@ public:
void deserialize(const caf::byte_buffer& buf, Ts&... xs) { void deserialize(const caf::byte_buffer& buf, Ts&... xs) {
caf::binary_deserializer source{sys, buf}; caf::binary_deserializer source{sys, buf};
if (auto err = source(xs...)) if (auto err = source(xs...))
CAF_FAIL("deserialization failed: " << sys.render(err)); CAF_FAIL("deserialization failed: " << err);
} }
template <class T> template <class T>
......
...@@ -274,8 +274,8 @@ construction arguments passed as message can mismatch, this version of ...@@ -274,8 +274,8 @@ construction arguments passed as message can mismatch, this version of
auto x = system.spawn<calculator>("calculator", make_message()); auto x = system.spawn<calculator>("calculator", make_message());
if (! x) { if (! x) {
std::cerr << "*** unable to spawn calculator: " std::cerr << "*** unable to spawn calculator: " << to_string(x.error())
<< system.render(x.error()) << std::endl; << std::endl;
return; return;
} }
calculator c = std::move(*x); calculator c = std::move(*x);
......
...@@ -14,8 +14,8 @@ name, joining, and leaving. ...@@ -14,8 +14,8 @@ name, joining, and leaving.
std::string id = "foo"; std::string id = "foo";
auto expected_grp = system.groups().get(module, id); auto expected_grp = system.groups().get(module, id);
if (! expected_grp) { if (! expected_grp) {
std::cerr << "*** cannot load group: " std::cerr << "*** cannot load group: " << to_string(expected_grp.error())
<< system.render(expected_grp.error()) << std::endl; << std::endl;
return; return;
} }
auto grp = std::move(*expected_grp); auto grp = std::move(*expected_grp);
......
...@@ -92,12 +92,10 @@ connect to the published actor by calling ``remote_actor``: ...@@ -92,12 +92,10 @@ connect to the published actor by calling ``remote_actor``:
// node B // node B
auto ping = system.middleman().remote_actor("node A", 4242); auto ping = system.middleman().remote_actor("node A", 4242);
if (! ping) { if (!ping)
cerr << "unable to connect to node A: " cerr << "unable to connect to node A: " << to_string(ping.error()) << '\n';
<< system.render(ping.error()) << std::endl; else
} else {
self->send(*ping, ping_atom::value); self->send(*ping, ping_atom::value);
}
There is no difference between server and client after the connection phase. There is no difference between server and client after the connection phase.
Remote actors use the same handle types as local actors and are thus fully Remote actors use the same handle types as local actors and are thus fully
......
...@@ -99,7 +99,7 @@ as ``CAF_CHECK`` and provide tests rather than implementing a ...@@ -99,7 +99,7 @@ as ``CAF_CHECK`` and provide tests rather than implementing a
}, },
[&](caf::error& err) { [&](caf::error& err) {
// Must not happen, stop test. // Must not happen, stop test.
CAF_FAIL(sys.render(err)); CAF_FAIL(err);
}); });
} }
......
...@@ -161,8 +161,8 @@ void bootstrap(actor_system& system, const string& wdir, ...@@ -161,8 +161,8 @@ void bootstrap(actor_system& system, const string& wdir,
// possible addresses slaves can use to connect to us // possible addresses slaves can use to connect to us
auto port_res = system.middleman().publish(self, 0); auto port_res = system.middleman().publish(self, 0);
if (!port_res) { if (!port_res) {
cerr << "fatal: unable to publish actor: " cerr << "fatal: unable to publish actor: " << to_string(port_res.error())
<< system.render(port_res.error()) << endl; << endl;
return; return;
} }
auto port = *port_res; auto port = *port_res;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment