Commit 101a66dc authored by Dominik Charousset's avatar Dominik Charousset

Add type_erased_tuple, drop == support for message

parent 329f45ff
...@@ -87,6 +87,7 @@ set (LIBCAF_CORE_SRCS ...@@ -87,6 +87,7 @@ set (LIBCAF_CORE_SRCS
src/sync_request_bouncer.cpp src/sync_request_bouncer.cpp
src/try_match.cpp src/try_match.cpp
src/type_erased_value.cpp src/type_erased_value.cpp
src/type_erased_tuple.cpp
src/uniform_type_info_map.cpp) src/uniform_type_info_map.cpp)
add_custom_target(libcaf_core) add_custom_target(libcaf_core)
......
...@@ -55,7 +55,7 @@ public: ...@@ -55,7 +55,7 @@ public:
// fill a pseudo tuple with values and invoke f // fill a pseudo tuple with values and invoke f
detail::pseudo_tuple<Ts...> buf; detail::pseudo_tuple<Ts...> buf;
// msg is guaranteed to be detached, hence we don't need to // msg is guaranteed to be detached, hence we don't need to
// check this condition over and over again via mutable_at // check this condition over and over again via get_mutable
for (size_t i = 0; i < msg.size(); ++i) for (size_t i = 0; i < msg.size(); ++i)
buf[i] = const_cast<void*>(msg.at(i)); buf[i] = const_cast<void*>(msg.at(i));
return detail::apply_args(f, detail::get_indices(buf), buf); return detail::apply_args(f, detail::get_indices(buf), buf);
......
...@@ -122,11 +122,9 @@ public: ...@@ -122,11 +122,9 @@ public:
template <class T> template <class T>
actor_system_config& add_message_type(std::string name) { actor_system_config& add_message_type(std::string name) {
static_assert(std::is_empty<T>::value static_assert(std::is_empty<T>::value
|| (detail::is_comparable<T, T>::value || (std::is_default_constructible<T>::value
&& std::is_default_constructible<T>::value
&& std::is_copy_constructible<T>::value), && std::is_copy_constructible<T>::value),
"T must provide default and copy constructors " "T must provide default and copy constructors");
"as well as operator==");
static_assert(detail::is_serializable<T>::value, "T must be serializable"); static_assert(detail::is_serializable<T>::value, "T must be serializable");
type_names_by_rtti_.emplace(std::type_index(typeid(T)), name); type_names_by_rtti_.emplace(std::type_index(typeid(T)), name);
value_factories_by_name_.emplace(std::move(name), &make_type_erased<T>); value_factories_by_name_.emplace(std::move(name), &make_type_erased<T>);
......
...@@ -38,28 +38,23 @@ public: ...@@ -38,28 +38,23 @@ public:
static cow_ptr make(std::initializer_list<cow_ptr> xs); static cow_ptr make(std::initializer_list<cow_ptr> xs);
void* mutable_at(size_t pos) override; void* get_mutable(size_t pos) override;
void serialize_at(deserializer& source, size_t pos) override; void load(size_t pos, deserializer& source) override;
size_t size() const override; size_t size() const override;
cow_ptr copy() const override; cow_ptr copy() const override;
const void* at(size_t pos) const override; const void* get(size_t pos) const override;
bool compare_at(size_t, const element_rtti&, const void*) const override;
bool match_element(size_t pos, uint16_t typenr,
const std::type_info* rtti) const override;
uint32_t type_token() const override; uint32_t type_token() const override;
element_rtti type_at(size_t pos) const override; rtti_pair type(size_t pos) const override;
void serialize_at(serializer& sink, size_t pos) const override; void save(size_t pos, serializer& sink) const override;
std::string stringify_at(size_t pos) const override; std::string stringify(size_t pos) const override;
concatenated_tuple(std::initializer_list<cow_ptr> xs); concatenated_tuple(std::initializer_list<cow_ptr> xs);
......
...@@ -47,28 +47,23 @@ public: ...@@ -47,28 +47,23 @@ public:
// creates a typed subtuple from `d` with mapping `v` // creates a typed subtuple from `d` with mapping `v`
static cow_ptr make(cow_ptr d, vector_type v); static cow_ptr make(cow_ptr d, vector_type v);
void* mutable_at(size_t pos) override; void* get_mutable(size_t pos) override;
void serialize_at(deserializer& source, size_t pos) override; void load(size_t pos, deserializer& source) override;
size_t size() const override; size_t size() const override;
cow_ptr copy() const override; cow_ptr copy() const override;
const void* at(size_t pos) const override; const void* get(size_t pos) const override;
bool compare_at(size_t, const element_rtti&, const void*) const override;
bool match_element(size_t pos, uint16_t typenr,
const std::type_info* rtti) const override;
uint32_t type_token() const override; uint32_t type_token() const override;
element_rtti type_at(size_t pos) const override; rtti_pair type(size_t pos) const override;
void serialize_at(serializer& sink, size_t pos) const override; void save(size_t pos, serializer& sink) const override;
std::string stringify_at(size_t pos) const override; std::string stringify(size_t pos) const override;
inline const cow_ptr& decorated() const { inline const cow_ptr& decorated() const {
return decorated_; return decorated_;
......
...@@ -41,27 +41,21 @@ public: ...@@ -41,27 +41,21 @@ public:
~dynamic_message_data(); ~dynamic_message_data();
const void* at(size_t pos) const override; const void* get(size_t pos) const override;
void serialize_at(serializer& sink, size_t pos) const override; void save(size_t pos, serializer& sink) const override;
void serialize_at(deserializer& source, size_t pos) override; void load(size_t pos, deserializer& source) override;
bool compare_at(size_t pos, const element_rtti& rtti, void* get_mutable(size_t pos) override;
const void* x) const override;
void* mutable_at(size_t pos) override;
size_t size() const override; size_t size() const override;
cow_ptr copy() const override; cow_ptr copy() const override;
bool match_element(size_t pos, uint16_t nr, rtti_pair type(size_t pos) const override;
const std::type_info* ptr) const override;
element_rtti type_at(size_t pos) const override;
std::string stringify_at(size_t pos) const override; std::string stringify(size_t pos) const override;
uint32_t type_token() const override; uint32_t type_token() const override;
......
...@@ -43,29 +43,23 @@ public: ...@@ -43,29 +43,23 @@ public:
// creates a typed subtuple from `d` with mapping `v` // creates a typed subtuple from `d` with mapping `v`
static cow_ptr make(message x, message y); static cow_ptr make(message x, message y);
void* mutable_at(size_t pos) override; void* get_mutable(size_t pos) override;
void serialize_at(deserializer& source, size_t pos) override; void load(size_t pos, deserializer& source) override;
size_t size() const override; size_t size() const override;
cow_ptr copy() const override; cow_ptr copy() const override;
const void* at(size_t pos) const override; const void* get(size_t pos) const override;
bool compare_at(size_t pos, const element_rtti& rtti,
const void* x) const override;
bool match_element(size_t pos, uint16_t typenr,
const std::type_info* rtti) const override;
uint32_t type_token() const override; uint32_t type_token() const override;
element_rtti type_at(size_t pos) const override; rtti_pair type(size_t pos) const override;
void serialize_at(serializer& sink, size_t pos) const override; void save(size_t pos, serializer& sink) const override;
std::string stringify_at(size_t pos) const override; std::string stringify(size_t pos) const override;
const mapping_type& mapping() const; const mapping_type& mapping() const;
......
...@@ -29,63 +29,21 @@ ...@@ -29,63 +29,21 @@
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/ref_counted.hpp" #include "caf/ref_counted.hpp"
#include "caf/intrusive_ptr.hpp" #include "caf/intrusive_ptr.hpp"
#include "caf/type_erased_tuple.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
namespace caf { namespace caf {
namespace detail { namespace detail {
class message_data : public ref_counted { class message_data : public ref_counted, public type_erased_tuple {
public: public:
message_data() = default; message_data() = default;
message_data(const message_data&) = default; message_data(const message_data&) = default;
~message_data(); ~message_data();
using element_rtti = std::pair<uint16_t, const std::type_info*>; // nested types
/****************************************************************************
* modifiers *
****************************************************************************/
virtual void* mutable_at(size_t pos) = 0;
virtual void serialize_at(deserializer& source, size_t pos) = 0;
/****************************************************************************
* observers *
****************************************************************************/
// compares each element using uniform_type_info objects
bool equals(const message_data& other) const;
uint16_t type_nr_at(size_t pos) const;
virtual size_t size() const = 0;
virtual const void* at(size_t pos) const = 0;
// Selects type `T` from `pos`, compares this type to `rtti` and returns
// `*reinterpret_cast<const T*>(x) == *reinterpret_cast<const T*>(at(pos))`
// if the types match, `false` otherwise.
virtual bool compare_at(size_t pos, const element_rtti& rtti,
const void* x) const = 0;
// Tries to match element at position `pos` to given RTTI.
virtual bool match_element(size_t pos, uint16_t typenr,
const std::type_info* rtti) const = 0;
virtual uint32_t type_token() const = 0;
virtual element_rtti type_at(size_t pos) const = 0;
virtual std::string stringify_at(size_t pos) const = 0;
virtual void serialize_at(serializer& sink, size_t pos) const = 0;
/****************************************************************************
* nested types *
****************************************************************************/
class cow_ptr { class cow_ptr {
public: public:
...@@ -104,9 +62,7 @@ public: ...@@ -104,9 +62,7 @@ public:
// nop // nop
} }
/************************************************************************** // modifiers
* modifiers *
**************************************************************************/
inline void swap(cow_ptr& other) { inline void swap(cow_ptr& other) {
ptr_.swap(other.ptr_); ptr_.swap(other.ptr_);
...@@ -131,9 +87,8 @@ public: ...@@ -131,9 +87,8 @@ public:
inline message_data& operator*() { inline message_data& operator*() {
return *get_unshared(); return *get_unshared();
} }
/**************************************************************************
* observers * // observers
**************************************************************************/
inline const message_data* operator->() const { inline const message_data* operator->() const {
return ptr_.get(); return ptr_.get();
......
...@@ -37,7 +37,7 @@ struct pseudo_tuple { ...@@ -37,7 +37,7 @@ struct pseudo_tuple {
inline const_pointer at(size_t p) const { return data[p]; } inline const_pointer at(size_t p) const { return data[p]; }
inline pointer mutable_at(size_t p) { return data[p]; } inline pointer get_mutable(size_t p) { return data[p]; }
inline pointer& operator[](size_t p) { return data[p]; } inline pointer& operator[](size_t p) { return data[p]; }
...@@ -55,7 +55,7 @@ get(const detail::pseudo_tuple<Ts...>& tv) { ...@@ -55,7 +55,7 @@ get(const detail::pseudo_tuple<Ts...>& tv) {
template <size_t N, class... Ts> template <size_t N, class... Ts>
typename detail::type_at<N, Ts...>::type& get(detail::pseudo_tuple<Ts...>& tv) { typename detail::type_at<N, Ts...>::type& get(detail::pseudo_tuple<Ts...>& tv) {
static_assert(N < sizeof...(Ts), "N >= tv.size()"); static_assert(N < sizeof...(Ts), "N >= tv.size()");
auto vp = tv.mutable_at(N); auto vp = tv.get_mutable(N);
CAF_ASSERT(vp != nullptr); CAF_ASSERT(vp != nullptr);
return *reinterpret_cast<typename detail::type_at<N, Ts...>::type*>(vp); return *reinterpret_cast<typename detail::type_at<N, Ts...>::type*>(vp);
} }
......
...@@ -104,14 +104,14 @@ struct tup_ptr_access<Pos, Max, false> { ...@@ -104,14 +104,14 @@ struct tup_ptr_access<Pos, Max, false> {
template <class T, uint16_t N = detail::type_nr<T>::value> template <class T, uint16_t N = detail::type_nr<T>::value>
struct tuple_vals_type_helper { struct tuple_vals_type_helper {
static typename message_data::element_rtti get() { static typename message_data::rtti_pair get() {
return {N, nullptr}; return {N, nullptr};
} }
}; };
template <class T> template <class T>
struct tuple_vals_type_helper<T, 0> { struct tuple_vals_type_helper<T, 0> {
static typename message_data::element_rtti get() { static typename message_data::rtti_pair get() {
return {0, &typeid(T)}; return {0, &typeid(T)};
} }
}; };
...@@ -123,7 +123,7 @@ public: ...@@ -123,7 +123,7 @@ public:
using super = message_data; using super = message_data;
using element_rtti = typename message_data::element_rtti; using rtti_pair = typename message_data::rtti_pair;
using data_type = std::tuple<Ts...>; using data_type = std::tuple<Ts...>;
...@@ -152,52 +152,33 @@ public: ...@@ -152,52 +152,33 @@ public:
return message_data::cow_ptr(new tuple_vals(*this), false); return message_data::cow_ptr(new tuple_vals(*this), false);
} }
const void* at(size_t pos) const override { const void* get(size_t pos) const override {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
return tup_ptr_access<0, sizeof...(Ts)>::get(pos, data_); return tup_ptr_access<0, sizeof...(Ts)>::get(pos, data_);
} }
bool compare_at(size_t pos, const element_rtti& rtti, const void* x) const override { void* get_mutable(size_t pos) override {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
auto& rtti_at_pos = types_[pos]; return const_cast<void*>(get(pos));
if (rtti.first != rtti_at_pos.first)
return false;
if (rtti_at_pos.first == 0 && *rtti_at_pos.second != *rtti.second)
return false;
return tup_ptr_access<0, sizeof...(Ts)>::cmp(pos, data_, x);
} }
void* mutable_at(size_t pos) override { std::string stringify(size_t pos) const override {
CAF_ASSERT(pos < size());
return const_cast<void*>(at(pos));
}
std::string stringify_at(size_t pos) const override {
return tup_ptr_access<0, sizeof...(Ts)>::stringify(pos, data_); return tup_ptr_access<0, sizeof...(Ts)>::stringify(pos, data_);
} }
void serialize_at(deserializer& source, size_t pos) override { void load(size_t pos, deserializer& source) override {
return tup_ptr_access<0, sizeof...(Ts)>::serialize(pos, data_, source); return tup_ptr_access<0, sizeof...(Ts)>::serialize(pos, data_, source);
} }
bool match_element(size_t pos, uint16_t typenr,
const std::type_info* rtti) const override {
CAF_ASSERT(pos < size());
auto& et = types_[pos];
if (et.first != typenr)
return false;
return et.first != 0 || et.second == rtti || *et.second == *rtti;
}
uint32_t type_token() const override { uint32_t type_token() const override {
return make_type_token<Ts...>(); return make_type_token<Ts...>();
} }
element_rtti type_at(size_t pos) const override { rtti_pair type(size_t pos) const override {
return types_[pos]; return types_[pos];
} }
void serialize_at(serializer& sink, size_t pos) const override { void save(size_t pos, serializer& sink) const override {
// the serialization framework uses non-const arguments for deserialization, // the serialization framework uses non-const arguments for deserialization,
// but this cast is safe since the values are not actually changed // but this cast is safe since the values are not actually changed
auto& nc_data = const_cast<data_type&>(data_); auto& nc_data = const_cast<data_type&>(data_);
...@@ -206,7 +187,7 @@ public: ...@@ -206,7 +187,7 @@ public:
private: private:
data_type data_; data_type data_;
std::array<element_rtti, sizeof...(Ts)> types_; std::array<rtti_pair, sizeof...(Ts)> types_;
}; };
} // namespace detail } // namespace detail
......
...@@ -150,8 +150,8 @@ template <class A, class B, template <class, class> class Predicate> ...@@ -150,8 +150,8 @@ template <class A, class B, template <class, class> class Predicate>
struct static_asserter { struct static_asserter {
static void verify_match() { static void verify_match() {
static constexpr int x = Predicate<A, B>::value; static constexpr int x = Predicate<A, B>::value;
using type_at_x = typename tl_at<B, (x < 0 ? 0 : x)>::type; using type_x = typename tl_at<B, (x < 0 ? 0 : x)>::type;
static_error_printer<x, x, type_at_x> dummy; static_error_printer<x, x, type_x> dummy;
static_cast<void>(dummy); static_cast<void>(dummy);
} }
}; };
......
...@@ -91,8 +91,6 @@ public: ...@@ -91,8 +91,6 @@ public:
using mailbox_type = detail::single_reader_queue<mailbox_element, using mailbox_type = detail::single_reader_queue<mailbox_element,
detail::disposer>; detail::disposer>;
//static constexpr auto memory_cache_flag = detail::needs_embedding;
~local_actor(); ~local_actor();
/**************************************************************************** /****************************************************************************
...@@ -677,6 +675,9 @@ protected: ...@@ -677,6 +675,9 @@ protected:
// used only in thread-mapped actors // used only in thread-mapped actors
void await_data(); void await_data();
// used by both event-based and blocking actors
mailbox_type mailbox_;
// identifies the execution unit this actor is currently executed by // identifies the execution unit this actor is currently executed by
execution_unit* context_; execution_unit* context_;
...@@ -702,9 +703,6 @@ protected: ...@@ -702,9 +703,6 @@ protected:
// used by both event-based and blocking actors // used by both event-based and blocking actors
detail::behavior_stack bhvr_stack_; detail::behavior_stack bhvr_stack_;
// used by both event-based and blocking actors
mailbox_type mailbox_;
// used by functor-based actors to implemented make_behavior() or act() // used by functor-based actors to implemented make_behavior() or act()
std::function<behavior (local_actor*)> initial_behavior_fac_; std::function<behavior (local_actor*)> initial_behavior_fac_;
......
...@@ -205,7 +205,7 @@ public: ...@@ -205,7 +205,7 @@ public:
// update pointers in our intermediate tuple // update pointers in our intermediate tuple
for (size_t i = 0; i < msg.size(); ++i) { for (size_t i = 0; i < msg.size(); ++i) {
// msg is guaranteed to be detached, hence we don't need to // msg is guaranteed to be detached, hence we don't need to
// check this condition over and over again via mutable_at // check this condition over and over again via get_mutable
it[i] = const_cast<void*>(msg.at(i)); it[i] = const_cast<void*>(msg.at(i));
} }
} }
......
...@@ -94,14 +94,11 @@ public: ...@@ -94,14 +94,11 @@ public:
} }
/// Returns a mutable pointer to the element at position `p`. /// Returns a mutable pointer to the element at position `p`.
void* mutable_at(size_t p); void* get_mutable(size_t p);
/// Returns a const pointer to the element at position `p`. /// Returns a const pointer to the element at position `p`.
const void* at(size_t p) const; const void* at(size_t p) const;
/// Returns @c true if `*this == other, otherwise false.
bool equals(const message& other) const;
/// Returns true if `size() == 0, otherwise false. /// Returns true if `size() == 0, otherwise false.
inline bool empty() const { inline bool empty() const {
return size() == 0; return size() == 0;
...@@ -118,7 +115,7 @@ public: ...@@ -118,7 +115,7 @@ public:
template <class T> template <class T>
T& get_as_mutable(size_t p) { T& get_as_mutable(size_t p) {
CAF_ASSERT(match_element(p, detail::type_nr<T>::value, &typeid(T))); CAF_ASSERT(match_element(p, detail::type_nr<T>::value, &typeid(T)));
return *reinterpret_cast<T*>(mutable_at(p)); return *reinterpret_cast<T*>(get_mutable(p));
} }
/// Returns `handler(*this)`. /// Returns `handler(*this)`.
...@@ -355,16 +352,6 @@ struct message::cli_res { ...@@ -355,16 +352,6 @@ struct message::cli_res {
std::string error; std::string error;
}; };
/// @relates message
inline bool operator==(const message& lhs, const message& rhs) {
return lhs.equals(rhs);
}
/// @relates message
inline bool operator!=(const message& lhs, const message& rhs) {
return !(lhs == rhs);
}
/// @relates message /// @relates message
inline message operator+(const message& lhs, const message& rhs) { inline message operator+(const message& lhs, const message& rhs) {
return message::concat(lhs, rhs); return message::concat(lhs, rhs);
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* 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_TYPE_ERASED_COLLECTION_HPP
#define CAF_TYPE_ERASED_COLLECTION_HPP
#include <cstddef>
#include <cstdint>
#include <typeinfo>
#include "caf/fwd.hpp"
namespace caf {
/// Represents a tuple of type-erased values.
class type_erased_tuple {
public:
using rtti_pair = std::pair<uint16_t, const std::type_info*>;
virtual ~type_erased_tuple();
// pure virtual modifiers
virtual void* get_mutable(size_t pos) = 0;
virtual void load(size_t pos, deserializer& source) = 0;
// pure virtual observers
virtual size_t size() const = 0;
virtual uint32_t type_token() const = 0;
virtual rtti_pair type(size_t pos) const = 0;
virtual const void* get(size_t pos) const = 0;
virtual std::string stringify(size_t pos) const = 0;
virtual void save(size_t pos, serializer& sink) const = 0;
// observers
/// Checks whether the type of the stored value matches
/// the type nr and type info object.
bool matches(size_t pos, uint16_t tnr, const std::type_info* tinf) const;
// inline observers
inline uint16_t type_nr(size_t pos) const {
return type(pos).first;
}
/// Checks whether the type of the stored value matches `rtti`.
inline bool matches(size_t pos, const rtti_pair& rtti) const {
return matches(pos, rtti.first, rtti.second);
}
};
} // namespace caf
#endif // CAF_TYPE_ERASED_COLLECTION_HPP
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#ifndef CAF_TYPE_ERASED_VALUE_HPP #ifndef CAF_TYPE_ERASED_VALUE_HPP
#define CAF_TYPE_ERASED_VALUE_HPP #define CAF_TYPE_ERASED_VALUE_HPP
#include <cstdint>
#include <typeinfo> #include <typeinfo>
#include "caf/deep_to_string.hpp" #include "caf/deep_to_string.hpp"
...@@ -30,25 +31,59 @@ ...@@ -30,25 +31,59 @@
namespace caf { namespace caf {
class type_erased_value;
using type_erased_value_ptr = std::unique_ptr<type_erased_value>;
/// Represents a single type-erased value.
class type_erased_value { class type_erased_value {
public: public:
using rtti_pair = std::pair<uint16_t, const std::type_info*>;
virtual ~type_erased_value(); virtual ~type_erased_value();
virtual void* get() = 0; // pure virtual modifiers
virtual const void* get() const = 0; /// Returns a mutable pointer to the stored value.
virtual void* get_mutable() = 0;
virtual bool equals(const void*) const = 0; /// Load the content for the stored value from `source`.
virtual void load(deserializer& source) = 0;
virtual void save(serializer&) const = 0; // pure virtual observers
virtual void load(deserializer&) = 0; /// Returns the type number and type information object for the stored value.
virtual rtti_pair type() const = 0;
/// Returns a pointer to the stored value.
virtual const void* get() const = 0;
/// Saves the content of the stored value to `sink`.
virtual void save(serializer& sink) const = 0;
/// Converts the stored value to a string.
virtual std::string stringify() const = 0; virtual std::string stringify() const = 0;
virtual type_erased_value* copy() const = 0; /// Returns a copy of the stored value.
virtual type_erased_value_ptr copy() const = 0;
// observers
/// Checks whether the type of the stored value matches
/// the type nr and type info object.
bool matches(uint16_t tnr, const std::type_info* tinf) const;
virtual std::pair<uint16_t, const std::type_info*> type() const = 0; // inline observers
/// Returns the type number for the stored value.
inline uint16_t type_nr() const {
return type().first;
}
/// Checks whether the type of the stored value matches `rtti`.
inline bool matches(const rtti_pair& rtti) const {
return matches(rtti.first, rtti.second);
}
}; };
template <class T> template <class T>
...@@ -64,7 +99,7 @@ struct type_erased_value_impl : public type_erased_value { ...@@ -64,7 +99,7 @@ struct type_erased_value_impl : public type_erased_value {
// nop // nop
} }
void* get() override { void* get_mutable() override {
return &x; return &x;
} }
...@@ -72,10 +107,6 @@ struct type_erased_value_impl : public type_erased_value { ...@@ -72,10 +107,6 @@ struct type_erased_value_impl : public type_erased_value {
return &x; return &x;
} }
bool equals(const void* y) const override {
return detail::safe_equal(x, *reinterpret_cast<const T*>(y));
}
void save(serializer& sink) const override { void save(serializer& sink) const override {
detail::try_serialize(sink, const_cast<T*>(&x)); detail::try_serialize(sink, const_cast<T*>(&x));
} }
...@@ -88,11 +119,11 @@ struct type_erased_value_impl : public type_erased_value { ...@@ -88,11 +119,11 @@ struct type_erased_value_impl : public type_erased_value {
return deep_to_string(x); return deep_to_string(x);
} }
type_erased_value* copy() const override { type_erased_value_ptr copy() const override {
return new type_erased_value_impl(x); return type_erased_value_ptr{new type_erased_value_impl(x)};
} }
std::pair<uint16_t, const std::type_info*> type() const override { rtti_pair type() const override {
auto nr = detail::type_nr<T>::value; auto nr = detail::type_nr<T>::value;
return {nr, &typeid(T)}; return {nr, &typeid(T)};
} }
...@@ -111,7 +142,7 @@ struct type_erased_value_impl<T[N]> : public type_erased_value { ...@@ -111,7 +142,7 @@ struct type_erased_value_impl<T[N]> : public type_erased_value {
// nop // nop
} }
void* get() override { void* get_mutable() override {
T* tmp = xs; T* tmp = xs;
return reinterpret_cast<void*>(tmp); return reinterpret_cast<void*>(tmp);
} }
...@@ -121,14 +152,6 @@ struct type_erased_value_impl<T[N]> : public type_erased_value { ...@@ -121,14 +152,6 @@ struct type_erased_value_impl<T[N]> : public type_erased_value {
return reinterpret_cast<const void*>(tmp); return reinterpret_cast<const void*>(tmp);
} }
bool equals(const void* vptr) const override {
auto cmp = [](const T& x, const T& y) {
return detail::safe_equal(x, y);
};
auto ys = reinterpret_cast<const T*>(vptr);
return std::equal(xs, xs + N, ys, cmp);
}
void save(serializer& sink) const override { void save(serializer& sink) const override {
array_serialize(sink, const_cast<array_type&>(xs)); array_serialize(sink, const_cast<array_type&>(xs));
} }
...@@ -141,11 +164,11 @@ struct type_erased_value_impl<T[N]> : public type_erased_value { ...@@ -141,11 +164,11 @@ struct type_erased_value_impl<T[N]> : public type_erased_value {
return deep_to_string(xs); return deep_to_string(xs);
} }
type_erased_value* copy() const override { type_erased_value_ptr copy() const override {
return new type_erased_value_impl(xs); return new type_erased_value_impl(xs);
} }
std::pair<uint16_t, const std::type_info*> type() const override { rtti_pair type() const override {
auto nr = detail::type_nr<T>::value; auto nr = detail::type_nr<T>::value;
return {nr, &typeid(T)}; return {nr, &typeid(T)};
} }
...@@ -212,8 +235,6 @@ struct type_erased_value_impl<T[N]> : public type_erased_value { ...@@ -212,8 +235,6 @@ struct type_erased_value_impl<T[N]> : public type_erased_value {
} }
}; };
using type_erased_value_ptr = std::unique_ptr<type_erased_value>;
template <class T, class... Ts> template <class T, class... Ts>
type_erased_value_ptr make_type_erased(Ts&&... xs) { type_erased_value_ptr make_type_erased(Ts&&... xs) {
type_erased_value_ptr result; type_erased_value_ptr result;
......
...@@ -198,8 +198,6 @@ void actor_registry::start() { ...@@ -198,8 +198,6 @@ void actor_registry::start() {
if (key == "*") if (key == "*")
return; return;
auto& vp = self->state.data[key]; auto& vp = self->state.data[key];
if (vp.first == msg)
return;
vp.first = std::move(msg); vp.first = std::move(msg);
for (auto& subscriber : vp.second) for (auto& subscriber : vp.second)
if (subscriber != self->current_sender()) if (subscriber != self->current_sender())
......
...@@ -31,19 +31,18 @@ auto concatenated_tuple::make(std::initializer_list<cow_ptr> xs) -> cow_ptr { ...@@ -31,19 +31,18 @@ auto concatenated_tuple::make(std::initializer_list<cow_ptr> xs) -> cow_ptr {
return cow_ptr{make_counted<concatenated_tuple>(xs)}; return cow_ptr{make_counted<concatenated_tuple>(xs)};
} }
void* concatenated_tuple::mutable_at(size_t pos) { void* concatenated_tuple::get_mutable(size_t pos) {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
auto selected = select(pos); auto selected = select(pos);
return selected.first->mutable_at(selected.second); return selected.first->get_mutable(selected.second);
} }
void concatenated_tuple::serialize_at(deserializer& source, size_t pos) { void concatenated_tuple::load(size_t pos, deserializer& source) {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
auto selected = select(pos); auto selected = select(pos);
selected.first->serialize_at(source, selected.second); selected.first->load(selected.second, source);
} }
size_t concatenated_tuple::size() const { size_t concatenated_tuple::size() const {
return size_; return size_;
} }
...@@ -52,45 +51,32 @@ message_data::cow_ptr concatenated_tuple::copy() const { ...@@ -52,45 +51,32 @@ message_data::cow_ptr concatenated_tuple::copy() const {
return cow_ptr(new concatenated_tuple(*this), false); return cow_ptr(new concatenated_tuple(*this), false);
} }
const void* concatenated_tuple::at(size_t pos) const { const void* concatenated_tuple::get(size_t pos) const {
CAF_ASSERT(pos < size());
auto selected = select(pos);
return selected.first->at(selected.second);
}
bool concatenated_tuple::compare_at(size_t pos, const element_rtti& rtti,
const void* x) const {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
auto selected = select(pos); auto selected = select(pos);
return selected.first->compare_at(selected.second, rtti, x); return selected.first->get(selected.second);
}
bool concatenated_tuple::match_element(size_t pos, uint16_t typenr,
const std::type_info* rtti) const {
auto selected = select(pos);
return selected.first->match_element(selected.second, typenr, rtti);
} }
uint32_t concatenated_tuple::type_token() const { uint32_t concatenated_tuple::type_token() const {
return type_token_; return type_token_;
} }
message_data::element_rtti concatenated_tuple::type_at(size_t pos) const { message_data::rtti_pair concatenated_tuple::type(size_t pos) const {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
auto selected = select(pos); auto selected = select(pos);
return selected.first->type_at(selected.second); return selected.first->type(selected.second);
} }
void concatenated_tuple::serialize_at(serializer& sink, size_t pos) const { void concatenated_tuple::save(size_t pos, serializer& sink) const {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
auto selected = select(pos); auto selected = select(pos);
selected.first->serialize_at(sink, selected.second); selected.first->save(selected.second, sink);
} }
std::string concatenated_tuple::stringify_at(size_t pos) const { std::string concatenated_tuple::stringify(size_t pos) const {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
auto selected = select(pos); auto selected = select(pos);
return selected.first->stringify_at(selected.second); return selected.first->stringify(selected.second);
} }
std::pair<message_data*, size_t> concatenated_tuple::select(size_t pos) const { std::pair<message_data*, size_t> concatenated_tuple::select(size_t pos) const {
...@@ -120,7 +106,7 @@ concatenated_tuple::concatenated_tuple(std::initializer_list<cow_ptr> xs) { ...@@ -120,7 +106,7 @@ concatenated_tuple::concatenated_tuple(std::initializer_list<cow_ptr> xs) {
type_token_ = make_type_token(); type_token_ = make_type_token();
for (const auto& m : data_) for (const auto& m : data_)
for (size_t i = 0; i < m->size(); ++i) for (size_t i = 0; i < m->size(); ++i)
type_token_ = add_to_type_token(type_token_, m->type_nr_at(i)); type_token_ = add_to_type_token(type_token_, m->type_nr(i));
auto acc_size = [](size_t tmp, const cow_ptr& val) { auto acc_size = [](size_t tmp, const cow_ptr& val) {
return tmp + val->size(); return tmp + val->size();
}; };
......
...@@ -36,14 +36,14 @@ decorated_tuple::cow_ptr decorated_tuple::make(cow_ptr d, vector_type v) { ...@@ -36,14 +36,14 @@ decorated_tuple::cow_ptr decorated_tuple::make(cow_ptr d, vector_type v) {
return make_counted<decorated_tuple>(std::move(d), std::move(v)); return make_counted<decorated_tuple>(std::move(d), std::move(v));
} }
void* decorated_tuple::mutable_at(size_t pos) { void* decorated_tuple::get_mutable(size_t pos) {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
return decorated_->mutable_at(mapping_[pos]); return decorated_->get_mutable(mapping_[pos]);
} }
void decorated_tuple::serialize_at(deserializer& source, size_t pos) { void decorated_tuple::load(size_t pos, deserializer& source) {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
return decorated_->serialize_at(source, mapping_[pos]); return decorated_->load(mapping_[pos], source);
} }
size_t decorated_tuple::size() const { size_t decorated_tuple::size() const {
...@@ -54,37 +54,27 @@ message_data::cow_ptr decorated_tuple::copy() const { ...@@ -54,37 +54,27 @@ message_data::cow_ptr decorated_tuple::copy() const {
return cow_ptr(new decorated_tuple(*this), false); return cow_ptr(new decorated_tuple(*this), false);
} }
const void* decorated_tuple::at(size_t pos) const { const void* decorated_tuple::get(size_t pos) const {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
return decorated_->at(mapping_[pos]); return decorated_->get(mapping_[pos]);
}
bool decorated_tuple::compare_at(size_t pos, const element_rtti& rtti,
const void* x) const {
return decorated_->compare_at(mapping_[pos], rtti, x);
}
bool decorated_tuple::match_element(size_t pos, uint16_t typenr,
const std::type_info* rtti) const {
return decorated_->match_element(mapping_[pos], typenr, rtti);
} }
uint32_t decorated_tuple::type_token() const { uint32_t decorated_tuple::type_token() const {
return type_token_; return type_token_;
} }
message_data::element_rtti decorated_tuple::type_at(size_t pos) const { message_data::rtti_pair decorated_tuple::type(size_t pos) const {
return decorated_->type_at(mapping_[pos]); return decorated_->type(mapping_[pos]);
} }
void decorated_tuple::serialize_at(serializer& sink, size_t pos) const { void decorated_tuple::save(size_t pos, serializer& sink) const {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
return decorated_->serialize_at(sink, mapping_[pos]); return decorated_->save(mapping_[pos], sink);
} }
std::string decorated_tuple::stringify_at(size_t pos) const { std::string decorated_tuple::stringify(size_t pos) const {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
return decorated_->stringify_at(pos); return decorated_->stringify(mapping_[pos]);
} }
decorated_tuple::decorated_tuple(cow_ptr&& d, vector_type&& v) decorated_tuple::decorated_tuple(cow_ptr&& d, vector_type&& v)
...@@ -97,7 +87,7 @@ decorated_tuple::decorated_tuple(cow_ptr&& d, vector_type&& v) ...@@ -97,7 +87,7 @@ decorated_tuple::decorated_tuple(cow_ptr&& d, vector_type&& v)
// calculate type token // calculate type token
for (size_t i = 0; i < mapping_.size(); ++i) { for (size_t i = 0; i < mapping_.size(); ++i) {
type_token_ <<= 6; type_token_ <<= 6;
type_token_ |= decorated_->type_nr_at(mapping_[i]); type_token_ |= decorated_->type_nr(mapping_[i]);
} }
} }
......
...@@ -48,29 +48,22 @@ dynamic_message_data::~dynamic_message_data() { ...@@ -48,29 +48,22 @@ dynamic_message_data::~dynamic_message_data() {
// nop // nop
} }
const void* dynamic_message_data::at(size_t pos) const { const void* dynamic_message_data::get(size_t pos) const {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
return elements_[pos]->get(); return elements_[pos]->get();
} }
void dynamic_message_data::serialize_at(serializer& sink, size_t pos) const { void dynamic_message_data::save(size_t pos, serializer& sink) const {
elements_[pos]->save(sink); elements_[pos]->save(sink);
} }
void dynamic_message_data::serialize_at(deserializer& source, size_t pos) { void dynamic_message_data::load(size_t pos, deserializer& source) {
elements_[pos]->load(source); elements_[pos]->load(source);
} }
bool dynamic_message_data::compare_at(size_t pos, const element_rtti& rtti, void* dynamic_message_data::get_mutable(size_t pos) {
const void* x) const {
return match_element(pos, rtti.first, rtti.second)
? elements_[pos]->equals(x)
: false;
}
void* dynamic_message_data::mutable_at(size_t pos) {
CAF_ASSERT(pos < size()); CAF_ASSERT(pos < size());
return elements_[pos]->get(); return elements_[pos]->get_mutable();
} }
size_t dynamic_message_data::size() const { size_t dynamic_message_data::size() const {
...@@ -81,18 +74,11 @@ message_data::cow_ptr dynamic_message_data::copy() const { ...@@ -81,18 +74,11 @@ message_data::cow_ptr dynamic_message_data::copy() const {
return make_counted<dynamic_message_data>(*this); return make_counted<dynamic_message_data>(*this);
} }
bool dynamic_message_data::match_element(size_t pos, uint16_t nr, auto dynamic_message_data::type(size_t pos) const -> rtti_pair {
const std::type_info* ptr) const {
CAF_ASSERT(nr != 0 || ptr != nullptr);
auto rtti = type_at(pos);
return rtti.first == nr && (nr != 0 || *rtti.second == *ptr);
}
auto dynamic_message_data::type_at(size_t pos) const -> element_rtti {
return elements_[pos]->type(); return elements_[pos]->type();
} }
std::string dynamic_message_data::stringify_at(size_t pos) const { std::string dynamic_message_data::stringify(size_t pos) const {
return elements_[pos]->stringify(); return elements_[pos]->stringify();
} }
......
...@@ -37,7 +37,7 @@ merged_tuple::merged_tuple(data_type xs, mapping_type ys) ...@@ -37,7 +37,7 @@ merged_tuple::merged_tuple(data_type xs, mapping_type ys)
for (size_t i = 0; i < mapping_.size(); ++i) { for (size_t i = 0; i < mapping_.size(); ++i) {
type_token_ <<= 6; type_token_ <<= 6;
auto& p = mapping_[i]; auto& p = mapping_[i];
type_token_ |= data_[p.first]->type_nr_at(p.second); type_token_ |= data_[p.first]->type_nr(p.second);
} }
} }
...@@ -56,16 +56,16 @@ merged_tuple::cow_ptr merged_tuple::make(message x, message y) { ...@@ -56,16 +56,16 @@ merged_tuple::cow_ptr merged_tuple::make(message x, message y) {
std::move(mapping))}; std::move(mapping))};
} }
void* merged_tuple::mutable_at(size_t pos) { void* merged_tuple::get_mutable(size_t pos) {
CAF_ASSERT(pos < mapping_.size()); CAF_ASSERT(pos < mapping_.size());
auto& p = mapping_[pos]; auto& p = mapping_[pos];
return data_[p.first]->mutable_at(p.second); return data_[p.first]->get_mutable(p.second);
} }
void merged_tuple::serialize_at(deserializer& source, size_t pos) { void merged_tuple::load(size_t pos, deserializer& source) {
CAF_ASSERT(pos < mapping_.size()); CAF_ASSERT(pos < mapping_.size());
auto& p = mapping_[pos]; auto& p = mapping_[pos];
data_[p.first]->serialize_at(source, p.second); data_[p.first]->load(p.second, source);
} }
size_t merged_tuple::size() const { size_t merged_tuple::size() const {
...@@ -76,46 +76,32 @@ merged_tuple::cow_ptr merged_tuple::copy() const { ...@@ -76,46 +76,32 @@ merged_tuple::cow_ptr merged_tuple::copy() const {
return cow_ptr{make_counted<merged_tuple>(data_, mapping_)}; return cow_ptr{make_counted<merged_tuple>(data_, mapping_)};
} }
const void* merged_tuple::at(size_t pos) const { const void* merged_tuple::get(size_t pos) const {
CAF_ASSERT(pos < mapping_.size()); CAF_ASSERT(pos < mapping_.size());
auto& p = mapping_[pos]; auto& p = mapping_[pos];
return data_[p.first]->at(p.second); return data_[p.first]->get(p.second);
}
bool merged_tuple::compare_at(size_t pos, const element_rtti& rtti,
const void* x) const {
CAF_ASSERT(pos < mapping_.size());
auto& p = mapping_[pos];
return data_[p.first]->compare_at(p.second, rtti, x);
}
bool merged_tuple::match_element(size_t pos, uint16_t typenr,
const std::type_info* rtti) const {
CAF_ASSERT(pos < mapping_.size());
auto& p = mapping_[pos];
return data_[p.first]->match_element(p.second, typenr, rtti);
} }
uint32_t merged_tuple::type_token() const { uint32_t merged_tuple::type_token() const {
return type_token_; return type_token_;
} }
merged_tuple::element_rtti merged_tuple::type_at(size_t pos) const { merged_tuple::rtti_pair merged_tuple::type(size_t pos) const {
CAF_ASSERT(pos < mapping_.size()); CAF_ASSERT(pos < mapping_.size());
auto& p = mapping_[pos]; auto& p = mapping_[pos];
return data_[p.first]->type_at(p.second); return data_[p.first]->type(p.second);
} }
void merged_tuple::serialize_at(serializer& sink, size_t pos) const { void merged_tuple::save(size_t pos, serializer& sink) const {
CAF_ASSERT(pos < mapping_.size()); CAF_ASSERT(pos < mapping_.size());
auto& p = mapping_[pos]; auto& p = mapping_[pos];
data_[p.first]->serialize_at(sink, p.second); data_[p.first]->save(p.second, sink);
} }
std::string merged_tuple::stringify_at(size_t pos) const { std::string merged_tuple::stringify(size_t pos) const {
CAF_ASSERT(pos < mapping_.size()); CAF_ASSERT(pos < mapping_.size());
auto& p = mapping_[pos]; auto& p = mapping_[pos];
return data_[p.first]->stringify_at(p.second); return data_[p.first]->stringify(p.second);
} }
const merged_tuple::mapping_type& merged_tuple::mapping() const { const merged_tuple::mapping_type& merged_tuple::mapping() const {
......
...@@ -54,19 +54,19 @@ void message::swap(message& other) { ...@@ -54,19 +54,19 @@ void message::swap(message& other) {
vals_.swap(other.vals_); vals_.swap(other.vals_);
} }
void* message::mutable_at(size_t p) { void* message::get_mutable(size_t p) {
CAF_ASSERT(vals_); CAF_ASSERT(vals_);
return vals_->mutable_at(p); return vals_->get_mutable(p);
} }
const void* message::at(size_t p) const { const void* message::at(size_t p) const {
CAF_ASSERT(vals_); CAF_ASSERT(vals_);
return vals_->at(p); return vals_->get(p);
} }
bool message::match_element(size_t pos, uint16_t typenr, bool message::match_element(size_t pos, uint16_t typenr,
const std::type_info* rtti) const { const std::type_info* rtti) const {
return vals_->match_element(pos, typenr, rtti); return vals_->matches(pos, typenr, rtti);
} }
message& message::operator+=(const message& x) { message& message::operator+=(const message& x) {
...@@ -75,20 +75,12 @@ message& message::operator+=(const message& x) { ...@@ -75,20 +75,12 @@ message& message::operator+=(const message& x) {
return *this; return *this;
} }
bool message::equals(const message& other) const {
if (empty())
return other.empty();
return other.empty() ? false : vals_->equals(*other.vals());
}
message message::drop(size_t n) const { message message::drop(size_t n) const {
CAF_ASSERT(vals_); CAF_ASSERT(vals_);
if (n == 0) { if (n == 0)
return *this; return *this;
} if (n >= size())
if (n >= size()) {
return message{}; return message{};
}
std::vector<size_t> mapping (size() - n); std::vector<size_t> mapping (size() - n);
size_t i = n; size_t i = n;
std::generate(mapping.begin(), mapping.end(), [&] { return i++; }); std::generate(mapping.begin(), mapping.end(), [&] { return i++; });
...@@ -382,7 +374,7 @@ void serialize(serializer& sink, const message& msg, const unsigned int) { ...@@ -382,7 +374,7 @@ void serialize(serializer& sink, const message& msg, const unsigned int) {
auto& types = sink.context()->system().types(); auto& types = sink.context()->system().types();
auto n = msg.size(); auto n = msg.size();
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
auto rtti = msg.cvals()->type_at(i); auto rtti = msg.cvals()->type(i);
auto ptr = types.portable_name(rtti); auto ptr = types.portable_name(rtti);
if (! ptr) { if (! ptr) {
std::cerr << "[ERROR]: cannot serialize message because a type was " std::cerr << "[ERROR]: cannot serialize message because a type was "
...@@ -396,7 +388,7 @@ void serialize(serializer& sink, const message& msg, const unsigned int) { ...@@ -396,7 +388,7 @@ void serialize(serializer& sink, const message& msg, const unsigned int) {
} }
sink.begin_object(zero, tname); sink.begin_object(zero, tname);
for (size_t i = 0; i < n; ++i) for (size_t i = 0; i < n; ++i)
msg.cvals()->serialize_at(sink, i); msg.cvals()->save(i, sink);
sink.end_object(); sink.end_object();
} }
...@@ -446,10 +438,10 @@ std::string to_string(const message& msg) { ...@@ -446,10 +438,10 @@ std::string to_string(const message& msg) {
if (msg.empty()) if (msg.empty())
return "<empty-message>"; return "<empty-message>";
std::string str = "("; std::string str = "(";
str += msg.cvals()->stringify_at(0); str += msg.cvals()->stringify(0);
for (size_t i = 1; i < msg.size(); ++i) { for (size_t i = 1; i < msg.size(); ++i) {
str += ", "; str += ", ";
str += msg.cvals()->stringify_at(i); str += msg.cvals()->stringify(i);
} }
str += ")"; str += ")";
return str; return str;
......
...@@ -28,22 +28,6 @@ message_data::~message_data() { ...@@ -28,22 +28,6 @@ message_data::~message_data() {
// nop // nop
} }
bool message_data::equals(const message_data& other) const {
if (this == &other)
return true;
auto n = size();
if (n != other.size())
return false;
for (size_t i = 0; i < n; ++i)
if (! compare_at(i, other.type_at(i), other.at(i)))
return false;
return true;
}
uint16_t message_data::type_nr_at(size_t pos) const {
return type_at(pos).first;
}
message_data* message_data::cow_ptr::get_unshared() { message_data* message_data::cow_ptr::get_unshared() {
auto p = ptr_.get(); auto p = ptr_.get();
if (! p->unique()) { if (! p->unique()) {
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* 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 "caf/type_erased_tuple.hpp"
#include "caf/config.hpp"
namespace caf {
type_erased_tuple::~type_erased_tuple() {
// nop
}
bool type_erased_tuple::matches(size_t pos, uint16_t nr,
const std::type_info* ptr) const {
CAF_ASSERT(pos < size());
auto tp = type(pos);
if (tp.first != nr)
return false;
if (nr == 0)
return ptr ? *tp.second == *ptr : false;
return true;
}
} // namespace caf
...@@ -25,4 +25,13 @@ type_erased_value::~type_erased_value() { ...@@ -25,4 +25,13 @@ type_erased_value::~type_erased_value() {
// nop // nop
} }
bool type_erased_value::matches(uint16_t nr, const std::type_info* ptr) const {
auto tp = type();
if (tp.first != nr)
return false;
if (nr == 0)
return ptr ? *tp.second == *ptr : false;
return true;
}
} // namespace caf } // namespace caf
...@@ -31,34 +31,34 @@ using namespace caf; ...@@ -31,34 +31,34 @@ using namespace caf;
using std::string; using std::string;
// exclude this test; advanced match cases are currently not supported on MSVC namespace {
#ifndef CAF_WINDOWS
CAF_TEST(simple_ints) { bool msg_equals_rec(const message&, size_t) {
auto msg = make_message(1, 2, 3); return true;
auto one = on(1) >> [] { }; }
auto two = on(2) >> [] { };
auto three = on(3) >> [] { }; template <class T, class... Ts>
auto skip_two = [](int i) -> optional<skip_message_t> { bool msg_equals_rec(const message& msg, size_t pos, const T& x, const Ts&... xs) {
if (i == 2) return msg.get_as<T>(pos) == x && msg_equals_rec(msg, pos + 1, xs...);
return skip_message();
return none;
};
CAF_CHECK_EQUAL(msg.extract(one), make_message(2, 3));
CAF_CHECK_EQUAL(msg.extract(two), make_message(1, 3));
CAF_CHECK_EQUAL(msg.extract(three), make_message(1, 2));
CAF_CHECK_EQUAL(msg.extract(skip_two), make_message(2));
} }
#endif // CAF_WINDOWS
template <class... Ts>
bool msg_equals(const message& msg, const Ts&... xs) {
return msg.match_elements<Ts...>() && msg_equals_rec(msg, 0, xs...);
}
} // namespace <anonymous>
CAF_TEST(type_sequences) { CAF_TEST(type_sequences) {
auto _64 = uint64_t{64}; auto _64 = uint64_t{64};
auto msg = make_message(1.0, 2.f, "str", 42, _64); std::string str = "str";
auto msg = make_message(1.0, 2.f, str, 42, _64);
auto df = [](double, float) { }; auto df = [](double, float) { };
auto fs = [](float, const string&) { }; auto fs = [](float, const string&) { };
auto iu = [](int, uint64_t) { }; auto iu = [](int, uint64_t) { };
CAF_CHECK_EQUAL(msg.extract(df), make_message("str", 42, _64)); CAF_CHECK(msg_equals(msg.extract(df), str, 42, _64));
CAF_CHECK_EQUAL(msg.extract(fs), make_message(1.0, 42, _64)); CAF_CHECK(msg_equals(msg.extract(fs), 1.0, 42, _64));
CAF_CHECK_EQUAL(msg.extract(iu), make_message(1.0, 2.f, "str")); CAF_CHECK(msg_equals(msg.extract(iu), 1.0, 2.f, str));
} }
CAF_TEST(cli_args) { CAF_TEST(cli_args) {
...@@ -73,7 +73,7 @@ CAF_TEST(cli_args) { ...@@ -73,7 +73,7 @@ CAF_TEST(cli_args) {
{"verbosity,v", "1-5", verbosity} {"verbosity,v", "1-5", verbosity}
}); });
CAF_CHECK_EQUAL(res.remainder.size(), 0u); CAF_CHECK_EQUAL(res.remainder.size(), 0u);
CAF_CHECK(res.remainder == message{}); CAF_CHECK(res.remainder.empty());
CAF_CHECK_EQUAL(res.opts.count("no-colors"), 1u); CAF_CHECK_EQUAL(res.opts.count("no-colors"), 1u);
CAF_CHECK_EQUAL(res.opts.count("verbosity"), 1u); CAF_CHECK_EQUAL(res.opts.count("verbosity"), 1u);
CAF_CHECK_EQUAL(res.opts.count("out-file"), 1u); CAF_CHECK_EQUAL(res.opts.count("out-file"), 1u);
......
...@@ -63,14 +63,14 @@ CAF_TEST(drop) { ...@@ -63,14 +63,14 @@ CAF_TEST(drop) {
message{} message{}
}; };
for (size_t i = 0; i < messages.size(); ++i) { for (size_t i = 0; i < messages.size(); ++i) {
CAF_CHECK(m1.drop(i) == messages[i]); CAF_CHECK(to_string(m1.drop(i)) == to_string(messages[i]));
} }
} }
CAF_TEST(slice) { CAF_TEST(slice) {
auto m1 = make_message(1, 2, 3, 4, 5); auto m1 = make_message(1, 2, 3, 4, 5);
auto m2 = m1.slice(2, 2); auto m2 = m1.slice(2, 2);
CAF_CHECK(m2 == make_message(3, 4)); CAF_CHECK(to_string(m2) == to_string(make_message(3, 4)));
} }
CAF_TEST(extract1) { CAF_TEST(extract1) {
...@@ -85,12 +85,13 @@ CAF_TEST(extract1) { ...@@ -85,12 +85,13 @@ CAF_TEST(extract1) {
[](int, int) { }, [](int, int) { },
[](float, float) { } [](float, float) { }
}; };
CAF_CHECK(m2.extract(f) == m1); auto m1s = to_string(m1);
CAF_CHECK(m3.extract(f) == m1); CAF_CHECK(to_string(m2.extract(f)) == m1s);
CAF_CHECK(m4.extract(f) == m1); CAF_CHECK(to_string(m3.extract(f)) == m1s);
CAF_CHECK(m5.extract(f) == m1); CAF_CHECK(to_string(m4.extract(f)) == m1s);
CAF_CHECK(m6.extract(f) == m1); CAF_CHECK(to_string(m5.extract(f)) == m1s);
CAF_CHECK(m7.extract(f) == m1); CAF_CHECK(to_string(m6.extract(f)) == m1s);
CAF_CHECK(to_string(m7.extract(f)) == m1s);
} }
CAF_TEST(extract2) { CAF_TEST(extract2) {
...@@ -102,7 +103,7 @@ CAF_TEST(extract2) { ...@@ -102,7 +103,7 @@ CAF_TEST(extract2) {
[](double, double) { } [](double, double) { }
}); });
// check for false positives through collapsing // check for false positives through collapsing
CAF_CHECK(m3 == make_message(1.0, 4.0)); CAF_CHECK(to_string(m3) == to_string(make_message(1.0, 4.0)));
} }
CAF_TEST(extract_opts) { CAF_TEST(extract_opts) {
...@@ -137,7 +138,8 @@ CAF_TEST(extract_opts) { ...@@ -137,7 +138,8 @@ CAF_TEST(extract_opts) {
CAF_CHECK(foo == 42); CAF_CHECK(foo == 42);
CAF_CHECK(bar == 0); CAF_CHECK(bar == 0);
CAF_CHECK(! r.error.empty()); // -b is an unknown option CAF_CHECK(! r.error.empty()); // -b is an unknown option
CAF_CHECK(! r.remainder.empty() && r.remainder == make_message("-b", "1337")); CAF_CHECK(! r.remainder.empty()
&& to_string(r.remainder) == to_string(make_message("-b", "1337")));
r = r.remainder.extract_opts({ r = r.remainder.extract_opts({
{"bar,b", "bar desc", bar} {"bar,b", "bar desc", bar}
}); });
...@@ -155,11 +157,11 @@ CAF_TEST(concat) { ...@@ -155,11 +157,11 @@ CAF_TEST(concat) {
auto m1 = make_message(get_atom::value); auto m1 = make_message(get_atom::value);
auto m2 = make_message(uint32_t{1}); auto m2 = make_message(uint32_t{1});
auto m3 = message::concat(m1, m2); auto m3 = message::concat(m1, m2);
CAF_CHECK(m3 == m1 + m2); CAF_CHECK(to_string(m3) == to_string(m1 + m2));
CAF_CHECK(m3 == make_message(get_atom::value, uint32_t{1})); CAF_CHECK(to_string(m3) == "('get', 1)");
auto m4 = make_message(get_atom::value, uint32_t{1}, auto m4 = make_message(get_atom::value, uint32_t{1},
get_atom::value, uint32_t{1}); get_atom::value, uint32_t{1});
CAF_CHECK(message::concat(m3, message{}, m1, m2) == m4); CAF_CHECK(to_string(message::concat(m3, message{}, m1, m2)) == to_string(m4));
} }
namespace { namespace {
...@@ -168,13 +170,6 @@ struct s1 { ...@@ -168,13 +170,6 @@ struct s1 {
int value[3] = {10, 20, 30}; int value[3] = {10, 20, 30};
}; };
bool operator==(const s1& lhs, const s1& rhs) {
for (size_t i = 0; i < 3; ++i)
if (lhs.value[i] != rhs.value[i])
return false;
return true;
}
template <class Processor> template <class Processor>
void serialize(Processor& proc, s1& x, const unsigned int) { void serialize(Processor& proc, s1& x, const unsigned int) {
proc & x.value; proc & x.value;
...@@ -188,14 +183,6 @@ struct s2 { ...@@ -188,14 +183,6 @@ struct s2 {
int value[4][2] = {{1, 10}, {2, 20}, {3, 30}, {4, 40}}; int value[4][2] = {{1, 10}, {2, 20}, {3, 30}, {4, 40}};
}; };
bool operator==(const s2& lhs, const s2& rhs) {
for (size_t i = 0; i < 4; ++i)
for (size_t j = 0; j < 2; ++j)
if (lhs.value[i][j] != rhs.value[i][j])
return false;
return true;
}
template <class Processor> template <class Processor>
void serialize(Processor& proc, s2& x, const unsigned int) { void serialize(Processor& proc, s2& x, const unsigned int) {
proc & x.value; proc & x.value;
...@@ -212,10 +199,6 @@ struct s3 { ...@@ -212,10 +199,6 @@ struct s3 {
} }
}; };
bool operator==(const s3& lhs, const s3& rhs) {
return lhs.value == rhs.value;
}
template <class Processor> template <class Processor>
void serialize(Processor& proc, s3& x, const unsigned int) { void serialize(Processor& proc, s3& x, const unsigned int) {
proc & x.value; proc & x.value;
...@@ -233,10 +216,9 @@ std::string msg_as_string(Ts&&... xs) { ...@@ -233,10 +216,9 @@ std::string msg_as_string(Ts&&... xs) {
} // namespace <anonymous> } // namespace <anonymous>
CAF_TEST(compare_custom_types) { CAF_TEST(compare_custom_types) {
CAF_CHECK(make_message(s1{}) == make_message(s1{}));
s2 tmp; s2 tmp;
tmp.value[0][1] = 100; tmp.value[0][1] = 100;
CAF_CHECK(make_message(s2{}) != make_message(tmp)); CAF_CHECK(to_string(make_message(s2{})) != to_string(make_message(tmp)));
} }
CAF_TEST(empty_to_string) { CAF_TEST(empty_to_string) {
...@@ -280,13 +262,10 @@ CAF_TEST(tuples_to_string) { ...@@ -280,13 +262,10 @@ CAF_TEST(tuples_to_string) {
} }
CAF_TEST(arrays_to_string) { CAF_TEST(arrays_to_string) {
CAF_CHECK(make_message(s1{}) == make_message(s1{}));
CAF_CHECK(msg_as_string(s1{}) == "((10, 20, 30))"); CAF_CHECK(msg_as_string(s1{}) == "((10, 20, 30))");
auto msg2 = make_message(s2{}); auto msg2 = make_message(s2{});
s2 tmp; s2 tmp;
tmp.value[0][1] = 100; tmp.value[0][1] = 100;
CAF_CHECK(! (msg2 == make_message(tmp)));
CAF_CHECK(to_string(msg2) == "(((1, 10), (2, 20), (3, 30), (4, 40)))"); CAF_CHECK(to_string(msg2) == "(((1, 10), (2, 20), (3, 30), (4, 40)))");
CAF_CHECK(make_message(s3{}) == make_message(s3{}));
CAF_CHECK(msg_as_string(s3{}) == "((1, 2, 3, 4))"); CAF_CHECK(msg_as_string(s3{}) == "((1, 2, 3, 4))");
} }
...@@ -108,12 +108,6 @@ void serialize(Processor& proc, test_array& x, const unsigned int) { ...@@ -108,12 +108,6 @@ void serialize(Processor& proc, test_array& x, const unsigned int) {
proc & x.value2; proc & x.value2;
} }
bool operator==(const test_array& lhs, const test_array& rhs) {
return std::equal(lhs.value, lhs.value + 4, rhs.value)
&& std::equal(lhs.value2[0], lhs.value2[0] + 4, rhs.value2[0])
&& std::equal(lhs.value2[1], lhs.value2[1] + 4, rhs.value2[1]);
}
struct test_empty_non_pod { struct test_empty_non_pod {
test_empty_non_pod() = default; test_empty_non_pod() = default;
test_empty_non_pod(const test_empty_non_pod&) = default; test_empty_non_pod(const test_empty_non_pod&) = default;
...@@ -306,7 +300,7 @@ CAF_TEST(messages) { ...@@ -306,7 +300,7 @@ CAF_TEST(messages) {
auto buf = serialize(msg); auto buf = serialize(msg);
message x; message x;
deserialize(buf, x); deserialize(buf, x);
CAF_CHECK(msg == x); CAF_CHECK(to_string(msg) == to_string(x));
CAF_CHECK(is_message(x).equal(i32, te, str, rs)); CAF_CHECK(is_message(x).equal(i32, te, str, rs));
} }
...@@ -317,7 +311,8 @@ CAF_TEST(multiple_messages) { ...@@ -317,7 +311,8 @@ CAF_TEST(multiple_messages) {
message m1; message m1;
message m2; message m2;
deserialize(buf, t, m1, m2); deserialize(buf, t, m1, m2);
CAF_CHECK(tie(t, m1, m2) == tie(te, m, msg)); CAF_CHECK_EQUAL(std::make_tuple(t, to_string(m1), to_string(m2)),
std::make_tuple(te, to_string(m), to_string(msg)));
CAF_CHECK(is_message(m1).equal(rs, te)); CAF_CHECK(is_message(m1).equal(rs, te));
CAF_CHECK(is_message(m2).equal(i32, te, str, rs)); CAF_CHECK(is_message(m2).equal(i32, te, str, rs));
} }
......
...@@ -31,7 +31,7 @@ CAF_TEST(simple_reply_response) { ...@@ -31,7 +31,7 @@ CAF_TEST(simple_reply_response) {
auto s = system.spawn([](event_based_actor* self) -> behavior { auto s = system.spawn([](event_based_actor* self) -> behavior {
return ( return (
others >> [=](const message& msg) -> message { others >> [=](const message& msg) -> message {
CAF_CHECK(msg == make_message(ok_atom::value)); CAF_CHECK(to_string(msg) == "('ok')");
self->quit(); self->quit();
return msg; return msg;
} }
...@@ -41,7 +41,7 @@ CAF_TEST(simple_reply_response) { ...@@ -41,7 +41,7 @@ CAF_TEST(simple_reply_response) {
self->send(s, ok_atom::value); self->send(s, ok_atom::value);
self->receive( self->receive(
others >> [&](const message& msg) { others >> [&](const message& msg) {
CAF_CHECK(msg == make_message(ok_atom::value)); CAF_CHECK(to_string(msg) == "('ok')");
} }
); );
} }
...@@ -89,10 +89,6 @@ void serialize(Processor& proc, my_request& x, const unsigned int) { ...@@ -89,10 +89,6 @@ void serialize(Processor& proc, my_request& x, const unsigned int) {
using server_type = typed_actor<replies_to<my_request>::with<bool>>; using server_type = typed_actor<replies_to<my_request>::with<bool>>;
bool operator==(const my_request& lhs, const my_request& rhs) {
return lhs.a == rhs.a && lhs.b == rhs.b;
}
server_type::behavior_type typed_server1() { server_type::behavior_type typed_server1() {
return { return {
[](const my_request& req) { [](const my_request& req) {
......
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