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
src/sync_request_bouncer.cpp
src/try_match.cpp
src/type_erased_value.cpp
src/type_erased_tuple.cpp
src/uniform_type_info_map.cpp)
add_custom_target(libcaf_core)
......
......@@ -55,7 +55,7 @@ public:
// fill a pseudo tuple with values and invoke f
detail::pseudo_tuple<Ts...> buf;
// 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)
buf[i] = const_cast<void*>(msg.at(i));
return detail::apply_args(f, detail::get_indices(buf), buf);
......
......@@ -122,11 +122,9 @@ public:
template <class T>
actor_system_config& add_message_type(std::string name) {
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),
"T must provide default and copy constructors "
"as well as operator==");
"T must provide default and copy constructors");
static_assert(detail::is_serializable<T>::value, "T must be serializable");
type_names_by_rtti_.emplace(std::type_index(typeid(T)), name);
value_factories_by_name_.emplace(std::move(name), &make_type_erased<T>);
......
......@@ -38,28 +38,23 @@ public:
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;
cow_ptr copy() const override;
const void* at(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;
const void* get(size_t pos) 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);
......
......@@ -47,28 +47,23 @@ public:
// creates a typed subtuple from `d` with mapping `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;
cow_ptr copy() const override;
const void* at(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;
const void* get(size_t pos) 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 {
return decorated_;
......
......@@ -41,27 +41,21 @@ public:
~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,
const void* x) const override;
void* mutable_at(size_t pos) override;
void* get_mutable(size_t pos) override;
size_t size() const override;
cow_ptr copy() const override;
bool match_element(size_t pos, uint16_t nr,
const std::type_info* ptr) const override;
element_rtti type_at(size_t pos) const override;
rtti_pair type(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;
......
......@@ -43,29 +43,23 @@ public:
// creates a typed subtuple from `d` with mapping `v`
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;
cow_ptr copy() const override;
const void* at(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;
const void* get(size_t pos) 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;
......
......@@ -29,63 +29,21 @@
#include "caf/config.hpp"
#include "caf/ref_counted.hpp"
#include "caf/intrusive_ptr.hpp"
#include "caf/type_erased_tuple.hpp"
#include "caf/detail/type_list.hpp"
namespace caf {
namespace detail {
class message_data : public ref_counted {
class message_data : public ref_counted, public type_erased_tuple {
public:
message_data() = default;
message_data(const message_data&) = default;
~message_data();
using element_rtti = std::pair<uint16_t, const std::type_info*>;
/****************************************************************************
* 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 *
****************************************************************************/
// nested types
class cow_ptr {
public:
......@@ -104,9 +62,7 @@ public:
// nop
}
/**************************************************************************
* modifiers *
**************************************************************************/
// modifiers
inline void swap(cow_ptr& other) {
ptr_.swap(other.ptr_);
......@@ -131,9 +87,8 @@ public:
inline message_data& operator*() {
return *get_unshared();
}
/**************************************************************************
* observers *
**************************************************************************/
// observers
inline const message_data* operator->() const {
return ptr_.get();
......
......@@ -37,7 +37,7 @@ struct pseudo_tuple {
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]; }
......@@ -55,7 +55,7 @@ get(const detail::pseudo_tuple<Ts...>& tv) {
template <size_t N, class... Ts>
typename detail::type_at<N, Ts...>::type& get(detail::pseudo_tuple<Ts...>& tv) {
static_assert(N < sizeof...(Ts), "N >= tv.size()");
auto vp = tv.mutable_at(N);
auto vp = tv.get_mutable(N);
CAF_ASSERT(vp != nullptr);
return *reinterpret_cast<typename detail::type_at<N, Ts...>::type*>(vp);
}
......
......@@ -104,14 +104,14 @@ struct tup_ptr_access<Pos, Max, false> {
template <class T, uint16_t N = detail::type_nr<T>::value>
struct tuple_vals_type_helper {
static typename message_data::element_rtti get() {
static typename message_data::rtti_pair get() {
return {N, nullptr};
}
};
template <class T>
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)};
}
};
......@@ -123,7 +123,7 @@ public:
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...>;
......@@ -152,52 +152,33 @@ public:
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());
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());
auto& rtti_at_pos = types_[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);
return const_cast<void*>(get(pos));
}
void* mutable_at(size_t pos) override {
CAF_ASSERT(pos < size());
return const_cast<void*>(at(pos));
}
std::string stringify_at(size_t pos) const override {
std::string stringify(size_t pos) const override {
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);
}
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 {
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];
}
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,
// but this cast is safe since the values are not actually changed
auto& nc_data = const_cast<data_type&>(data_);
......@@ -206,7 +187,7 @@ public:
private:
data_type data_;
std::array<element_rtti, sizeof...(Ts)> types_;
std::array<rtti_pair, sizeof...(Ts)> types_;
};
} // namespace detail
......
......@@ -150,8 +150,8 @@ template <class A, class B, template <class, class> class Predicate>
struct static_asserter {
static void verify_match() {
static constexpr int x = Predicate<A, B>::value;
using type_at_x = typename tl_at<B, (x < 0 ? 0 : x)>::type;
static_error_printer<x, x, type_at_x> dummy;
using type_x = typename tl_at<B, (x < 0 ? 0 : x)>::type;
static_error_printer<x, x, type_x> dummy;
static_cast<void>(dummy);
}
};
......
......@@ -91,8 +91,6 @@ public:
using mailbox_type = detail::single_reader_queue<mailbox_element,
detail::disposer>;
//static constexpr auto memory_cache_flag = detail::needs_embedding;
~local_actor();
/****************************************************************************
......@@ -677,6 +675,9 @@ protected:
// used only in thread-mapped actors
void await_data();
// used by both event-based and blocking actors
mailbox_type mailbox_;
// identifies the execution unit this actor is currently executed by
execution_unit* context_;
......@@ -702,9 +703,6 @@ protected:
// used by both event-based and blocking actors
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()
std::function<behavior (local_actor*)> initial_behavior_fac_;
......
......@@ -205,7 +205,7 @@ public:
// update pointers in our intermediate tuple
for (size_t i = 0; i < msg.size(); ++i) {
// 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));
}
}
......
......@@ -94,14 +94,11 @@ public:
}
/// 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`.
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.
inline bool empty() const {
return size() == 0;
......@@ -118,7 +115,7 @@ public:
template <class T>
T& get_as_mutable(size_t p) {
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)`.
......@@ -355,16 +352,6 @@ struct message::cli_res {
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
inline message operator+(const message& lhs, const message& 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 @@
#ifndef CAF_TYPE_ERASED_VALUE_HPP
#define CAF_TYPE_ERASED_VALUE_HPP
#include <cstdint>
#include <typeinfo>
#include "caf/deep_to_string.hpp"
......@@ -30,25 +31,59 @@
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 {
public:
using rtti_pair = std::pair<uint16_t, const std::type_info*>;
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 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>
......@@ -64,7 +99,7 @@ struct type_erased_value_impl : public type_erased_value {
// nop
}
void* get() override {
void* get_mutable() override {
return &x;
}
......@@ -72,10 +107,6 @@ struct type_erased_value_impl : public type_erased_value {
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 {
detail::try_serialize(sink, const_cast<T*>(&x));
}
......@@ -88,11 +119,11 @@ struct type_erased_value_impl : public type_erased_value {
return deep_to_string(x);
}
type_erased_value* copy() const override {
return new type_erased_value_impl(x);
type_erased_value_ptr copy() const override {
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;
return {nr, &typeid(T)};
}
......@@ -111,7 +142,7 @@ struct type_erased_value_impl<T[N]> : public type_erased_value {
// nop
}
void* get() override {
void* get_mutable() override {
T* tmp = xs;
return reinterpret_cast<void*>(tmp);
}
......@@ -121,14 +152,6 @@ struct type_erased_value_impl<T[N]> : public type_erased_value {
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 {
array_serialize(sink, const_cast<array_type&>(xs));
}
......@@ -141,11 +164,11 @@ struct type_erased_value_impl<T[N]> : public type_erased_value {
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);
}
std::pair<uint16_t, const std::type_info*> type() const override {
rtti_pair type() const override {
auto nr = detail::type_nr<T>::value;
return {nr, &typeid(T)};
}
......@@ -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>
type_erased_value_ptr make_type_erased(Ts&&... xs) {
type_erased_value_ptr result;
......
......@@ -198,8 +198,6 @@ void actor_registry::start() {
if (key == "*")
return;
auto& vp = self->state.data[key];
if (vp.first == msg)
return;
vp.first = std::move(msg);
for (auto& subscriber : vp.second)
if (subscriber != self->current_sender())
......
......@@ -31,19 +31,18 @@ auto concatenated_tuple::make(std::initializer_list<cow_ptr> xs) -> cow_ptr {
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());
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());
auto selected = select(pos);
selected.first->serialize_at(source, selected.second);
selected.first->load(selected.second, source);
}
size_t concatenated_tuple::size() const {
return size_;
}
......@@ -52,45 +51,32 @@ message_data::cow_ptr concatenated_tuple::copy() const {
return cow_ptr(new concatenated_tuple(*this), false);
}
const void* concatenated_tuple::at(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 {
const void* concatenated_tuple::get(size_t pos) const {
CAF_ASSERT(pos < size());
auto selected = select(pos);
return selected.first->compare_at(selected.second, rtti, x);
}
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);
return selected.first->get(selected.second);
}
uint32_t concatenated_tuple::type_token() const {
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());
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());
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());
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 {
......@@ -120,7 +106,7 @@ concatenated_tuple::concatenated_tuple(std::initializer_list<cow_ptr> xs) {
type_token_ = make_type_token();
for (const auto& m : data_)
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) {
return tmp + val->size();
};
......
......@@ -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));
}
void* decorated_tuple::mutable_at(size_t pos) {
void* decorated_tuple::get_mutable(size_t pos) {
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());
return decorated_->serialize_at(source, mapping_[pos]);
return decorated_->load(mapping_[pos], source);
}
size_t decorated_tuple::size() const {
......@@ -54,37 +54,27 @@ message_data::cow_ptr decorated_tuple::copy() const {
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());
return decorated_->at(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);
return decorated_->get(mapping_[pos]);
}
uint32_t decorated_tuple::type_token() const {
return type_token_;
}
message_data::element_rtti decorated_tuple::type_at(size_t pos) const {
return decorated_->type_at(mapping_[pos]);
message_data::rtti_pair decorated_tuple::type(size_t pos) const {
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());
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());
return decorated_->stringify_at(pos);
return decorated_->stringify(mapping_[pos]);
}
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
for (size_t i = 0; i < mapping_.size(); ++i) {
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() {
// 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());
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);
}
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);
}
bool dynamic_message_data::compare_at(size_t pos, const element_rtti& rtti,
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) {
void* dynamic_message_data::get_mutable(size_t pos) {
CAF_ASSERT(pos < size());
return elements_[pos]->get();
return elements_[pos]->get_mutable();
}
size_t dynamic_message_data::size() const {
......@@ -81,18 +74,11 @@ message_data::cow_ptr dynamic_message_data::copy() const {
return make_counted<dynamic_message_data>(*this);
}
bool dynamic_message_data::match_element(size_t pos, uint16_t nr,
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 {
auto dynamic_message_data::type(size_t pos) const -> rtti_pair {
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();
}
......
......@@ -37,7 +37,7 @@ merged_tuple::merged_tuple(data_type xs, mapping_type ys)
for (size_t i = 0; i < mapping_.size(); ++i) {
type_token_ <<= 6;
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) {
std::move(mapping))};
}
void* merged_tuple::mutable_at(size_t pos) {
void* merged_tuple::get_mutable(size_t pos) {
CAF_ASSERT(pos < mapping_.size());
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());
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 {
......@@ -76,46 +76,32 @@ merged_tuple::cow_ptr merged_tuple::copy() const {
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());
auto& p = mapping_[pos];
return data_[p.first]->at(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);
return data_[p.first]->get(p.second);
}
uint32_t merged_tuple::type_token() const {
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());
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());
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());
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 {
......
......@@ -54,19 +54,19 @@ void message::swap(message& other) {
vals_.swap(other.vals_);
}
void* message::mutable_at(size_t p) {
void* message::get_mutable(size_t p) {
CAF_ASSERT(vals_);
return vals_->mutable_at(p);
return vals_->get_mutable(p);
}
const void* message::at(size_t p) const {
CAF_ASSERT(vals_);
return vals_->at(p);
return vals_->get(p);
}
bool message::match_element(size_t pos, uint16_t typenr,
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) {
......@@ -75,20 +75,12 @@ message& message::operator+=(const message& x) {
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 {
CAF_ASSERT(vals_);
if (n == 0) {
if (n == 0)
return *this;
}
if (n >= size()) {
if (n >= size())
return message{};
}
std::vector<size_t> mapping (size() - n);
size_t i = n;
std::generate(mapping.begin(), mapping.end(), [&] { return i++; });
......@@ -382,7 +374,7 @@ void serialize(serializer& sink, const message& msg, const unsigned int) {
auto& types = sink.context()->system().types();
auto n = msg.size();
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);
if (! ptr) {
std::cerr << "[ERROR]: cannot serialize message because a type was "
......@@ -396,7 +388,7 @@ void serialize(serializer& sink, const message& msg, const unsigned int) {
}
sink.begin_object(zero, tname);
for (size_t i = 0; i < n; ++i)
msg.cvals()->serialize_at(sink, i);
msg.cvals()->save(i, sink);
sink.end_object();
}
......@@ -446,10 +438,10 @@ std::string to_string(const message& msg) {
if (msg.empty())
return "<empty-message>";
std::string str = "(";
str += msg.cvals()->stringify_at(0);
str += msg.cvals()->stringify(0);
for (size_t i = 1; i < msg.size(); ++i) {
str += ", ";
str += msg.cvals()->stringify_at(i);
str += msg.cvals()->stringify(i);
}
str += ")";
return str;
......
......@@ -28,22 +28,6 @@ message_data::~message_data() {
// 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() {
auto p = ptr_.get();
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() {
// 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
......@@ -31,34 +31,34 @@ using namespace caf;
using std::string;
// exclude this test; advanced match cases are currently not supported on MSVC
#ifndef CAF_WINDOWS
CAF_TEST(simple_ints) {
auto msg = make_message(1, 2, 3);
auto one = on(1) >> [] { };
auto two = on(2) >> [] { };
auto three = on(3) >> [] { };
auto skip_two = [](int i) -> optional<skip_message_t> {
if (i == 2)
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));
namespace {
bool msg_equals_rec(const message&, size_t) {
return true;
}
template <class T, class... Ts>
bool msg_equals_rec(const message& msg, size_t pos, const T& x, const Ts&... xs) {
return msg.get_as<T>(pos) == x && msg_equals_rec(msg, pos + 1, xs...);
}
#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) {
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 fs = [](float, const string&) { };
auto iu = [](int, uint64_t) { };
CAF_CHECK_EQUAL(msg.extract(df), make_message("str", 42, _64));
CAF_CHECK_EQUAL(msg.extract(fs), make_message(1.0, 42, _64));
CAF_CHECK_EQUAL(msg.extract(iu), make_message(1.0, 2.f, "str"));
CAF_CHECK(msg_equals(msg.extract(df), str, 42, _64));
CAF_CHECK(msg_equals(msg.extract(fs), 1.0, 42, _64));
CAF_CHECK(msg_equals(msg.extract(iu), 1.0, 2.f, str));
}
CAF_TEST(cli_args) {
......@@ -73,7 +73,7 @@ CAF_TEST(cli_args) {
{"verbosity,v", "1-5", verbosity}
});
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("verbosity"), 1u);
CAF_CHECK_EQUAL(res.opts.count("out-file"), 1u);
......
......@@ -63,14 +63,14 @@ CAF_TEST(drop) {
message{}
};
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) {
auto m1 = make_message(1, 2, 3, 4, 5);
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) {
......@@ -85,12 +85,13 @@ CAF_TEST(extract1) {
[](int, int) { },
[](float, float) { }
};
CAF_CHECK(m2.extract(f) == m1);
CAF_CHECK(m3.extract(f) == m1);
CAF_CHECK(m4.extract(f) == m1);
CAF_CHECK(m5.extract(f) == m1);
CAF_CHECK(m6.extract(f) == m1);
CAF_CHECK(m7.extract(f) == m1);
auto m1s = to_string(m1);
CAF_CHECK(to_string(m2.extract(f)) == m1s);
CAF_CHECK(to_string(m3.extract(f)) == m1s);
CAF_CHECK(to_string(m4.extract(f)) == m1s);
CAF_CHECK(to_string(m5.extract(f)) == m1s);
CAF_CHECK(to_string(m6.extract(f)) == m1s);
CAF_CHECK(to_string(m7.extract(f)) == m1s);
}
CAF_TEST(extract2) {
......@@ -102,7 +103,7 @@ CAF_TEST(extract2) {
[](double, double) { }
});
// 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) {
......@@ -137,7 +138,8 @@ CAF_TEST(extract_opts) {
CAF_CHECK(foo == 42);
CAF_CHECK(bar == 0);
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({
{"bar,b", "bar desc", bar}
});
......@@ -155,11 +157,11 @@ CAF_TEST(concat) {
auto m1 = make_message(get_atom::value);
auto m2 = make_message(uint32_t{1});
auto m3 = message::concat(m1, m2);
CAF_CHECK(m3 == m1 + m2);
CAF_CHECK(m3 == make_message(get_atom::value, uint32_t{1}));
CAF_CHECK(to_string(m3) == to_string(m1 + m2));
CAF_CHECK(to_string(m3) == "('get', 1)");
auto m4 = make_message(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 {
......@@ -168,13 +170,6 @@ struct s1 {
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>
void serialize(Processor& proc, s1& x, const unsigned int) {
proc & x.value;
......@@ -188,14 +183,6 @@ struct s2 {
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>
void serialize(Processor& proc, s2& x, const unsigned int) {
proc & x.value;
......@@ -212,10 +199,6 @@ struct s3 {
}
};
bool operator==(const s3& lhs, const s3& rhs) {
return lhs.value == rhs.value;
}
template <class Processor>
void serialize(Processor& proc, s3& x, const unsigned int) {
proc & x.value;
......@@ -233,10 +216,9 @@ std::string msg_as_string(Ts&&... xs) {
} // namespace <anonymous>
CAF_TEST(compare_custom_types) {
CAF_CHECK(make_message(s1{}) == make_message(s1{}));
s2 tmp;
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) {
......@@ -280,13 +262,10 @@ CAF_TEST(tuples_to_string) {
}
CAF_TEST(arrays_to_string) {
CAF_CHECK(make_message(s1{}) == make_message(s1{}));
CAF_CHECK(msg_as_string(s1{}) == "((10, 20, 30))");
auto msg2 = make_message(s2{});
s2 tmp;
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(make_message(s3{}) == make_message(s3{}));
CAF_CHECK(msg_as_string(s3{}) == "((1, 2, 3, 4))");
}
......@@ -108,12 +108,6 @@ void serialize(Processor& proc, test_array& x, const unsigned int) {
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 {
test_empty_non_pod() = default;
test_empty_non_pod(const test_empty_non_pod&) = default;
......@@ -306,7 +300,7 @@ CAF_TEST(messages) {
auto buf = serialize(msg);
message 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));
}
......@@ -317,7 +311,8 @@ CAF_TEST(multiple_messages) {
message m1;
message 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(m2).equal(i32, te, str, rs));
}
......
......@@ -31,7 +31,7 @@ CAF_TEST(simple_reply_response) {
auto s = system.spawn([](event_based_actor* self) -> behavior {
return (
others >> [=](const message& msg) -> message {
CAF_CHECK(msg == make_message(ok_atom::value));
CAF_CHECK(to_string(msg) == "('ok')");
self->quit();
return msg;
}
......@@ -41,7 +41,7 @@ CAF_TEST(simple_reply_response) {
self->send(s, ok_atom::value);
self->receive(
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) {
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() {
return {
[](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