Commit f6d2a84c authored by Dominik Charousset's avatar Dominik Charousset

Remove automated demangling, close #205

CAF no longer automatically tries to demangle platform-dependent type name
representations as returned by `typeid(...).name()`. Although this is a nice
convenience feature in theory, there are to many issues attached to it,
including broken ABI versions on some platforms. Instead of automatically
computing the uniform type name at runtime, users of CAF now need to pass it to
`announce`. This is a breaking change, as the signature of `announce` has been
changed to take a string as first argument.
parent e314976b
...@@ -80,9 +80,10 @@ void tester(event_based_actor* self, const calculator_type& testee) { ...@@ -80,9 +80,10 @@ void tester(event_based_actor* self, const calculator_type& testee) {
int main() { int main() {
// announce custom message types // announce custom message types
announce<shutdown_request>(); announce<shutdown_request>("shutdown_request");
announce<plus_request>(&plus_request::a, &plus_request::b); announce<plus_request>("plus_request", &plus_request::a, &plus_request::b);
announce<minus_request>(&minus_request::a, &minus_request::b); announce<minus_request>("minus_request", &minus_request::a,
&minus_request::b);
// test function-based impl // test function-based impl
spawn(tester, spawn_typed(typed_calculator)); spawn(tester, spawn_typed(typed_calculator));
await_all_actors_done(); await_all_actors_done();
......
...@@ -77,11 +77,11 @@ int main(int, char**) { ...@@ -77,11 +77,11 @@ int main(int, char**) {
// announces foo to the libcaf type system; // announces foo to the libcaf type system;
// the function expects member pointers to all elements of foo // the function expects member pointers to all elements of foo
announce<foo>(&foo::a, &foo::b); announce<foo>("foo", &foo::a, &foo::b);
// announce foo2 to the libcaf type system, // announce foo2 to the libcaf type system,
// note that recursive containers are managed automatically by libcaf // note that recursive containers are managed automatically by libcaf
announce<foo2>(&foo2::a, &foo2::b); announce<foo2>("foo2", &foo2::a, &foo2::b);
foo2 vd; foo2 vd;
vd.a = 5; vd.a = 5;
...@@ -98,17 +98,11 @@ int main(int, char**) { ...@@ -98,17 +98,11 @@ int main(int, char**) {
assert(vd == vd2); assert(vd == vd2);
// announce std::pair<int, int> to the type system; // announce std::pair<int, int> to the type system
// NOTE: foo_pair is NOT distinguishable from foo_pair2! announce<foo_pair>("foo_pair", &foo_pair::first, &foo_pair::second);
auto uti = announce<foo_pair>(&foo_pair::first, &foo_pair::second);
// since foo_pair and foo_pair2 are not distinguishable since typedefs
// do not 'create' an own type, this announce fails, since
// std::pair<int, int> is already announced
assert(announce<foo_pair2>(&foo_pair2::first, &foo_pair2::second) == uti);
// libcaf returns the same uniform_type_info // libcaf returns the same uniform_type_info
// instance for foo_pair and foo_pair2 // instance for the type aliases foo_pair and foo_pair2
assert(uniform_typeid<foo_pair>() == uniform_typeid<foo_pair2>()); assert(uniform_typeid<foo_pair>() == uniform_typeid<foo_pair2>());
// spawn a testee that receives two messages // spawn a testee that receives two messages
...@@ -124,4 +118,3 @@ int main(int, char**) { ...@@ -124,4 +118,3 @@ int main(int, char**) {
shutdown(); shutdown();
return 0; return 0;
} }
...@@ -54,7 +54,7 @@ void testee(event_based_actor* self) { ...@@ -54,7 +54,7 @@ void testee(event_based_actor* self) {
int main(int, char**) { int main(int, char**) {
// if a class uses getter and setter member functions, // if a class uses getter and setter member functions,
// we pass those to the announce function as { getter, setter } pairs. // we pass those to the announce function as { getter, setter } pairs.
announce<foo>(make_pair(&foo::a, &foo::set_a), announce<foo>("foo", make_pair(&foo::a, &foo::set_a),
make_pair(&foo::b, &foo::set_b)); make_pair(&foo::b, &foo::set_b));
{ {
scoped_actor self; scoped_actor self;
......
...@@ -68,11 +68,12 @@ int main(int, char**) { ...@@ -68,11 +68,12 @@ int main(int, char**) {
foo_setter s2 = &foo::b; foo_setter s2 = &foo::b;
// equal to example 3 // equal to example 3
announce<foo>(make_pair(g1, s1), make_pair(g2, s2)); announce<foo>("foo", make_pair(g1, s1), make_pair(g2, s2));
// alternative syntax that uses casts instead of variables // alternative syntax that uses casts instead of variables
// (returns false since foo is already announced) // (returns false since foo is already announced)
announce<foo>(make_pair(static_cast<foo_getter>(&foo::a), announce<foo>("foo",
make_pair(static_cast<foo_getter>(&foo::a),
static_cast<foo_setter>(&foo::a)), static_cast<foo_setter>(&foo::a)),
make_pair(static_cast<foo_getter>(&foo::b), make_pair(static_cast<foo_getter>(&foo::b),
static_cast<foo_setter>(&foo::b))); static_cast<foo_setter>(&foo::b)));
......
...@@ -108,23 +108,20 @@ int main(int, char**) { ...@@ -108,23 +108,20 @@ int main(int, char**) {
// it takes a pointer to the non-trivial member as first argument // it takes a pointer to the non-trivial member as first argument
// followed by all "sub-members" either as member pointer or // followed by all "sub-members" either as member pointer or
// { getter, setter } pair // { getter, setter } pair
announce<bar>(compound_member(&bar::f, auto meta_bar_f = [] {
return compound_member(&bar::f,
make_pair(&foo::a, &foo::set_a), make_pair(&foo::a, &foo::set_a),
make_pair(&foo::b, &foo::set_b)), make_pair(&foo::b, &foo::set_b));
&bar::i); };
// with meta_bar_f, we can now announce bar
announce<bar>("bar", meta_bar_f(), &bar::i);
// baz has non-trivial data members with getter/setter pair // baz has non-trivial data members with getter/setter pair
// and getter returning a mutable reference // and getter returning a mutable reference
announce<baz>(compound_member(make_pair(&baz::f, &baz::set_f), announce<baz>("baz", compound_member(make_pair(&baz::f, &baz::set_f),
make_pair(&foo::a, &foo::set_a), make_pair(&foo::a, &foo::set_a),
make_pair(&foo::b, &foo::set_b)), make_pair(&foo::b, &foo::set_b)),
// compound member that has a compound member // compound member that has a compound member
compound_member(&baz::b, compound_member(&baz::b, meta_bar_f(), &bar::i));
compound_member(&bar::f,
make_pair(&foo::a, &foo::set_a),
make_pair(&foo::b, &foo::set_b)),
&bar::i));
// spawn a testee that receives two messages // spawn a testee that receives two messages
auto t = spawn(testee, 2); auto t = spawn(testee, 2);
{ {
......
...@@ -86,9 +86,12 @@ bool operator==(const tree& lhs, const tree& rhs) { ...@@ -86,9 +86,12 @@ bool operator==(const tree& lhs, const tree& rhs) {
// - does have a copy constructor // - does have a copy constructor
// - does provide operator== // - does provide operator==
class tree_type_info : public detail::abstract_uniform_type_info<tree> { class tree_type_info : public detail::abstract_uniform_type_info<tree> {
public:
tree_type_info() : detail::abstract_uniform_type_info<tree>("tree") {
// nop
}
protected: protected:
void serialize(const void* ptr, serializer* sink) const { void serialize(const void* ptr, serializer* sink) const {
// ptr is guaranteed to be a pointer of type tree // ptr is guaranteed to be a pointer of type tree
auto tree_ptr = reinterpret_cast<const tree*>(ptr); auto tree_ptr = reinterpret_cast<const tree*>(ptr);
...@@ -105,7 +108,6 @@ class tree_type_info : public detail::abstract_uniform_type_info<tree> { ...@@ -105,7 +108,6 @@ class tree_type_info : public detail::abstract_uniform_type_info<tree> {
} }
private: private:
void serialize_node(const tree_node& node, serializer* sink) const { void serialize_node(const tree_node& node, serializer* sink) const {
// value, ... children ... // value, ... children ...
sink->write_value(node.value); sink->write_value(node.value);
...@@ -127,7 +129,6 @@ class tree_type_info : public detail::abstract_uniform_type_info<tree> { ...@@ -127,7 +129,6 @@ class tree_type_info : public detail::abstract_uniform_type_info<tree> {
} }
source->end_sequence(); source->end_sequence();
} }
}; };
using tree_vector = std::vector<tree>; using tree_vector = std::vector<tree>;
...@@ -202,7 +203,7 @@ int main() { ...@@ -202,7 +203,7 @@ int main() {
self->send(t, t0); self->send(t, t0);
// send a vector of trees // send a vector of trees
announce<tree_vector>(); announce<tree_vector>("tree_vector");
tree_vector tvec; tree_vector tvec;
tvec.push_back(t0); tvec.push_back(t0);
tvec.push_back(t0); tvec.push_back(t0);
......
...@@ -38,7 +38,6 @@ set (LIBCAF_CORE_SRCS ...@@ -38,7 +38,6 @@ set (LIBCAF_CORE_SRCS
src/continue_helper.cpp src/continue_helper.cpp
src/decorated_tuple.cpp src/decorated_tuple.cpp
src/default_attachable.cpp src/default_attachable.cpp
src/demangle.cpp
src/deserializer.cpp src/deserializer.cpp
src/duration.cpp src/duration.cpp
src/event_based_actor.cpp src/event_based_actor.cpp
...@@ -73,7 +72,6 @@ set (LIBCAF_CORE_SRCS ...@@ -73,7 +72,6 @@ set (LIBCAF_CORE_SRCS
src/string_algorithms.cpp src/string_algorithms.cpp
src/string_serialization.cpp src/string_serialization.cpp
src/sync_request_bouncer.cpp src/sync_request_bouncer.cpp
src/to_uniform_name.cpp
src/uniform_type_info.cpp src/uniform_type_info.cpp
src/uniform_type_info_map.cpp) src/uniform_type_info_map.cpp)
......
...@@ -79,8 +79,8 @@ namespace caf { ...@@ -79,8 +79,8 @@ namespace caf {
*/ */
/** /**
* Adds a new mapping to the type system. Returns `false` if a mapping * Adds a new mapping to the type system. Returns `utype.get()` on
* for `tinfo` already exists, otherwise `true`. * success, otherwise a pointer to the previously installed singleton.
* @warning `announce` is **not** thead-safe! * @warning `announce` is **not** thead-safe!
*/ */
const uniform_type_info* announce(const std::type_info& tinfo, const uniform_type_info* announce(const std::type_info& tinfo,
...@@ -95,7 +95,7 @@ const uniform_type_info* announce(const std::type_info& tinfo, ...@@ -95,7 +95,7 @@ const uniform_type_info* announce(const std::type_info& tinfo,
template <class C, class Parent, class... Ts> template <class C, class Parent, class... Ts>
std::pair<C Parent::*, detail::abstract_uniform_type_info<C>*> std::pair<C Parent::*, detail::abstract_uniform_type_info<C>*>
compound_member(C Parent::*c_ptr, const Ts&... args) { compound_member(C Parent::*c_ptr, const Ts&... args) {
return {c_ptr, new detail::default_uniform_type_info<C>(args...)}; return {c_ptr, new detail::default_uniform_type_info<C>("???", args...)};
} }
// deals with getter returning a mutable reference // deals with getter returning a mutable reference
...@@ -108,7 +108,7 @@ compound_member(C Parent::*c_ptr, const Ts&... args) { ...@@ -108,7 +108,7 @@ compound_member(C Parent::*c_ptr, const Ts&... args) {
template <class C, class Parent, class... Ts> template <class C, class Parent, class... Ts>
std::pair<C& (Parent::*)(), detail::abstract_uniform_type_info<C>*> std::pair<C& (Parent::*)(), detail::abstract_uniform_type_info<C>*>
compound_member(C& (Parent::*getter)(), const Ts&... args) { compound_member(C& (Parent::*getter)(), const Ts&... args) {
return {getter, new detail::default_uniform_type_info<C>(args...)}; return {getter, new detail::default_uniform_type_info<C>("???", args...)};
} }
// deals with getter/setter pair // deals with getter/setter pair
...@@ -126,16 +126,17 @@ compound_member(const std::pair<GRes (Parent::*)() const, ...@@ -126,16 +126,17 @@ compound_member(const std::pair<GRes (Parent::*)() const,
SRes (Parent::*)(SArg)>& gspair, SRes (Parent::*)(SArg)>& gspair,
const Ts&... args) { const Ts&... args) {
using mtype = typename std::decay<GRes>::type; using mtype = typename std::decay<GRes>::type;
return {gspair, new detail::default_uniform_type_info<mtype>(args...)}; return {gspair, new detail::default_uniform_type_info<mtype>("???", args...)};
} }
/** /**
* Adds a new type mapping for `C` to the type system. * Adds a new type mapping for `C` to the type system
* using `tname` as its uniform name.
* @warning `announce` is **not** thead-safe! * @warning `announce` is **not** thead-safe!
*/ */
template <class C, class... Ts> template <class C, class... Ts>
inline const uniform_type_info* announce(const Ts&... args) { inline const uniform_type_info* announce(std::string tname, const Ts&... args) {
auto ptr = new detail::default_uniform_type_info<C>(args...); auto ptr = new detail::default_uniform_type_info<C>(std::move(tname), args...);
return announce(typeid(C), uniform_type_info_ptr{ptr}); return announce(typeid(C), uniform_type_info_ptr{ptr});
} }
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
#include "caf/detail/to_uniform_name.hpp"
#include "caf/detail/uniform_type_info_map.hpp" #include "caf/detail/uniform_type_info_map.hpp"
namespace caf { namespace caf {
...@@ -61,13 +60,8 @@ class abstract_uniform_type_info : public uniform_type_info { ...@@ -61,13 +60,8 @@ class abstract_uniform_type_info : public uniform_type_info {
protected: protected:
abstract_uniform_type_info() { abstract_uniform_type_info(std::string tname) {
auto uname = detail::to_uniform_name<T>(); m_name = detail::mapped_name_by_decorated_name(std::move(tname));
auto cname = detail::mapped_name_by_decorated_name(uname.c_str());
if (cname == uname.c_str())
m_name = std::move(uname);
else
m_name = cname;
} }
static inline const T& deref(const void* ptr) { static inline const T& deref(const void* ptr) {
......
...@@ -248,16 +248,22 @@ template <class T, class AccessPolicy, ...@@ -248,16 +248,22 @@ template <class T, class AccessPolicy,
bool IsEmptyType = std::is_class<T>::value&& std::is_empty<T>::value> bool IsEmptyType = std::is_class<T>::value&& std::is_empty<T>::value>
class member_tinfo : public detail::abstract_uniform_type_info<T> { class member_tinfo : public detail::abstract_uniform_type_info<T> {
public: public:
using super = detail::abstract_uniform_type_info<T>;
member_tinfo(AccessPolicy apol, SerializePolicy spol) member_tinfo(AccessPolicy apol, SerializePolicy spol)
: m_apol(std::move(apol)), m_spol(std::move(spol)) { : super("--member--"),
m_apol(std::move(apol)), m_spol(std::move(spol)) {
// nop // nop
} }
member_tinfo(AccessPolicy apol) : m_apol(std::move(apol)) { member_tinfo(AccessPolicy apol)
: super("--member--"),
m_apol(std::move(apol)) {
// nop // nop
} }
member_tinfo() = default; member_tinfo() : super("--member--") {
// nop
}
void serialize(const void* vptr, serializer* s) const override { void serialize(const void* vptr, serializer* s) const override {
m_spol(m_apol(vptr), s); m_spol(m_apol(vptr), s);
...@@ -289,15 +295,19 @@ template <class T, class A, class S> ...@@ -289,15 +295,19 @@ template <class T, class A, class S>
class member_tinfo<T, A, S, false, true> class member_tinfo<T, A, S, false, true>
: public detail::abstract_uniform_type_info<T> { : public detail::abstract_uniform_type_info<T> {
public: public:
member_tinfo(const A&, const S&) { using super = detail::abstract_uniform_type_info<T>;
member_tinfo(const A&, const S&) : super("--member--") {
// nop // nop
} }
member_tinfo(const A&) { member_tinfo(const A&) : super("--member--") {
// nop // nop
} }
member_tinfo() = default; member_tinfo() : super("--member--") {
// nop
}
void serialize(const void*, serializer*) const override { void serialize(const void*, serializer*) const override {
// nop // nop
...@@ -312,14 +322,24 @@ template <class T, class AccessPolicy, class SerializePolicy> ...@@ -312,14 +322,24 @@ template <class T, class AccessPolicy, class SerializePolicy>
class member_tinfo<T, AccessPolicy, SerializePolicy, true, false> class member_tinfo<T, AccessPolicy, SerializePolicy, true, false>
: public detail::abstract_uniform_type_info<T> { : public detail::abstract_uniform_type_info<T> {
public: public:
using super = detail::abstract_uniform_type_info<T>;
using value_type = typename std::underlying_type<T>::type; using value_type = typename std::underlying_type<T>::type;
member_tinfo(AccessPolicy apol, SerializePolicy spol) member_tinfo(AccessPolicy apol, SerializePolicy spol)
: m_apol(std::move(apol)), m_spol(std::move(spol)) {} : super("--member--"),
m_apol(std::move(apol)), m_spol(std::move(spol)) {
// nop
}
member_tinfo(AccessPolicy apol) : m_apol(std::move(apol)) {} member_tinfo(AccessPolicy apol)
: super("--member--"),
m_apol(std::move(apol)) {
// nop
}
member_tinfo() = default; member_tinfo() : super("--member--") {
// nop
}
void serialize(const void* p, serializer* s) const override { void serialize(const void* p, serializer* s) const override {
auto val = m_apol(p); auto val = m_apol(p);
...@@ -453,12 +473,15 @@ uniform_type_info_ptr new_member_tinfo(GRes (C::*getter)() const, ...@@ -453,12 +473,15 @@ uniform_type_info_ptr new_member_tinfo(GRes (C::*getter)() const,
template <class T> template <class T>
class default_uniform_type_info : public detail::abstract_uniform_type_info<T> { class default_uniform_type_info : public detail::abstract_uniform_type_info<T> {
public: public:
using super = detail::abstract_uniform_type_info<T>;
template <class... Ts> template <class... Ts>
default_uniform_type_info(Ts&&... args) { default_uniform_type_info(std::string tname, Ts&&... args)
: super(std::move(tname)) {
push_back(std::forward<Ts>(args)...); push_back(std::forward<Ts>(args)...);
} }
default_uniform_type_info() { default_uniform_type_info(std::string tname) : super(std::move(tname)) {
using result_type = member_tinfo<T, fake_access_policy<T>>; using result_type = member_tinfo<T, fake_access_policy<T>>;
m_members.push_back(uniform_type_info_ptr(new result_type)); m_members.push_back(uniform_type_info_ptr(new result_type));
} }
...@@ -552,9 +575,10 @@ template <class... Rs> ...@@ -552,9 +575,10 @@ template <class... Rs>
class default_uniform_type_info<typed_actor<Rs...>> : class default_uniform_type_info<typed_actor<Rs...>> :
public detail::abstract_uniform_type_info<typed_actor<Rs...>> { public detail::abstract_uniform_type_info<typed_actor<Rs...>> {
public: public:
using super = detail::abstract_uniform_type_info<typed_actor<Rs...>>;
using handle_type = typed_actor<Rs...>; using handle_type = typed_actor<Rs...>;
default_uniform_type_info() { default_uniform_type_info(std::string tname) : super(std::move(tname)) {
sub_uti = uniform_typeid<actor>(); sub_uti = uniform_typeid<actor>();
} }
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include "caf/to_string.hpp" #include "caf/to_string.hpp"
#include "caf/abstract_actor.hpp" #include "caf/abstract_actor.hpp"
#include "caf/detail/demangle.hpp"
#include "caf/detail/singletons.hpp" #include "caf/detail/singletons.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
...@@ -184,7 +183,7 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; } ...@@ -184,7 +183,7 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; }
caf::detail::singletons::get_logger()->set_aid(aid_arg) caf::detail::singletons::get_logger()->set_aid(aid_arg)
#endif #endif
#define CAF_CLASS_NAME caf::detail::demangle(typeid(decltype(*this))).c_str() #define CAF_CLASS_NAME typeid(*this).name()
#define CAF_PRINT0(lvlname, classname, funname, msg) \ #define CAF_PRINT0(lvlname, classname, funname, msg) \
CAF_LOG_IMPL(lvlname, classname, funname, msg) CAF_LOG_IMPL(lvlname, classname, funname, msg)
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#ifndef CAF_DETAIL_TO_UNIFORM_NAME_HPP
#define CAF_DETAIL_TO_UNIFORM_NAME_HPP
#include <string>
#include <typeinfo>
namespace caf {
namespace detail {
std::string to_uniform_name(const std::string& demangled_name);
std::string to_uniform_name(const std::type_info& tinfo);
template <class T>
inline std::string to_uniform_name() {
return to_uniform_name(typeid(T));
}
} // namespace detail
} // namespace caf
#endif // CAF_DETAIL_TO_UNIFORM_NAME_HPP
...@@ -23,15 +23,11 @@ ...@@ -23,15 +23,11 @@
#include <atomic> #include <atomic>
#include <typeinfo> #include <typeinfo>
#include "caf/uniform_typeid.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
// forward declarations
namespace caf {
class uniform_type_info;
const uniform_type_info* uniform_typeid(const std::type_info&);
} // namespace caf
namespace caf { namespace caf {
namespace detail { namespace detail {
......
...@@ -170,9 +170,8 @@ class event_based_resume { ...@@ -170,9 +170,8 @@ class event_based_resume {
} }
} }
catch (std::exception& e) { catch (std::exception& e) {
CAF_LOG_INFO("actor died because of an exception: " CAF_LOG_INFO("actor died because of an exception, what() = "
<< detail::demangle(typeid(e)) << e.what());
<< ", what() = " << e.what());
if (d->exit_reason() == exit_reason::not_exited) { if (d->exit_reason() == exit_reason::not_exited) {
d->quit(exit_reason::unhandled_exception); d->quit(exit_reason::unhandled_exception);
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#ifndef CAF_REPLIES_TO_HPP #ifndef CAF_REPLIES_TO_HPP
#define CAF_REPLIES_TO_HPP #define CAF_REPLIES_TO_HPP
#include "caf/uniform_type_info.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
namespace caf { namespace caf {
...@@ -28,9 +29,33 @@ template <class... Is> ...@@ -28,9 +29,33 @@ template <class... Is>
struct replies_to { struct replies_to {
template <class... Os> template <class... Os>
struct with { struct with {
static_assert(sizeof...(Is) > 0, "template parameter pack Is empty");
static_assert(sizeof...(Os) > 0, "template parameter pack Os empty");
using input_types = detail::type_list<Is...>; using input_types = detail::type_list<Is...>;
using output_types = detail::type_list<Os...>; using output_types = detail::type_list<Os...>;
static std::string as_string() {
const uniform_type_info* inputs[] = {uniform_typeid<Is>(true)...};
const uniform_type_info* outputs[] = {uniform_typeid<Os>(true)...};
std::string result;
// 'void' is not an announced type, hence we check whether uniform_typeid
// did return a valid pointer to identify 'void' (this has the
// possibility of false positives, but those will be catched anyways)
auto plot = [&](const uniform_type_info** arr) {
auto uti = arr[0];
result += uti ? uti->name() : "void";
for (size_t i = 1; i < sizeof...(Is); ++i) {
uti = arr[i];
result += ",";
result += uti ? uti->name() : "void";
}
};
result = "caf::replies_to<";
plot(inputs);
result += ">::with<";
plot(outputs);
result += ">";
return result;
}
}; };
}; };
......
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
#include "caf/uniform_type_info.hpp" #include "caf/uniform_type_info.hpp"
#include "caf/primitive_variant.hpp" #include "caf/primitive_variant.hpp"
#include "caf/detail/to_uniform_name.hpp"
namespace caf { namespace caf {
class actor_namespace; class actor_namespace;
...@@ -111,8 +109,7 @@ template <class T> ...@@ -111,8 +109,7 @@ template <class T>
serializer& operator<<(serializer& s, const T& what) { serializer& operator<<(serializer& s, const T& what) {
auto mtype = uniform_typeid<T>(); auto mtype = uniform_typeid<T>();
if (mtype == nullptr) { if (mtype == nullptr) {
throw std::logic_error("no uniform type info found for " throw std::logic_error("no uniform type info found for T");
+ detail::to_uniform_name(typeid(T)));
} }
mtype->serialize(&what, &s); mtype->serialize(&what, &s);
return s; return s;
......
...@@ -69,7 +69,7 @@ intrusive_ptr<C> spawn_impl(execution_unit* host, ...@@ -69,7 +69,7 @@ intrusive_ptr<C> spawn_impl(execution_unit* host,
"spawned without blocking_api_flag"); "spawned without blocking_api_flag");
static_assert(is_unbound(Os), static_assert(is_unbound(Os),
"top-level spawns cannot have monitor or link flag"); "top-level spawns cannot have monitor or link flag");
CAF_LOGF_TRACE("spawn " << detail::demangle<C>()); CAF_LOGF_TRACE("");
using scheduling_policy = using scheduling_policy =
typename std::conditional< typename std::conditional<
has_detach_flag(Os) || has_blocking_api_flag(Os), has_detach_flag(Os) || has_blocking_api_flag(Os),
......
...@@ -60,7 +60,7 @@ std::string to_string(const node_id& what); ...@@ -60,7 +60,7 @@ std::string to_string(const node_id& what);
std::string to_string(const atom_value& what); std::string to_string(const atom_value& what);
/** /**
* Converts `e` to a string including the demangled type of `e` and `e.what()`. * Converts `e` to a string including `e.what()`.
*/ */
std::string to_verbose_string(const std::exception& e); std::string to_verbose_string(const std::exception& e);
......
...@@ -131,7 +131,7 @@ class typed_actor ...@@ -131,7 +131,7 @@ class typed_actor
} }
static std::set<std::string> message_types() { static std::set<std::string> message_types() {
return {detail::to_uniform_name<Rs>()...}; return {Rs::as_string()...};
} }
explicit operator bool() const { return static_cast<bool>(m_ptr); } explicit operator bool() const { return static_cast<bool>(m_ptr); }
......
...@@ -49,7 +49,7 @@ class typed_event_based_actor : public ...@@ -49,7 +49,7 @@ class typed_event_based_actor : public
using behavior_type = typed_behavior<Rs...>; using behavior_type = typed_behavior<Rs...>;
std::set<std::string> message_types() const override { std::set<std::string> message_types() const override {
return {detail::to_uniform_name<Rs>()...}; return {Rs::as_string()...};
} }
protected: protected:
......
...@@ -29,20 +29,16 @@ ...@@ -29,20 +29,16 @@
#include <type_traits> #include <type_traits>
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/uniform_typeid.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
#include "caf/detail/demangle.hpp"
#include "caf/detail/to_uniform_name.hpp"
namespace caf { namespace caf {
class serializer; class serializer;
class deserializer; class deserializer;
class uniform_type_info; class uniform_type_info;
const uniform_type_info* uniform_typeid(const std::type_info&);
struct uniform_value_t; struct uniform_value_t;
using uniform_value = std::unique_ptr<uniform_value_t>; using uniform_value = std::unique_ptr<uniform_value_t>;
...@@ -203,8 +199,8 @@ class uniform_type_info { ...@@ -203,8 +199,8 @@ class uniform_type_info {
/** /**
* Creates a copy of `other`. * Creates a copy of `other`.
*/ */
virtual uniform_value virtual uniform_value create(const uniform_value& other
create(const uniform_value& other = uniform_value{}) const = 0; = uniform_value{}) const = 0;
/** /**
* Deserializes an object of this type from `source`. * Deserializes an object of this type from `source`.
...@@ -279,18 +275,14 @@ using uniform_type_info_ptr = std::unique_ptr<uniform_type_info>; ...@@ -279,18 +275,14 @@ using uniform_type_info_ptr = std::unique_ptr<uniform_type_info>;
/** /**
* @relates uniform_type_info * @relates uniform_type_info
*/ */
template <class T>
inline const uniform_type_info* uniform_typeid() {
return uniform_typeid(typeid(T));
}
/** /**
* @relates uniform_type_info * @relates uniform_type_info
*/ */
inline bool operator==(const uniform_type_info& lhs, inline bool operator==(const uniform_type_info& lhs,
const uniform_type_info& rhs) { const uniform_type_info& rhs) {
// uniform_type_info instances are singletons, // uniform_type_info instances are singletons
// thus, equal == identical
return &lhs == &rhs; return &lhs == &rhs;
} }
......
...@@ -17,24 +17,23 @@ ...@@ -17,24 +17,23 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#ifndef CAF_DETAIL_DEMANGLE_HPP #ifndef CAF_UNIFORM_TYPEID_HPP
#define CAF_DETAIL_DEMANGLE_HPP #define CAF_UNIFORM_TYPEID_HPP
#include <string>
#include <typeinfo> #include <typeinfo>
namespace caf { namespace caf {
namespace detail {
std::string demangle(const char* typeid_name); class uniform_type_info;
std::string demangle(const std::type_info& tinf);
const uniform_type_info* uniform_typeid(const std::type_info& tinf,
bool allow_nullptr = false);
template <class T> template <class T>
inline std::string demangle() { const uniform_type_info* uniform_typeid(bool allow_nullptr = false) {
return demangle(typeid(T)); return uniform_typeid(typeid(T), allow_nullptr);
} }
} // namespace detail
} // namespace caf } // namespace caf
#endif // CAF_DETAIL_DEMANGLE_HPP #endif // CAF_UNIFORM_TYPEID_HPP
...@@ -32,8 +32,6 @@ ...@@ -32,8 +32,6 @@
#include "caf/on.hpp" #include "caf/on.hpp"
#include "caf/optional.hpp" #include "caf/optional.hpp"
#include "caf/detail/demangle.hpp"
#include "cppa/opt_impls.hpp" #include "cppa/opt_impls.hpp"
namespace caf { namespace caf {
......
...@@ -93,7 +93,7 @@ class rd_arg_functor { ...@@ -93,7 +93,7 @@ class rd_arg_functor {
auto opt = conv_arg_impl<T>::_(arg); auto opt = conv_arg_impl<T>::_(arg);
if (!opt) { if (!opt) {
std::cerr << "*** error: cannot convert \"" << arg << "\" to " std::cerr << "*** error: cannot convert \"" << arg << "\" to "
<< detail::demangle(typeid(T).name()) << typeid(T).name()
<< " [option: \"" << m_storage->arg_name << "\"]" << " [option: \"" << m_storage->arg_name << "\"]"
<< std::endl; << std::endl;
return false; return false;
...@@ -126,7 +126,7 @@ class add_arg_functor { ...@@ -126,7 +126,7 @@ class add_arg_functor {
auto opt = conv_arg_impl<T>::_(arg); auto opt = conv_arg_impl<T>::_(arg);
if (!opt) { if (!opt) {
std::cerr << "*** error: cannot convert \"" << arg << "\" to " std::cerr << "*** error: cannot convert \"" << arg << "\" to "
<< detail::demangle(typeid(T)) << typeid(T).name()
<< " [option: \"" << m_storage->arg_name << "\"]" << " [option: \"" << m_storage->arg_name << "\"]"
<< std::endl; << std::endl;
return false; return false;
......
...@@ -217,7 +217,7 @@ void abstract_actor::cleanup(uint32_t reason) { ...@@ -217,7 +217,7 @@ void abstract_actor::cleanup(uint32_t reason) {
CAF_LOG_INFO_IF(!is_remote(), "cleanup actor with ID " CAF_LOG_INFO_IF(!is_remote(), "cleanup actor with ID "
<< m_id << "; exit reason = " << m_id << "; exit reason = "
<< reason << ", class = " << reason << ", class = "
<< detail::demangle(typeid(*this))); << class_name());
// send exit messages // send exit messages
for (attachable* i = head.get(); i != nullptr; i = i->next.get()) { for (attachable* i = head.get(); i != nullptr; i = i->next.get()) {
i->actor_exited(this, reason); i->actor_exited(this, reason);
......
...@@ -31,7 +31,7 @@ continue_helper& continue_helper::continue_with(behavior::continuation_fun f) { ...@@ -31,7 +31,7 @@ continue_helper& continue_helper::continue_with(behavior::continuation_fun f) {
behavior cpy = *ref_opt; behavior cpy = *ref_opt;
*ref_opt = cpy.add_continuation(std::move(f)); *ref_opt = cpy.add_continuation(std::move(f));
} else { } else {
CAF_LOG_ERROR("failed to add continuation"); CAF_LOGF_ERROR("failed to add continuation");
} }
return *this; return *this;
} }
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#include <memory>
#include <string>
#include <cstdlib>
#include <stdexcept>
#include "caf/config.hpp"
#include "caf/detail/demangle.hpp"
#if defined(CAF_CLANG) || defined(CAF_GCC)
# include <cxxabi.h>
# include <stdlib.h>
#endif
namespace caf {
namespace detail {
namespace {
// filter unnecessary characters from undecorated cstr
std::string filter_whitespaces(const char* cstr, size_t size = 0) {
std::string result;
if (size > 0) {
result.reserve(size);
}
char c = *cstr;
while (c != '\0') {
if (c == ' ') {
char previous_c = result.empty() ? ' ' : *(result.rbegin());
for (c = *++cstr; c == ' '; c = *++cstr) {
// scan for next non-space character
}
if (c != '\0') {
// skip whitespace unless it separates two alphanumeric
// characters (such as in "unsigned int")
if (isalnum(c) && isalnum(previous_c)) {
result += ' ';
result += c;
} else {
result += c;
}
c = *++cstr;
}
} else {
result += c;
c = *++cstr;
}
}
return result;
}
} // namespace <anonymous>
#if defined(CAF_CLANG) || defined(CAF_GCC)
std::string demangle(const char* decorated) {
using std::string;
size_t size;
int status;
using uptr = std::unique_ptr<char, void (*)(void*)>;
uptr undecorated{abi::__cxa_demangle(decorated, nullptr, &size, &status),
std::free};
if (status != 0) {
string error_msg = "Could not demangle type name ";
error_msg += decorated;
throw std::logic_error(error_msg);
}
// the undecorated typeid name
string result = filter_whitespaces(undecorated.get(), size);
# ifdef CAF_CLANG
// replace "std::__1::" with "std::" (fixes strange clang names)
string needle = "std::__1::";
string fixed_string = "std::";
for (auto pos = result.find(needle); pos != string::npos;
pos = result.find(needle)) {
result.replace(pos, needle.size(), fixed_string);
}
# endif
return result;
}
#elif defined(CAF_MSVC)
string demangle(const char* decorated) {
// on MSVC, name() returns a human-readable version, all we need
// to do is to remove "struct" and "class" qualifiers
// (handled in to_uniform_name)
return filter_whitespaces(decorated);
}
#else
# error "compiler or platform not supported"
#endif
std::string demangle(const std::type_info& tinf) {
return demangle(tinf.name());
}
} // namespace detail
} // namespace caf
...@@ -166,8 +166,8 @@ void local_actor::cleanup(uint32_t reason) { ...@@ -166,8 +166,8 @@ void local_actor::cleanup(uint32_t reason) {
} }
void local_actor::quit(uint32_t reason) { void local_actor::quit(uint32_t reason) {
CAF_LOG_TRACE("reason = " << reason << ", class " CAF_LOG_TRACE("reason = " << reason << ", class = "
<< detail::demangle(typeid(*this))); << class_name());
planned_exit_reason(reason); planned_exit_reason(reason);
if (is_blocking()) { if (is_blocking()) {
throw actor_exited(reason); throw actor_exited(reason);
......
...@@ -609,7 +609,7 @@ string to_string(const node_id& what) { ...@@ -609,7 +609,7 @@ string to_string(const node_id& what) {
string to_verbose_string(const std::exception& e) { string to_verbose_string(const std::exception& e) {
std::ostringstream oss; std::ostringstream oss;
oss << detail::demangle(typeid(e)) << ": " << e.what(); oss << "std::exception, what(): " << e.what();
return oss.str(); return oss.str();
} }
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#include <map>
#include <cwchar>
#include <limits>
#include <vector>
#include <cstring>
#include <typeinfo>
#include <stdexcept>
#include <algorithm>
#include "caf/string_algorithms.hpp"
#include "caf/atom.hpp"
#include "caf/actor.hpp"
#include "caf/channel.hpp"
#include "caf/message.hpp"
#include "caf/message.hpp"
#include "caf/abstract_group.hpp"
#include "caf/detail/demangle.hpp"
#include "caf/detail/safe_equal.hpp"
#include "caf/detail/singletons.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/detail/to_uniform_name.hpp"
#include "caf/detail/uniform_type_info_map.hpp"
//#define DEBUG_PARSER
#ifdef DEBUG_PARSER
# include <iostream>
namespace {
size_t s_indentation = 0;
} // namespace <anonymous>
# define PARSER_INIT(message) \
std::cout << std::string(s_indentation, ' ') << ">>> " << message \
<< std::endl; \
s_indentation += 2; \
auto ____sg = caf::detail::make_scope_guard([] { s_indentation -= 2; })
# define PARSER_OUT(condition, message) \
if (condition) { \
std::cout << std::string(s_indentation, ' ') << "### " << message \
<< std::endl; \
} \
static_cast<void>(0)
#else
# define PARSER_INIT(unused) static_cast<void>(0)
# define PARSER_OUT(unused1, unused2) static_cast<void>(0)
#endif
namespace caf {
namespace detail {
namespace {
using namespace std;
struct platform_int_mapping {
const char* name;
size_t size;
bool is_signed;
};
// WARNING: this list is sorted and searched with std::lower_bound;
// keep ordered when adding elements!
constexpr platform_int_mapping platform_dependent_sizes[] = {
{"char", sizeof(char), true },
{"char16_t", sizeof(char16_t), true },
{"char32_t", sizeof(char32_t), true },
{"int", sizeof(int), true },
{"long", sizeof(long), true },
{"long int", sizeof(long int), true },
{"long long", sizeof(long long), true },
{"short", sizeof(short), true },
{"short int", sizeof(short int), true },
{"signed char", sizeof(signed char), true },
{"signed int", sizeof(signed int), true },
{"signed long", sizeof(signed long), true },
{"signed long int", sizeof(signed long int), true },
{"signed long long", sizeof(signed long long), true },
{"signed short", sizeof(signed short), true },
{"signed short int", sizeof(signed short int), true },
{"unsigned char", sizeof(unsigned char), false},
{"unsigned int", sizeof(unsigned int), false},
{"unsigned long", sizeof(unsigned long), false},
{"unsigned long int", sizeof(unsigned long int), false},
{"unsigned long long", sizeof(unsigned long long), false},
{"unsigned short", sizeof(unsigned short), false},
{"unsigned short int", sizeof(unsigned short int), false}
};
string map2decorated(string&& name) {
auto cmp = [](const platform_int_mapping& pim, const string& str) {
return strcmp(pim.name, str.c_str()) < 0;
};
auto e = end(platform_dependent_sizes);
auto i = lower_bound(begin(platform_dependent_sizes), e, name, cmp);
if (i != e && i->name == name) {
PARSER_OUT(true, name << " => "
<< mapped_int_names[i->size][i->is_signed ? 1 : 0]);
return mapped_int_names[i->size][i->is_signed ? 1 : 0];
}
# ifdef DEBUG_PARSER
auto mapped = mapped_name_by_decorated_name(name.c_str());
PARSER_OUT(mapped != name, name << " => " << string{mapped});
return mapped;
# else
return mapped_name_by_decorated_name(std::move(name));
# endif
}
class parse_tree {
public:
string compile(bool parent_invoked = false) {
string result;
propagate_flags();
if (!parent_invoked) {
if (m_volatile) {
result += "volatile ";
}
if (m_const) {
result += "const ";
}
}
if (has_children()) {
string sub_result;
for (auto& child : m_children) {
if (!sub_result.empty()) {
sub_result += "::";
}
sub_result += child.compile(true);
}
result += map2decorated(std::move(sub_result));
} else {
string full_name = map2decorated(std::move(m_name));
if (is_template()) {
full_name += "<";
for (auto& tparam : m_template_parameters) {
// decorate each single template parameter
if (full_name.back() != '<') {
full_name += ",";
}
full_name += tparam.compile();
}
full_name += ">";
// decorate full name
}
result += map2decorated(std::move(full_name));
}
if (!parent_invoked) {
if (m_pointer) {
result += "*";
}
if (m_lvalue_ref) {
result += "&";
}
if (m_rvalue_ref) {
result += "&&";
}
}
return map2decorated(std::move(result));
}
template <class Iterator>
static vector<parse_tree> parse_tpl_args(Iterator first, Iterator last);
template <class Iterator>
static parse_tree parse(Iterator first, Iterator last) {
PARSER_INIT((std::string{first, last}));
parse_tree result;
using range = std::pair<Iterator, Iterator>;
std::vector<range> subranges;
{ // lifetime scope of temporary variables needed to fill 'subranges'
auto find_end = [&](Iterator from)->Iterator {
auto open = 1;
for (auto i = from + 1; i != last && open > 0; ++i) {
switch (*i) {
default:
break;
case '<':
++open;
break;
case '>':
if (--open == 0) return i;
break;
}
}
return last;
};
auto sub_first = find(first, last, '<');
while (sub_first != last) {
auto sub_last = find_end(sub_first);
subranges.emplace_back(sub_first, sub_last);
sub_first = find(sub_last + 1, last, '<');
}
}
auto islegal = [](char c) {
return isalnum(c) || c == ':' || c == '_';
};
vector<string> tokens;
tokens.push_back("");
vector<Iterator> scope_resolution_ops;
auto is_in_subrange = [&](Iterator i) -> bool {
for (auto& r : subranges) {
if (i >= r.first && i < r.second) {
return true;
}
}
return false;
};
auto add_child = [&](Iterator ch_first, Iterator ch_last) {
PARSER_OUT(true, "new child: [" << distance(first, ch_first) << ", "
<< ", " << distance(first, ch_last)
<< ")");
result.m_children.push_back(parse(ch_first, ch_last));
};
// scan string for "::" separators
const char* scope_resultion = "::";
auto sr_first = scope_resultion;
auto sr_last = sr_first + 2;
auto scope_iter = search(first, last, sr_first, sr_last);
if (scope_iter != last) {
auto itermediate = first;
if (!is_in_subrange(scope_iter)) {
add_child(first, scope_iter);
itermediate = scope_iter + 2;
}
while (scope_iter != last) {
scope_iter = search(scope_iter + 2, last, sr_first, sr_last);
if (scope_iter != last && !is_in_subrange(scope_iter)) {
add_child(itermediate, scope_iter);
itermediate = scope_iter + 2;
}
}
if (!result.m_children.empty()) {
add_child(itermediate, last);
}
}
if (result.m_children.empty()) {
// no children -> leaf node; parse non-template part now
CAF_REQUIRE(subranges.size() < 2);
vector<range> non_template_ranges;
if (subranges.empty()) {
non_template_ranges.emplace_back(first, last);
} else {
non_template_ranges.emplace_back(first, subranges[0].first);
for (size_t i = 1; i < subranges.size(); ++i) {
non_template_ranges.emplace_back(subranges[i - 1].second + 1,
subranges[i].first);
}
non_template_ranges.emplace_back(subranges.back().second + 1, last);
}
for (auto& ntr : non_template_ranges) {
for (auto i = ntr.first; i != ntr.second; ++i) {
char c = *i;
if (islegal(c)) {
if (!tokens.back().empty() && !islegal(tokens.back().back())) {
tokens.push_back("");
}
tokens.back() += c;
} else if (c == ' ') {
tokens.push_back("");
} else if (c == '&') {
if (tokens.back().empty() || tokens.back().back() == '&') {
tokens.back() += c;
} else {
tokens.push_back("&");
}
} else if (c == '*') {
tokens.push_back("*");
}
}
tokens.push_back("");
}
if (!subranges.empty()) {
auto& range0 = subranges.front();
PARSER_OUT(true, "subrange: [" << distance(first, range0.first + 1)
<< "," << distance(first, range0.second)
<< ")");
result.m_template_parameters
= parse_tpl_args(range0.first + 1, range0.second);
}
for (auto& token : tokens) {
if (token == "const") {
result.m_const = true;
} else if (token == "volatile") {
result.m_volatile = true;
} else if (token == "&") {
result.m_lvalue_ref = true;
} else if (token == "&&") {
result.m_rvalue_ref = true;
} else if (token == "*") {
result.m_pointer = true;
} else if (token == "class" || token == "struct") {
// ignored (created by visual c++ compilers)
} else if (!token.empty()) {
if (!result.m_name.empty()) {
result.m_name += " ";
}
result.m_name += token;
}
}
}
PARSER_OUT(!subranges.empty(), subranges.size() << " subranges");
PARSER_OUT(!result.m_children.empty(), result.m_children.size()
<< " children");
return result;
}
inline bool has_children() const {
return !m_children.empty();
}
inline bool is_template() const {
return !m_template_parameters.empty();
}
private:
void propagate_flags() {
for (auto& c : m_children) {
c.propagate_flags();
if (c.m_volatile) m_volatile = true;
if (c.m_const) m_const = true;
if (c.m_pointer) m_pointer = true;
if (c.m_lvalue_ref) m_lvalue_ref = true;
if (c.m_rvalue_ref) m_rvalue_ref = true;
}
}
parse_tree()
: m_const(false), m_pointer(false), m_volatile(false),
m_lvalue_ref(false), m_rvalue_ref(false) {
// nop
}
bool m_const;
bool m_pointer;
bool m_volatile;
bool m_lvalue_ref;
bool m_rvalue_ref;
bool m_nested_type;
string m_name;
vector<parse_tree> m_children;
vector<parse_tree> m_template_parameters;
};
template <class Iterator>
vector<parse_tree> parse_tree::parse_tpl_args(Iterator first, Iterator last) {
vector<parse_tree> result;
long open_brackets = 0;
auto i0 = first;
for (; first != last; ++first) {
switch (*first) {
case '<':
++open_brackets;
break;
case '>':
--open_brackets;
break;
case ',':
if (open_brackets == 0) {
result.push_back(parse(i0, first));
i0 = first + 1;
}
break;
default:
break;
}
}
result.push_back(parse(i0, first));
return result;
}
const char raw_anonymous_namespace[] = "anonymous namespace";
const char unified_anonymous_namespace[] = "$";
} // namespace <anonymous>
std::string to_uniform_name(const std::string& dname) {
auto r = parse_tree::parse(begin(dname), end(dname)).compile();
// replace compiler-dependent "anonmyous namespace" with "@_"
replace_all(r, raw_anonymous_namespace, unified_anonymous_namespace);
return r.c_str();
}
std::string to_uniform_name(const std::type_info& tinfo) {
return to_uniform_name(demangle(tinfo.name()));
}
} // namespace detail
} // namespace caf
...@@ -40,10 +40,8 @@ ...@@ -40,10 +40,8 @@
#include "caf/uniform_type_info.hpp" #include "caf/uniform_type_info.hpp"
#include "caf/detail/logging.hpp" #include "caf/detail/logging.hpp"
#include "caf/detail/demangle.hpp"
#include "caf/detail/singletons.hpp" #include "caf/detail/singletons.hpp"
#include "caf/detail/actor_registry.hpp" #include "caf/detail/actor_registry.hpp"
#include "caf/detail/to_uniform_name.hpp"
#include "caf/detail/uniform_type_info_map.hpp" #include "caf/detail/uniform_type_info_map.hpp"
namespace caf { namespace caf {
...@@ -73,8 +71,8 @@ const uniform_type_info* uniform_type_info::from(const std::type_info& tinf) { ...@@ -73,8 +71,8 @@ const uniform_type_info* uniform_type_info::from(const std::type_info& tinf) {
auto result = uti_map().by_rtti(tinf); auto result = uti_map().by_rtti(tinf);
if (result == nullptr) { if (result == nullptr) {
std::string error = "uniform_type_info::by_type_info(): "; std::string error = "uniform_type_info::by_type_info(): ";
error += detail::to_uniform_name(tinf); error += tinf.name();
error += " is an unknown typeid name"; error += " has not been announced";
CAF_LOGM_ERROR("caf::uniform_type_info", error); CAF_LOGM_ERROR("caf::uniform_type_info", error);
throw std::runtime_error(error); throw std::runtime_error(error);
} }
...@@ -99,8 +97,18 @@ std::vector<const uniform_type_info*> uniform_type_info::instances() { ...@@ -99,8 +97,18 @@ std::vector<const uniform_type_info*> uniform_type_info::instances() {
return uti_map().get_all(); return uti_map().get_all();
} }
const uniform_type_info* uniform_typeid(const std::type_info& tinfo) { const uniform_type_info* uniform_typeid(const std::type_info& tinf,
return uniform_type_info::from(tinfo); bool allow_nullptr) {
auto result = uti_map().by_rtti(tinf);
if (result == nullptr && !allow_nullptr) {
std::string error = "uniform_typeid(): ";
error += tinf.name();
error += " has not been announced";
CAF_LOGM_ERROR("caf::uniform_type_info", error);
throw std::runtime_error(error);
}
return result;
} }
} // namespace caf } // namespace caf
...@@ -116,7 +116,8 @@ using static_type_table = type_list<bool, ...@@ -116,7 +116,8 @@ using static_type_table = type_list<bool,
std::u16string, std::u16string,
std::u32string, std::u32string,
std::map<std::string, std::string>, std::map<std::string, std::string>,
std::vector<char>>; std::vector<char>,
std::vector<std::string>>;
} // namespace <anonymous> } // namespace <anonymous>
template <class T> template <class T>
...@@ -453,6 +454,30 @@ inline void deserialize_impl(const sync_timeout_msg&, deserializer*) { ...@@ -453,6 +454,30 @@ inline void deserialize_impl(const sync_timeout_msg&, deserializer*) {
// nop // nop
} }
inline void serialize_impl(const std::map<std::string, std::string>& smap,
serializer* sink) {
default_serialize_policy sp;
sp(smap, sink);
}
inline void deserialize_impl(std::map<std::string, std::string>& smap,
deserializer* source) {
default_serialize_policy sp;
sp(smap, source);
}
template <class T>
inline void serialize_impl(const std::vector<T>& vec, serializer* sink) {
default_serialize_policy sp;
sp(vec, sink);
}
template <class T>
inline void deserialize_impl(std::vector<T>& vec, deserializer* source) {
default_serialize_policy sp;
sp(vec, source);
}
bool types_equal(const std::type_info* lhs, const std::type_info* rhs) { bool types_equal(const std::type_info* lhs, const std::type_info* rhs) {
// in some cases (when dealing with dynamic libraries), // in some cases (when dealing with dynamic libraries),
// address can be different although types are equal // address can be different although types are equal
...@@ -795,7 +820,7 @@ class utim_impl : public uniform_type_info_map { ...@@ -795,7 +820,7 @@ class utim_impl : public uniform_type_info_map {
uti_impl<std::string>, uti_impl<std::string>,
uti_impl<std::u16string>, uti_impl<std::u16string>,
uti_impl<std::u32string>, uti_impl<std::u32string>,
default_uniform_type_info<strmap>, uti_impl<strmap>,
uti_impl<bool>, uti_impl<bool>,
uti_impl<float>, uti_impl<float>,
uti_impl<double>, uti_impl<double>,
...@@ -808,8 +833,8 @@ class utim_impl : public uniform_type_info_map { ...@@ -808,8 +833,8 @@ class utim_impl : public uniform_type_info_map {
int_tinfo<uint32_t>, int_tinfo<uint32_t>,
int_tinfo<int64_t>, int_tinfo<int64_t>,
int_tinfo<uint64_t>, int_tinfo<uint64_t>,
default_uniform_type_info<charbuf>, uti_impl<charbuf>,
default_uniform_type_info<strvec>>; uti_impl<strvec>>;
builtin_types m_storage; builtin_types m_storage;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "caf/io/spawn_io.hpp" #include "caf/io/spawn_io.hpp"
#include "caf/io/middleman.hpp" #include "caf/io/middleman.hpp"
#include "caf/io/unpublish.hpp" #include "caf/io/unpublish.hpp"
#include "caf/io/basp_broker.hpp"
#include "caf/io/max_msg_size.hpp" #include "caf/io/max_msg_size.hpp"
#include "caf/io/remote_actor.hpp" #include "caf/io/remote_actor.hpp"
#include "caf/io/remote_group.hpp" #include "caf/io/remote_group.hpp"
......
...@@ -117,7 +117,7 @@ deserialize_impl(T& dm, deserializer* source) { ...@@ -117,7 +117,7 @@ deserialize_impl(T& dm, deserializer* source) {
template <class T> template <class T>
class uti_impl : public uniform_type_info { class uti_impl : public uniform_type_info {
public: public:
uti_impl() : m_native(&typeid(T)), m_name(detail::demangle<T>()) { uti_impl(const char* tname) : m_native(&typeid(T)), m_name(tname) {
// nop // nop
} }
...@@ -165,23 +165,10 @@ class uti_impl : public uniform_type_info { ...@@ -165,23 +165,10 @@ class uti_impl : public uniform_type_info {
std::string m_name; std::string m_name;
}; };
template <class... Ts> template <class T>
struct announce_helper; void do_announce(const char* tname) {
announce(typeid(T), uniform_type_info_ptr{new uti_impl<T>(tname)});
template <class T, class... Ts> }
struct announce_helper<T, Ts...> {
static inline void exec() {
announce(typeid(T), uniform_type_info_ptr{new uti_impl<T>});
announce_helper<Ts...>::exec();
}
};
template <>
struct announce_helper<> {
static inline void exec() {
// end of recursion
}
};
} // namespace <anonymous> } // namespace <anonymous>
...@@ -209,11 +196,16 @@ void middleman::initialize() { ...@@ -209,11 +196,16 @@ void middleman::initialize() {
}); });
m_backend->thread_id(m_thread.get_id()); m_backend->thread_id(m_thread.get_id());
// announce io-related types // announce io-related types
announce_helper<new_data_msg, new_connection_msg, do_announce<new_data_msg>("caf::io::new_data_msg");
acceptor_closed_msg, connection_closed_msg, do_announce<new_connection_msg>("caf::io::new_connection_msg");
accept_handle, acceptor_closed_msg, do_announce<acceptor_closed_msg>("caf::io::acceptor_closed_msg");
connection_closed_msg, connection_handle, do_announce<connection_closed_msg>("caf::io::connection_closed_msg");
new_connection_msg, new_data_msg>::exec(); do_announce<accept_handle>("caf::io::accept_handle");
do_announce<acceptor_closed_msg>("caf::io::acceptor_closed_msg");
do_announce<connection_closed_msg>("caf::io::connection_closed_msg");
do_announce<connection_handle>("caf::io::connection_handle");
do_announce<new_connection_msg>("caf::io::new_connection_msg");
do_announce<new_data_msg>("caf::io::new_data_msg");
} }
void middleman::stop() { void middleman::stop() {
......
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#include "caf/detail/int_list.hpp" #include "caf/detail/int_list.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
#include "caf/detail/demangle.hpp"
using std::cout; using std::cout;
using std::endl; using std::endl;
using std::is_same; using std::is_same;
...@@ -53,10 +51,7 @@ int main() { ...@@ -53,10 +51,7 @@ int main() {
using il0 = int_list<0, 1, 2, 3, 4, 5>; using il0 = int_list<0, 1, 2, 3, 4, 5>;
using il1 = int_list<4, 5>; using il1 = int_list<4, 5>;
using il2 = typename il_right<il0, 2>::type; using il2 = typename il_right<il0, 2>::type;
CAF_CHECK_VERBOSE((is_same<il2, il1>::value), CAF_CHECK((is_same<il2, il1>::value));
"il_right<il0, 2> returned "
<< detail::demangle<il2>()
<< "expected: " << detail::demangle<il1>());
/* test tl_is_strict_subset */ { /* test tl_is_strict_subset */ {
using list_a = type_list<int, float, double>; using list_a = type_list<int, float, double>;
......
...@@ -401,7 +401,7 @@ void test_remote_actor(std::string app_path, bool run_remote_actor) { ...@@ -401,7 +401,7 @@ void test_remote_actor(std::string app_path, bool run_remote_actor) {
int main(int argc, char** argv) { int main(int argc, char** argv) {
CAF_TEST(test_remote_actor); CAF_TEST(test_remote_actor);
announce<actor_vector>(); announce<actor_vector>("actor_vector");
cout << "this node is: " << to_string(caf::detail::singletons::get_node_id()) cout << "this node is: " << to_string(caf::detail::singletons::get_node_id())
<< endl; << endl;
message_builder{argv + 1, argv + argc}.apply({ message_builder{argv + 1, argv + argc}.apply({
......
...@@ -77,6 +77,10 @@ bool operator==(const raw_struct& lhs, const raw_struct& rhs) { ...@@ -77,6 +77,10 @@ bool operator==(const raw_struct& lhs, const raw_struct& rhs) {
} }
struct raw_struct_type_info : detail::abstract_uniform_type_info<raw_struct> { struct raw_struct_type_info : detail::abstract_uniform_type_info<raw_struct> {
using super = detail::abstract_uniform_type_info<raw_struct>;
raw_struct_type_info() : super("raw_struct") {
// nop
}
void serialize(const void* ptr, serializer* sink) const override { void serialize(const void* ptr, serializer* sink) const override {
auto rs = reinterpret_cast<const raw_struct*>(ptr); auto rs = reinterpret_cast<const raw_struct*>(ptr);
sink->write_value(static_cast<uint32_t>(rs->str.size())); sink->write_value(static_cast<uint32_t>(rs->str.size()));
...@@ -92,7 +96,6 @@ struct raw_struct_type_info : detail::abstract_uniform_type_info<raw_struct> { ...@@ -92,7 +96,6 @@ struct raw_struct_type_info : detail::abstract_uniform_type_info<raw_struct> {
bool equals(const void* lhs, const void* rhs) const override { bool equals(const void* lhs, const void* rhs) const override {
return deref(lhs) == deref(rhs); return deref(lhs) == deref(rhs);
} }
}; };
void test_ieee_754() { void test_ieee_754() {
...@@ -121,7 +124,7 @@ enum class test_enum { ...@@ -121,7 +124,7 @@ enum class test_enum {
int main() { int main() {
CAF_TEST(test_serialization); CAF_TEST(test_serialization);
announce<test_enum>(); announce<test_enum>("test_enum");
test_ieee_754(); test_ieee_754();
...@@ -133,8 +136,7 @@ int main() { ...@@ -133,8 +136,7 @@ int main() {
CAF_CHECK_EQUAL(detail::impl_id<strmap>(), 2); CAF_CHECK_EQUAL(detail::impl_id<strmap>(), 2);
CAF_CHECK_EQUAL(token::value, 2); CAF_CHECK_EQUAL(token::value, 2);
announce(typeid(raw_struct), announce(typeid(raw_struct), uniform_type_info_ptr{new raw_struct_type_info});
uniform_type_info_ptr{new raw_struct_type_info});
auto nid = detail::singletons::get_node_id(); auto nid = detail::singletons::get_node_id();
auto nid_str = to_string(nid); auto nid_str = to_string(nid);
......
...@@ -166,28 +166,26 @@ void testee1(event_based_actor* self) { ...@@ -166,28 +166,26 @@ void testee1(event_based_actor* self) {
}); });
} }
template <class Testee>
string behavior_test(scoped_actor& self, actor et) { string behavior_test(scoped_actor& self, actor et) {
string testee_name = detail::to_uniform_name(typeid(Testee)); CAF_LOGF_TRACE(CAF_TARG(et, to_string));
CAF_LOGF_TRACE(CAF_TARG(et, to_string) << ", " << CAF_ARG(testee_name));
string result; string result;
self->send(et, 1); self->send(et, 1);
self->send(et, 2); self->send(et, 2);
self->send(et, 3); self->send(et, 3);
self->send(et, .1f); self->send(et, .1f);
self->send(et, "hello " + testee_name); self->send(et, "hello");
self->send(et, .2f); self->send(et, .2f);
self->send(et, .3f); self->send(et, .3f);
self->send(et, "hello again " + testee_name); self->send(et, "hello again");
self->send(et, "goodbye " + testee_name); self->send(et, "goodbye");
self->send(et, atom("get_state")); self->send(et, atom("get_state"));
self->receive ( self->receive (
[&](const string& str) { [&](const string& str) {
result = str; result = str;
}, },
after(chrono::minutes(1)) >> [&]() { after(chrono::minutes(1)) >> [&]() {
CAF_LOGF_ERROR(testee_name << " does not reply"); CAF_LOGF_ERROR("actor does not reply");
throw runtime_error(testee_name + " does not reply"); throw runtime_error("actor does not reply");
} }
); );
self->send_exit(et, exit_reason::user_shutdown); self->send_exit(et, exit_reason::user_shutdown);
...@@ -529,9 +527,9 @@ void test_spawn() { ...@@ -529,9 +527,9 @@ void test_spawn() {
self->await_all_other_actors_done(); self->await_all_other_actors_done();
CAF_CHECKPOINT(); CAF_CHECKPOINT();
auto res1 = behavior_test<testee_actor>(self, spawn<blocking_api>(testee_actor{})); auto res1 = behavior_test(self, spawn<blocking_api>(testee_actor{}));
CAF_CHECK_EQUAL("wait4int", res1); CAF_CHECK_EQUAL("wait4int", res1);
CAF_CHECK_EQUAL(behavior_test<event_testee>(self, spawn<event_testee>()), "wait4int"); CAF_CHECK_EQUAL(behavior_test(self, spawn<event_testee>()), "wait4int");
self->await_all_other_actors_done(); self->await_all_other_actors_done();
CAF_CHECKPOINT(); CAF_CHECKPOINT();
......
...@@ -86,8 +86,8 @@ uint16_t run_server() { ...@@ -86,8 +86,8 @@ uint16_t run_server() {
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
announce<ping>(&ping::value); announce<ping>("ping", &ping::value);
announce<pong>(&pong::value); announce<pong>("pong", &pong::value);
message_builder{argv + 1, argv + argc}.apply({ message_builder{argv + 1, argv + argc}.apply({
on("-c", spro<uint16_t>)>> [](uint16_t port) { on("-c", spro<uint16_t>)>> [](uint16_t port) {
CAF_PRINT("run in client mode"); CAF_PRINT("run in client mode");
......
...@@ -177,7 +177,7 @@ void test_event_testee() { ...@@ -177,7 +177,7 @@ void test_event_testee() {
self->send(et, "goodbye event testee!"); self->send(et, "goodbye event testee!");
typed_actor<replies_to<get_state_msg>::with<string>> sub_et = et; typed_actor<replies_to<get_state_msg>::with<string>> sub_et = et;
// $:: is the anonymous namespace // $:: is the anonymous namespace
set<string> iface{"caf::replies_to<$::get_state_msg>::with<@str>", set<string> iface{"caf::replies_to<get_state_msg>::with<@str>",
"caf::replies_to<@str>::with<void>", "caf::replies_to<@str>::with<void>",
"caf::replies_to<float>::with<void>", "caf::replies_to<float>::with<void>",
"caf::replies_to<@i32>::with<@i32>"}; "caf::replies_to<@i32>::with<@i32>"};
...@@ -311,9 +311,9 @@ void test_sending_typed_actors_and_down_msg() { ...@@ -311,9 +311,9 @@ void test_sending_typed_actors_and_down_msg() {
int main() { int main() {
CAF_TEST(test_typed_spawn); CAF_TEST(test_typed_spawn);
// announce stuff // announce stuff
announce<get_state_msg>(); announce<get_state_msg>("get_state_msg");
announce<int_actor>(); announce<int_actor>("int_actor");
announce<my_request>(&my_request::a, &my_request::b); announce<my_request>("my_request", &my_request::a, &my_request::b);
// run test series with typed_server(1|2) // run test series with typed_server(1|2)
test_typed_spawn(spawn_typed(typed_server1)); test_typed_spawn(spawn_typed(typed_server1));
await_all_actors_done(); await_all_actors_done();
......
...@@ -107,14 +107,14 @@ T& append(T& storage, U&& u, Us&&... us) { ...@@ -107,14 +107,14 @@ T& append(T& storage, U&& u, Us&&... us) {
int main() { int main() {
CAF_TEST(test_uniform_type); CAF_TEST(test_uniform_type);
auto announce1 = announce<foo>(&foo::value); auto announce1 = announce<foo>("foo", &foo::value);
auto announce2 = announce<foo>(&foo::value); auto announce2 = announce<foo>("foo", &foo::value);
auto announce3 = announce<foo>(&foo::value); auto announce3 = announce<foo>("foo", &foo::value);
auto announce4 = announce<foo>(&foo::value); auto announce4 = announce<foo>("foo", &foo::value);
CAF_CHECK(announce1 == announce2); CAF_CHECK(announce1 == announce2);
CAF_CHECK(announce1 == announce3); CAF_CHECK(announce1 == announce3);
CAF_CHECK(announce1 == announce4); CAF_CHECK(announce1 == announce4);
CAF_CHECK_EQUAL(announce1->name(), "$::foo"); CAF_CHECK_EQUAL(announce1->name(), "foo");
{ {
auto uti = uniform_typeid<atom_value>(); auto uti = uniform_typeid<atom_value>();
CAF_CHECK(uti != nullptr); CAF_CHECK(uti != nullptr);
...@@ -124,7 +124,7 @@ int main() { ...@@ -124,7 +124,7 @@ int main() {
// the uniform_type_info implementation is correct // the uniform_type_info implementation is correct
std::set<std::string> expected = { std::set<std::string> expected = {
// local types // local types
"$::foo", // <anonymous namespace>::foo "foo", // <anonymous namespace>::foo
// primitive types // primitive types
"bool", "@i8", "@i16", "bool", "@i8", "@i16",
"@i32", "@i64", // signed integer names "@i32", "@i64", // signed integer names
...@@ -166,7 +166,7 @@ int main() { ...@@ -166,7 +166,7 @@ int main() {
"caf::io::new_data_msg")); "caf::io::new_data_msg"));
} }
// check whether enums can be announced as members // check whether enums can be announced as members
announce<test_enum>(); announce<test_enum>("test_enum");
announce<test_struct>(&test_struct::test_value); announce<test_struct>("test_struct", &test_struct::test_value);
return CAF_TEST_RESULT(); return CAF_TEST_RESULT();
} }
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