Commit af0db378 authored by Dominik Charousset's avatar Dominik Charousset

improved announce interface, i.e., allow user-defined types as POD members and...

improved announce interface, i.e., allow user-defined types as POD members and auto-detect recursive containers such as vector<vector<double>>
parent cc998bac
Version 0.4.2
2012-XX-XX
2012-10-1
- Bugfix: evaluate `errno` whenever select() fails and handle errors properly
- Refactored announce
* accept recursive containers, e.g., vector<vector<double>>
* allow user-defined types as members of announced types
* all-new, policy-based implementation
Version 0.4.1
......
......@@ -54,14 +54,11 @@ cppa/detail/empty_tuple.hpp
cppa/detail/get_behavior.hpp
cppa/detail/group_manager.hpp
cppa/detail/implicit_conversions.hpp
cppa/detail/list_member.hpp
cppa/detail/map_member.hpp
cppa/detail/matches.hpp
cppa/detail/network_manager.hpp
cppa/detail/object_array.hpp
cppa/detail/object_impl.hpp
cppa/detail/pair_member.hpp
cppa/detail/primitive_member.hpp
cppa/detail/projection.hpp
cppa/detail/pseudo_tuple.hpp
cppa/detail/ptype_to_type.hpp
......
......@@ -83,7 +83,7 @@ class container_tuple_view : public abstract_tuple {
private:
std::unique_ptr<Container, disablable_delete<Container> > m_ptr;
std::unique_ptr<Container, disablable_delete> m_ptr;
};
......
......@@ -33,21 +33,25 @@
namespace cppa { namespace detail {
template<typename T>
class disablable_delete {
bool m_enabled;
public:
disablable_delete() : m_enabled(true) { }
constexpr disablable_delete() : m_enabled(true) { }
inline void disable() { m_enabled = false; }
inline void disable() {
m_enabled = false;
}
template<typename T>
inline void operator()(T* ptr) {
if (m_enabled) delete ptr;
}
private:
bool m_enabled;
};
} } // namespace cppa::detail
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_LIST_MEMBER_HPP
#define CPPA_LIST_MEMBER_HPP
#include "cppa/util/is_primitive.hpp"
#include "cppa/util/abstract_uniform_type_info.hpp"
namespace cppa { namespace detail {
template<typename List, bool HasPrimitiveValues>
struct list_member_util {
typedef typename List::value_type value_type;
static constexpr primitive_type vptype = type_to_ptype<value_type>::ptype;
void operator()(const List& list, serializer* s) const {
s->begin_sequence(list.size());
for (auto i = list.begin(); i != list.end(); ++i) {
s->write_value(*i);
}
s->end_sequence();
}
void operator()(List& list, deserializer* d) const {
list.clear();
auto size = d->begin_sequence();
for (decltype(size) i = 0; i < size; ++i) {
list.push_back(get<value_type>(d->read_value(vptype)));
}
d->end_sequence();
}
};
template<typename List>
struct list_member_util<List, false> {
typedef typename List::value_type value_type;
const uniform_type_info* m_value_type;
list_member_util() : m_value_type(uniform_typeid<value_type>()) {
}
void operator()(const List& list, serializer* s) const {
s->begin_sequence(list.size());
for (auto i = list.begin(); i != list.end(); ++i) {
m_value_type->serialize(&(*i), s);
}
s->end_sequence();
}
void operator()(List& list, deserializer* d) const {
list.clear();
value_type tmp;
auto size = d->begin_sequence();
for (decltype(size) i = 0; i < size; ++i) {
m_value_type->deserialize(&tmp, d);
list.push_back(tmp);
}
d->end_sequence();
}
};
template<typename List>
class list_member : public util::abstract_uniform_type_info<List> {
typedef typename List::value_type value_type;
list_member_util<List, util::is_primitive<value_type>::value> m_helper;
public:
void serialize(const void* obj, serializer* s) const {
auto& list = *reinterpret_cast<const List*>(obj);
m_helper(list, s);
}
void deserialize(void* obj, deserializer* d) const {
auto& list = *reinterpret_cast<List*>(obj);
m_helper(list, d);
}
};
} } // namespace cppa::detail
#endif // CPPA_LIST_MEMBER_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_MAP_MEMBER_HPP
#define CPPA_MAP_MEMBER_HPP
#include <type_traits>
#include "cppa/detail/pair_member.hpp"
#include "cppa/detail/primitive_member.hpp"
#include "cppa/util/abstract_uniform_type_info.hpp"
namespace cppa { namespace detail {
template<typename T>
struct is_pair { static constexpr bool value = false; };
template<typename First, typename Second>
struct is_pair< std::pair<First, Second> > { static constexpr bool value = true; };
template<typename T, bool IsPair, bool IsPrimitive>
struct map_member_util;
// std::set with primitive value
template<typename T>
struct map_member_util<T, false, true> {
primitive_member<T> impl;
void serialize_value(const T& what, serializer* s) const {
impl.serialize(&what, s);
}
template<typename M>
void deserialize_and_insert(M& map, deserializer* d) const {
T value;
impl.deserialize(&value, d);
map.insert(std::move(value));
}
};
// std::set with non-primitive value
template<typename T>
struct map_member_util<T, false, false> {
const uniform_type_info* m_type;
map_member_util() : m_type(uniform_typeid<T>()) {
}
void serialize_value(const T& what, serializer* s) const {
m_type->serialize(&what, s);
}
template<typename M>
void deserialize_and_insert(M& map, deserializer* d) const {
T value;
m_type->deserialize(&value, d);
map.insert(std::move(value));
}
};
// std::map
template<typename T>
struct map_member_util<T, true, false> {
// std::map defines its first half of value_type as const
typedef typename std::remove_const<typename T::first_type>::type first_type;
typedef typename T::second_type second_type;
pair_member<first_type, second_type> impl;
void serialize_value(const T& what, serializer* s) const {
// impl needs a pair without const modifier
std::pair<first_type, second_type> p(what.first, what.second);
impl.serialize(&p, s);
}
template<typename M>
void deserialize_and_insert(M& map, deserializer* d) const {
std::pair<first_type, second_type> p;
impl.deserialize(&p, d);
std::pair<const first_type, second_type> v(std::move(p.first),
std::move(p.second));
map.insert(std::move(v));
}
};
template<typename Map>
class map_member : public util::abstract_uniform_type_info<Map> {
typedef typename Map::key_type key_type;
typedef typename Map::value_type value_type;
map_member_util<value_type,
is_pair<value_type>::value,
util::is_primitive<value_type>::value> m_helper;
public:
void serialize(const void* obj, serializer* s) const {
auto& mp = *reinterpret_cast<const Map*>(obj);
s->begin_sequence(mp.size());
for (const auto& val : mp) {
m_helper.serialize_value(val, s);
}
s->end_sequence();
}
void deserialize(void* obj, deserializer* d) const {
auto& mp = *reinterpret_cast<Map*>(obj);
mp.clear();
size_t mp_size = d->begin_sequence();
for (size_t i = 0; i < mp_size; ++i) {
m_helper.deserialize_and_insert(mp, d);
}
d->end_sequence();
}
};
} } // namespace cppa::detail
#endif // CPPA_MAP_MEMBER_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_PRIMITIVE_MEMBER_HPP
#define CPPA_PRIMITIVE_MEMBER_HPP
#include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/primitive_type.hpp"
#include "cppa/primitive_variant.hpp"
#include "cppa/detail/type_to_ptype.hpp"
#include "cppa/util/abstract_uniform_type_info.hpp"
namespace cppa { namespace detail {
// uniform_type_info implementation for primitive data types.
template<typename T>
class primitive_member : public util::abstract_uniform_type_info<T> {
static constexpr primitive_type ptype = type_to_ptype<T>::ptype;
static_assert(ptype != pt_null, "T is not a primitive type");
public:
void serialize(const void* obj, serializer* s) const {
s->write_value(*reinterpret_cast<const T*>(obj));
}
void deserialize(void* obj, deserializer* d) const {
primitive_variant val(d->read_value(ptype));
*reinterpret_cast<T*>(obj) = std::move(get<T>(val));
}
};
} } // namespace cppa::detail
#endif // CPPA_PRIMITIVE_MEMBER_HPP
......@@ -4,10 +4,13 @@
#include <iostream>
#include "cppa/cppa.hpp"
#include "cppa/binary_serializer.hpp"
#include "cppa/binary_deserializer.hpp"
using std::cout;
using std::endl;
using namespace std;
using namespace cppa;
// POD struct
......@@ -28,11 +31,41 @@ typedef std::pair<int,int> foo_pair;
// another pair of two ints
typedef std::pair<int,int> foo_pair2;
// a struct with member vector<vector<...>>
struct foo2 {
int a;
vector<vector<double> > b;
};
bool operator==( const foo2& lhs, const foo2& rhs ) {
return lhs.a == rhs.a && lhs.b == rhs.b;
}
int main(int, char**) {
// announces foo to the libcppa type system;
// the function expects member pointers to all elements of foo
assert(announce<foo>(&foo::a, &foo::b) == true);
// announce foo2 to the libcppa type system,
// note that recursive containers are managed automatically by libcppa
assert(announce<foo2>(&foo2::a, &foo2::b) == true);
foo2 vd;
vd.a = 5;
vd.b.resize(1);
vd.b.back().push_back(42);
util::buffer buf;
binary_serializer bs(&buf);
bs << vd;
binary_deserializer bd(buf.data(), buf.size());
foo2 vd2;
uniform_typeid<foo2>()->deserialize(&vd2, &bd);
assert(vd == vd2);
// announce std::pair<int,int> to the type system;
// NOTE: foo_pair is NOT distinguishable from foo_pair2!
assert(announce<foo_pair>(&foo_pair::first, &foo_pair::second) == true);
......
......@@ -24,6 +24,9 @@ inline void exec_plugin() {
}
}
}
else {
cerr << "*** plugin did not define symbol exec_plugin!" << endl;
}
}
}
......
#define CPPA_VERBOSE_CHECK
#include "cppa/config.hpp"
#include <new>
......@@ -185,7 +187,7 @@ int main() {
}
{
any_tuple ttup = make_cow_tuple(1, 2, actor_ptr(self));
auto ttup = make_any_tuple(1, 2, actor_ptr(self));
util::buffer wr_buf;
binary_serializer bs(&wr_buf);
bs << ttup;
......
......@@ -73,6 +73,7 @@ int main() {
"@i8", "@i16", "@i32", "@i64", // signed integer names
"@u8", "@u16", "@u32", "@u64", // unsigned integer names
"@str", "@u16str", "@u32str", // strings
"@strmap", // string containers
"float", "double", // floating points
"@0", // cppa::util::void_type
// default announced cppa types
......
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