Commit 904adf60 authored by neverlord's avatar neverlord

any_tuple, serialization stuff and group modules

parent 767ab3f4
all: all:
./create_libcppa_Makefile.sh > libcppa.Makefile
make -f libcppa.Makefile make -f libcppa.Makefile
make -C unit_testing make -C unit_testing
make -C queue_performances make -C queue_performances
......
...@@ -17,7 +17,6 @@ cppa/config.hpp ...@@ -17,7 +17,6 @@ cppa/config.hpp
unit_testing/test__tuple.cpp unit_testing/test__tuple.cpp
cppa/detail/abstract_tuple.hpp cppa/detail/abstract_tuple.hpp
cppa/tuple_view.hpp cppa/tuple_view.hpp
cppa/untyped_tuple.hpp
cppa/any_type.hpp cppa/any_type.hpp
cppa/detail/matcher.hpp cppa/detail/matcher.hpp
cppa/detail/tuple_vals.hpp cppa/detail/tuple_vals.hpp
...@@ -64,15 +63,12 @@ src/deserializer.cpp ...@@ -64,15 +63,12 @@ src/deserializer.cpp
cppa/util/eval_type_list.hpp cppa/util/eval_type_list.hpp
cppa/util/is_legal_tuple_type.hpp cppa/util/is_legal_tuple_type.hpp
cppa/util/replace_type.hpp cppa/util/replace_type.hpp
src/untyped_tuple.cpp
cppa/util/abstract_type_list.hpp cppa/util/abstract_type_list.hpp
cppa/detail/serialize_tuple.hpp cppa/detail/serialize_tuple.hpp
unit_testing/test__atom.cpp unit_testing/test__atom.cpp
unit_testing/test__queue_performance.cpp unit_testing/test__queue_performance.cpp
cppa/detail/actor_public.hpp
cppa/util/single_reader_queue.hpp cppa/util/single_reader_queue.hpp
cppa/util/singly_linked_list.hpp cppa/util/singly_linked_list.hpp
cppa/detail/actor_private.hpp
unit_testing/test__local_group.cpp unit_testing/test__local_group.cpp
unit_testing/hash_of.cpp unit_testing/hash_of.cpp
unit_testing/hash_of.hpp unit_testing/hash_of.hpp
...@@ -128,7 +124,6 @@ cppa/util/is_primitive.hpp ...@@ -128,7 +124,6 @@ cppa/util/is_primitive.hpp
cppa/util/is_iterable.hpp cppa/util/is_iterable.hpp
src/primitive_variant.cpp src/primitive_variant.cpp
unit_testing/test__primitive_variant.cpp unit_testing/test__primitive_variant.cpp
cppa/util/uniform_type_info_base.hpp
cppa/detail/primitive_member.hpp cppa/detail/primitive_member.hpp
cppa/detail/list_member.hpp cppa/detail/list_member.hpp
cppa/detail/pair_member.hpp cppa/detail/pair_member.hpp
...@@ -147,3 +142,9 @@ src/message.cpp ...@@ -147,3 +142,9 @@ src/message.cpp
cppa/util/shared_spinlock.hpp cppa/util/shared_spinlock.hpp
src/shared_spinlock.cpp src/shared_spinlock.cpp
cppa/util/shared_lock_guard.hpp cppa/util/shared_lock_guard.hpp
cppa/get_view.hpp
cppa/detail/object_array.hpp
src/object_array.cpp
cppa/any_tuple.hpp
src/any_tuple.cpp
cppa/util/abstract_uniform_type_info.hpp
...@@ -4,13 +4,13 @@ ...@@ -4,13 +4,13 @@
#include <typeinfo> #include <typeinfo>
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
#include "cppa/util/uniform_type_info_base.hpp" #include "cppa/util/abstract_uniform_type_info.hpp"
#include "cppa/detail/default_uniform_type_info_impl.hpp" #include "cppa/detail/default_uniform_type_info_impl.hpp"
namespace cppa { namespace cppa {
template<class C, class Parent, typename... Args> template<class C, class Parent, typename... Args>
std::pair<C Parent::*, util::uniform_type_info_base<C>*> std::pair<C Parent::*, util::abstract_uniform_type_info<C>*>
compound_member(C Parent::*c_ptr, const Args&... args) compound_member(C Parent::*c_ptr, const Args&... args)
{ {
return { c_ptr, new detail::default_uniform_type_info_impl<C>(args...) }; return { c_ptr, new detail::default_uniform_type_info_impl<C>(args...) };
......
#ifndef ANY_TUPLE_HPP
#define ANY_TUPLE_HPP
#include "cppa/cow_ptr.hpp"
#include "cppa/tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/detail/abstract_tuple.hpp"
namespace cppa {
/**
* @brief Describes a fixed-length tuple (or tuple view)
* with elements of any type.
*/
class any_tuple
{
cow_ptr<detail::abstract_tuple> m_vals;
public:
typedef cow_ptr<detail::abstract_tuple> vals_ptr;
any_tuple();
template<typename... Args>
any_tuple(const tuple<Args...>& t) : m_vals(t.vals()) { }
template<typename... Args>
any_tuple(const tuple_view<Args...>& t) : m_vals(t.vals()) { }
any_tuple(vals_ptr&& vals);
any_tuple(const vals_ptr& vals);
any_tuple(any_tuple&&);
any_tuple(const any_tuple&) = default;
any_tuple& operator=(any_tuple&&);
any_tuple& operator=(const any_tuple&) = default;
size_t size() const;
void* mutable_at(size_t p);
const void* at(size_t p) const;
const uniform_type_info& type_at(size_t p) const;
const util::abstract_type_list& types() const;
const cow_ptr<detail::abstract_tuple>& vals() const;
bool equal_to(const any_tuple& other) const;
};
inline bool operator==(const any_tuple& lhs, const any_tuple& rhs)
{
return lhs.equal_to(rhs);
}
inline bool operator!=(const any_tuple& lhs, const any_tuple& rhs)
{
return !(lhs == rhs);
}
} // namespace cppa
#endif // ANY_TUPLE_HPP
...@@ -14,9 +14,9 @@ class channel : public ref_counted ...@@ -14,9 +14,9 @@ class channel : public ref_counted
public: public:
virtual ~channel(); virtual ~channel();
virtual void enqueue(const message&) = 0; virtual void enqueue(const message&) = 0;
}; };
......
...@@ -124,7 +124,7 @@ void reply(const Arg0& arg0, const Args&... args) ...@@ -124,7 +124,7 @@ void reply(const Arg0& arg0, const Args&... args)
if (whom) whom->enqueue(message(sptr, whom, arg0, args...)); if (whom) whom->enqueue(message(sptr, whom, arg0, args...));
} }
inline void await_all_actors_done() inline void await_all_others_done()
{ {
get_scheduler()->await_others_done(); get_scheduler()->await_others_done();
} }
......
...@@ -12,15 +12,15 @@ struct abstract_tuple : ref_counted ...@@ -12,15 +12,15 @@ struct abstract_tuple : ref_counted
{ {
// mutators // mutators
virtual void* mutable_at(std::size_t pos) = 0; virtual void* mutable_at(size_t pos) = 0;
// accessors // accessors
virtual std::size_t size() const = 0; virtual size_t size() const = 0;
virtual abstract_tuple* copy() const = 0; virtual abstract_tuple* copy() const = 0;
virtual const void* at(std::size_t pos) const = 0; virtual const void* at(size_t pos) const = 0;
virtual const util::abstract_type_list& types() const = 0; virtual const util::abstract_type_list& types() const = 0;
virtual bool equal_to(const abstract_tuple& other) const = 0; virtual bool equal_to(const abstract_tuple& other) const = 0;
virtual const uniform_type_info* utype_at(std::size_t pos) const = 0; virtual const uniform_type_info& type_at(size_t pos) const = 0;
}; };
......
#ifndef ACTOR_PRIVATE_HPP
#define ACTOR_PRIVATE_HPP
/*
#include <boost/thread/thread.hpp>
#include "cppa/invoke_rules.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/detail/channel.hpp"
#include "cppa/detail/actor_public.hpp"
namespace cppa { class message; }
namespace cppa { namespace detail {
// private part of the actor interface (callable only from this_actor())
struct actor_private : public actor_public
{
boost::thread* m_thread;
inline actor_private() : m_thread(0) { }
virtual ~actor_private();
virtual const message& receive() = 0;
virtual const message& last_dequeued() const = 0;
virtual void receive(invoke_rules&) = 0;
virtual void send(channel* whom, untyped_tuple&& what) = 0;
};
} } // namespace cppa::detail
namespace cppa {
detail::actor_private* this_actor();
inline const message& receive()
{
return this_actor()->receive();
}
inline void receive(invoke_rules& rules)
{
this_actor()->receive(rules);
}
inline void receive(invoke_rules&& rules)
{
invoke_rules tmp(std::move(rules));
this_actor()->receive(tmp);
}
inline const message& last_dequeued()
{
return this_actor()->last_dequeued();
}
} // namespace cppa
*/
#endif // ACTOR_PRIVATE_HPP
#ifndef ACTOR_PUBLIC_HPP
#define ACTOR_PUBLIC_HPP
/*
#include "cppa/detail/channel.hpp"
namespace cppa { namespace detail {
// public part of the actor interface
struct actor_public : channel
{
virtual void enqueue_msg(const message& msg) = 0;
};
} } // namespace cppa::detail
*/
#endif // ACTOR_PUBLIC_HPP
...@@ -25,7 +25,7 @@ class converted_thread_context : public context ...@@ -25,7 +25,7 @@ class converted_thread_context : public context
bool m_exited; bool m_exited;
// manages group subscriptions // manages group subscriptions
std::map<group_ptr, intrusive_ptr<group::subscription>> m_subscriptions; std::map<group_ptr, group::subscription> m_subscriptions;
// manages actor links // manages actor links
std::set<actor_ptr> m_links; std::set<actor_ptr> m_links;
......
...@@ -25,17 +25,17 @@ class decorated_tuple : public abstract_tuple ...@@ -25,17 +25,17 @@ class decorated_tuple : public abstract_tuple
typedef cow_ptr<abstract_tuple> ptr_type; typedef cow_ptr<abstract_tuple> ptr_type;
decorated_tuple(const ptr_type& d, decorated_tuple(const ptr_type& d,
const std::vector<std::size_t>& v) const std::vector<size_t>& v)
: m_decorated(d), m_mappings(v) : m_decorated(d), m_mappings(v)
{ {
} }
virtual void* mutable_at(std::size_t pos) virtual void* mutable_at(size_t pos)
{ {
return m_decorated->mutable_at(m_mappings[pos]); return m_decorated->mutable_at(m_mappings[pos]);
} }
virtual std::size_t size() const virtual size_t size() const
{ {
return m_mappings.size(); return m_mappings.size();
} }
...@@ -45,14 +45,14 @@ class decorated_tuple : public abstract_tuple ...@@ -45,14 +45,14 @@ class decorated_tuple : public abstract_tuple
return new decorated_tuple(*this); return new decorated_tuple(*this);
} }
virtual const void* at(std::size_t pos) const virtual const void* at(size_t pos) const
{ {
return m_decorated->at(m_mappings[pos]); return m_decorated->at(m_mappings[pos]);
} }
virtual const uniform_type_info* utype_at(std::size_t pos) const virtual const uniform_type_info& type_at(size_t pos) const
{ {
return m_decorated->utype_at(m_mappings[pos]); return m_decorated->type_at(m_mappings[pos]);
} }
virtual const util::abstract_type_list& types() const virtual const util::abstract_type_list& types() const
...@@ -68,7 +68,7 @@ class decorated_tuple : public abstract_tuple ...@@ -68,7 +68,7 @@ class decorated_tuple : public abstract_tuple
private: private:
ptr_type m_decorated; ptr_type m_decorated;
std::vector<std::size_t> m_mappings; std::vector<size_t> m_mappings;
element_types m_types; element_types m_types;
decorated_tuple(const decorated_tuple& other) decorated_tuple(const decorated_tuple& other)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "cppa/util/is_iterable.hpp" #include "cppa/util/is_iterable.hpp"
#include "cppa/util/is_primitive.hpp" #include "cppa/util/is_primitive.hpp"
#include "cppa/util/is_forward_iterator.hpp" #include "cppa/util/is_forward_iterator.hpp"
#include "cppa/util/uniform_type_info_base.hpp" #include "cppa/util/abstract_uniform_type_info.hpp"
#include "cppa/detail/map_member.hpp" #include "cppa/detail/map_member.hpp"
#include "cppa/detail/list_member.hpp" #include "cppa/detail/list_member.hpp"
...@@ -80,7 +80,7 @@ struct has_default_uniform_type_info_impl ...@@ -80,7 +80,7 @@ struct has_default_uniform_type_info_impl
}; };
template<typename T> template<typename T>
class default_uniform_type_info_impl : public util::uniform_type_info_base<T> class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T>
{ {
template<typename X> template<typename X>
...@@ -194,7 +194,7 @@ class default_uniform_type_info_impl : public util::uniform_type_info_base<T> ...@@ -194,7 +194,7 @@ class default_uniform_type_info_impl : public util::uniform_type_info_base<T>
// pr.first = member pointer // pr.first = member pointer
// pr.second = meta object to handle pr.first // pr.second = meta object to handle pr.first
template<typename R, class C, typename... Args> template<typename R, class C, typename... Args>
void push_back(std::pair<R C::*, util::uniform_type_info_base<R>*> pr, void push_back(std::pair<R C::*, util::abstract_uniform_type_info<R>*> pr,
const Args&... args) const Args&... args)
{ {
m_members.push_back({ pr.second, pr.first }); m_members.push_back({ pr.second, pr.first });
......
...@@ -6,16 +6,16 @@ ...@@ -6,16 +6,16 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
// intermediate is NOT thread safe // intermediate is NOT thread safe
class intermediate : public ref_counted_impl<std::size_t> class intermediate : public ref_counted_impl<size_t>
{ {
intermediate(const intermediate&) = delete; intermediate(const intermediate&) = delete;
intermediate& operator=(const intermediate&) = delete; intermediate& operator=(const intermediate&) = delete;
public: public:
intermediate() = default; intermediate() = default;
virtual void invoke() = 0; virtual void invoke() = 0;
}; };
...@@ -23,20 +23,20 @@ template<typename Impl, typename View> ...@@ -23,20 +23,20 @@ template<typename Impl, typename View>
class intermediate_impl : public intermediate class intermediate_impl : public intermediate
{ {
Impl m_impl; Impl m_impl;
View m_view; View m_view;
public: public:
intermediate_impl(const Impl& impl, const View& view) intermediate_impl(const Impl& impl, const View& view)
: intermediate(), m_impl(impl), m_view(view) : intermediate(), m_impl(impl), m_view(view)
{ {
} }
virtual void invoke() virtual void invoke()
{ {
m_impl(m_view); m_impl(m_view);
} }
}; };
......
...@@ -8,17 +8,17 @@ namespace cppa { namespace detail { ...@@ -8,17 +8,17 @@ namespace cppa { namespace detail {
class intermediate; class intermediate;
// invokable is NOT thread safe // invokable is NOT thread safe
class invokable : public ref_counted_impl<std::size_t> class invokable : public ref_counted_impl<size_t>
{ {
invokable(const invokable&) = delete; invokable(const invokable&) = delete;
invokable& operator=(const invokable&) = delete; invokable& operator=(const invokable&) = delete;
public: public:
invokable() = default; invokable() = default;
virtual bool invoke(const untyped_tuple&) const = 0; virtual bool invoke(const any_tuple&) const = 0;
virtual intermediate* get_intermediate(const untyped_tuple&) const = 0; virtual intermediate* get_intermediate(const any_tuple&) const = 0;
}; };
...@@ -26,22 +26,22 @@ template<typename Invoker, typename Getter> ...@@ -26,22 +26,22 @@ template<typename Invoker, typename Getter>
class invokable_impl : public invokable class invokable_impl : public invokable
{ {
Invoker m_inv; Invoker m_inv;
Getter m_get; Getter m_get;
public: public:
invokable_impl(Invoker&& i, Getter&& g) : m_inv(i), m_get(g) { } invokable_impl(Invoker&& i, Getter&& g) : m_inv(i), m_get(g) { }
virtual bool invoke(const untyped_tuple& t) const virtual bool invoke(const any_tuple& t) const
{ {
return m_inv(t); return m_inv(t);
} }
virtual intermediate* get_intermediate(const untyped_tuple& t) const virtual intermediate* get_intermediate(const any_tuple& t) const
{ {
return m_get(t); return m_get(t);
} }
}; };
......
#ifndef LIST_MEMBER_HPP #ifndef LIST_MEMBER_HPP
#define LIST_MEMBER_HPP #define LIST_MEMBER_HPP
#include "cppa/util/uniform_type_info_base.hpp" #include "cppa/util/abstract_uniform_type_info.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<typename List> template<typename List>
class list_member : public util::uniform_type_info_base<List> class list_member : public util::abstract_uniform_type_info<List>
{ {
typedef typename List::value_type value_type; typedef typename List::value_type value_type;
......
#ifndef MAP_MEMBER_HPP #ifndef MAP_MEMBER_HPP
#define MAP_MEMBER_HPP #define MAP_MEMBER_HPP
#include "cppa/util/uniform_type_info_base.hpp" #include "cppa/util/abstract_uniform_type_info.hpp"
#include "cppa/detail/primitive_member.hpp" #include "cppa/detail/primitive_member.hpp"
#include "cppa/detail/pair_member.hpp" #include "cppa/detail/pair_member.hpp"
...@@ -46,7 +46,7 @@ struct meta_value_type<std::pair<const T1, T2>> ...@@ -46,7 +46,7 @@ struct meta_value_type<std::pair<const T1, T2>>
}; };
template<typename Map> template<typename Map>
class map_member : public util::uniform_type_info_base<Map> class map_member : public util::abstract_uniform_type_info<Map>
{ {
typedef typename Map::key_type key_type; typedef typename Map::key_type key_type;
......
...@@ -16,8 +16,8 @@ struct matcher<Head, Tail...> ...@@ -16,8 +16,8 @@ struct matcher<Head, Tail...>
{ {
static bool match(util::abstract_type_list::const_iterator& begin, static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end, util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr, std::vector<size_t>* res = nullptr,
std::size_t pos = 0) size_t pos = 0)
{ {
auto head_uti = uniform_typeid<Head>(); auto head_uti = uniform_typeid<Head>();
if (begin != end) if (begin != end)
...@@ -42,8 +42,8 @@ struct matcher<any_type, Tail...> ...@@ -42,8 +42,8 @@ struct matcher<any_type, Tail...>
{ {
static bool match(util::abstract_type_list::const_iterator& begin, static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end, util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr, std::vector<size_t>* res = nullptr,
std::size_t pos = 0) size_t pos = 0)
{ {
if (begin != end) if (begin != end)
{ {
...@@ -60,8 +60,8 @@ struct matcher<any_type*, Next, Tail...> ...@@ -60,8 +60,8 @@ struct matcher<any_type*, Next, Tail...>
{ {
static bool match(util::abstract_type_list::const_iterator& begin, static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end, util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr, std::vector<size_t>* res = nullptr,
std::size_t pos = 0) size_t pos = 0)
{ {
bool result = false; bool result = false;
while (!result) while (!result)
...@@ -90,8 +90,8 @@ struct matcher<any_type*> ...@@ -90,8 +90,8 @@ struct matcher<any_type*>
{ {
static bool match(util::abstract_type_list::const_iterator&, static bool match(util::abstract_type_list::const_iterator&,
util::abstract_type_list::const_iterator&, util::abstract_type_list::const_iterator&,
std::vector<std::size_t>* = nullptr, std::vector<size_t>* = nullptr,
std::size_t = 0) size_t = 0)
{ {
return true; return true;
} }
...@@ -102,8 +102,8 @@ struct matcher<> ...@@ -102,8 +102,8 @@ struct matcher<>
{ {
static bool match(util::abstract_type_list::const_iterator& begin, static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end, util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* = nullptr, std::vector<size_t>* = nullptr,
std::size_t = 0) size_t = 0)
{ {
return begin == end; return begin == end;
} }
......
#ifndef OBJECT_ARRAY_HPP
#define OBJECT_ARRAY_HPP
#include <vector>
#include "cppa/object.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/util/abstract_type_list.hpp"
namespace cppa { namespace detail {
class object_array : public detail::abstract_tuple
, public util::abstract_type_list
{
std::vector<object> m_elements;
public:
object_array();
object_array(object_array&& other);
object_array(const object_array& other);
/**
* @pre
*/
void push_back(object&& what);
void push_back(const object& what);
void* mutable_at(size_t pos);
size_t size() const;
abstract_tuple* copy() const;
const void* at(size_t pos) const;
const util::abstract_type_list& types() const;
bool equal_to(const cppa::detail::abstract_tuple&) const;
const uniform_type_info& type_at(size_t pos) const;
util::abstract_type_list::const_iterator begin() const;
};
} } // namespace cppa::detail
#endif // OBJECT_ARRAY_HPP
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
#define PAIR_MEMBER_HPP #define PAIR_MEMBER_HPP
#include <utility> #include <utility>
#include "cppa/util/uniform_type_info_base.hpp" #include "cppa/util/abstract_uniform_type_info.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<typename T1, typename T2> template<typename T1, typename T2>
class pair_member : public util::uniform_type_info_base<std::pair<T1,T2>> class pair_member : public util::abstract_uniform_type_info<std::pair<T1,T2>>
{ {
static constexpr primitive_type ptype1 = type_to_ptype<T1>::ptype; static constexpr primitive_type ptype1 = type_to_ptype<T1>::ptype;
......
...@@ -6,13 +6,13 @@ ...@@ -6,13 +6,13 @@
#include "cppa/primitive_type.hpp" #include "cppa/primitive_type.hpp"
#include "cppa/primitive_variant.hpp" #include "cppa/primitive_variant.hpp"
#include "cppa/detail/type_to_ptype.hpp" #include "cppa/detail/type_to_ptype.hpp"
#include "cppa/util/uniform_type_info_base.hpp" #include "cppa/util/abstract_uniform_type_info.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
// uniform_type_info implementation for primitive data types. // uniform_type_info implementation for primitive data types.
template<typename T> template<typename T>
class primitive_member : public util::uniform_type_info_base<T> class primitive_member : public util::abstract_uniform_type_info<T>
{ {
static constexpr primitive_type ptype = type_to_ptype<T>::ptype; static constexpr primitive_type ptype = type_to_ptype<T>::ptype;
......
...@@ -10,23 +10,23 @@ namespace cppa { class serializer; } ...@@ -10,23 +10,23 @@ namespace cppa { class serializer; }
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<typename List, std::size_t Pos = 0> template<typename List, size_t Pos = 0>
struct serialize_tuple struct serialize_tuple
{ {
template<typename T> template<typename T>
inline static void _(serializer& s, const T* self) inline static void _(serializer& s, const T* self)
{ {
s << uniform_typeid<typename List::head_type>()->name() s << uniform_typeid<typename List::head_type>()->name()
<< *reinterpret_cast<const typename List::head_type*>(self->at(Pos)); << *reinterpret_cast<const typename List::head_type*>(self->at(Pos));
serialize_tuple<typename List::tail_type, Pos + 1>::_(s, self); serialize_tuple<typename List::tail_type, Pos + 1>::_(s, self);
} }
}; };
template<std::size_t Pos> template<size_t Pos>
struct serialize_tuple<util::type_list<>, Pos> struct serialize_tuple<util::type_list<>, Pos>
{ {
template<typename T> template<typename T>
inline static void _(serializer&, const T*) { } inline static void _(serializer&, const T*) { }
}; };
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -8,39 +8,39 @@ namespace cppa { namespace detail { ...@@ -8,39 +8,39 @@ namespace cppa { namespace detail {
template<typename T> template<typename T>
struct byte_access struct byte_access
{ {
union union
{ {
T value; T value;
unsigned char bytes[sizeof(T)]; unsigned char bytes[sizeof(T)];
}; };
inline byte_access(T val = 0) : value(val) { } inline byte_access(T val = 0) : value(val) { }
}; };
template<std::size_t SizeOfT, typename T> template<size_t SizeOfT, typename T>
struct byte_swapper struct byte_swapper
{ {
static T _(byte_access<T> from) static T _(byte_access<T> from)
{ {
byte_access<T> to; byte_access<T> to;
auto i = SizeOfT - 1; auto i = SizeOfT - 1;
for (std::size_t j = 0 ; j < SizeOfT ; --i, ++j) for (size_t j = 0 ; j < SizeOfT ; --i, ++j)
{ {
to.bytes[i] = from.bytes[j]; to.bytes[i] = from.bytes[j];
} }
return to.value; return to.value;
} }
}; };
template<typename T> template<typename T>
struct byte_swapper<1, T> struct byte_swapper<1, T>
{ {
inline static T _(T what) { return what; } inline static T _(T what) { return what; }
}; };
template<typename T> template<typename T>
inline T swap_bytes(T what) inline T swap_bytes(T what)
{ {
return byte_swapper<sizeof(T), T>::_(what); return byte_swapper<sizeof(T), T>::_(what);
} }
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -14,30 +14,30 @@ template<> ...@@ -14,30 +14,30 @@ template<>
struct tdata<> struct tdata<>
{ {
typedef util::type_list<> element_types; typedef util::type_list<> element_types;
typedef typename element_types::head_type head_type; typedef typename element_types::head_type head_type;
typedef typename element_types::tail_type tail_type; typedef typename element_types::tail_type tail_type;
static const std::size_t type_list_size = element_types::type_list_size; static const size_t type_list_size = element_types::type_list_size;
util::void_type head; util::void_type head;
tdata<>& tail() tdata<>& tail()
{ {
throw std::out_of_range(""); throw std::out_of_range("");
} }
const tdata<>& tail() const const tdata<>& tail() const
{ {
throw std::out_of_range(""); throw std::out_of_range("");
} }
inline bool operator==(const tdata&) const inline bool operator==(const tdata&) const
{ {
return true; return true;
} }
}; };
...@@ -45,72 +45,72 @@ template<typename Head, typename... Tail> ...@@ -45,72 +45,72 @@ template<typename Head, typename... Tail>
struct tdata<Head, Tail...> : tdata<Tail...> struct tdata<Head, Tail...> : tdata<Tail...>
{ {
typedef tdata<Tail...> super; typedef tdata<Tail...> super;
typedef util::type_list<Head, Tail...> element_types; typedef util::type_list<Head, Tail...> element_types;
typedef typename element_types::head_type head_type; typedef typename element_types::head_type head_type;
typedef typename element_types::tail_type tail_type; typedef typename element_types::tail_type tail_type;
static const std::size_t type_list_size = element_types::type_list_size; static const size_t type_list_size = element_types::type_list_size;
Head head; Head head;
inline tdata() : super(), head() { } inline tdata() : super(), head() { }
tdata(const Head& v0, const Tail&... vals) : super(vals...), head(v0) { } tdata(const Head& v0, const Tail&... vals) : super(vals...), head(v0) { }
inline tdata<Tail...>& tail() inline tdata<Tail...>& tail()
{ {
// upcast // upcast
return *this; return *this;
} }
inline const tdata<Tail...>& tail() const inline const tdata<Tail...>& tail() const
{ {
// upcast // upcast
return *this; return *this;
} }
inline bool operator==(const tdata& other) const inline bool operator==(const tdata& other) const
{ {
return head == other.head && tail() == other.tail(); return head == other.head && tail() == other.tail();
} }
}; };
template<std::size_t N, typename... ElementTypes> template<size_t N, typename... ElementTypes>
struct tdata_upcast_helper; struct tdata_upcast_helper;
template<std::size_t N, typename Head, typename... Tail> template<size_t N, typename Head, typename... Tail>
struct tdata_upcast_helper<N, Head, Tail...> struct tdata_upcast_helper<N, Head, Tail...>
{ {
typedef typename tdata_upcast_helper<N-1, Tail...>::type type; typedef typename tdata_upcast_helper<N-1, Tail...>::type type;
}; };
template<typename Head, typename... Tail> template<typename Head, typename... Tail>
struct tdata_upcast_helper<0, Head, Tail...> struct tdata_upcast_helper<0, Head, Tail...>
{ {
typedef tdata<Head, Tail...> type; typedef tdata<Head, Tail...> type;
}; };
template<std::size_t N, typename... ElementTypes> template<size_t N, typename... ElementTypes>
const typename util::type_at<N, util::type_list<ElementTypes...>>::type& const typename util::type_at<N, util::type_list<ElementTypes...>>::type&
tdata_get(const tdata<ElementTypes...>& tv) tdata_get(const tdata<ElementTypes...>& tv)
{ {
static_assert(N < util::type_list<ElementTypes...>::type_list_size, static_assert(N < util::type_list<ElementTypes...>::type_list_size,
"N < tv.size()"); "N < tv.size()");
return static_cast<const typename tdata_upcast_helper<N, ElementTypes...>::type&>(tv).head; return static_cast<const typename tdata_upcast_helper<N, ElementTypes...>::type&>(tv).head;
} }
template<std::size_t N, typename... ElementTypes> template<size_t N, typename... ElementTypes>
typename util::type_at<N, util::type_list<ElementTypes...>>::type& typename util::type_at<N, util::type_list<ElementTypes...>>::type&
tdata_get_ref(tdata<ElementTypes...>& tv) tdata_get_ref(tdata<ElementTypes...>& tv)
{ {
static_assert(N < util::type_list<ElementTypes...>::type_list_size, static_assert(N < util::type_list<ElementTypes...>::type_list_size,
"N >= tv.size()"); "N >= tv.size()");
return static_cast<typename tdata_upcast_helper<N, ElementTypes...>::type &>(tv).head; return static_cast<typename tdata_upcast_helper<N, ElementTypes...>::type &>(tv).head;
} }
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -26,13 +26,13 @@ class tuple_vals : public abstract_tuple ...@@ -26,13 +26,13 @@ class tuple_vals : public abstract_tuple
element_types m_types; element_types m_types;
template<typename... Types> template<typename... Types>
void* tdata_mutable_at(tdata<Types...>& d, std::size_t pos) void* tdata_mutable_at(tdata<Types...>& d, size_t pos)
{ {
return (pos == 0) ? &(d.head) : tdata_mutable_at(d.tail(), pos - 1); return (pos == 0) ? &(d.head) : tdata_mutable_at(d.tail(), pos - 1);
} }
template<typename... Types> template<typename... Types>
const void* tdata_at(const tdata<Types...>& d, std::size_t pos) const const void* tdata_at(const tdata<Types...>& d, size_t pos) const
{ {
return (pos == 0) ? &(d.head) : tdata_at(d.tail(), pos - 1); return (pos == 0) ? &(d.head) : tdata_at(d.tail(), pos - 1);
} }
...@@ -43,7 +43,7 @@ class tuple_vals : public abstract_tuple ...@@ -43,7 +43,7 @@ class tuple_vals : public abstract_tuple
typedef typename element_types::tail_type tail_type; typedef typename element_types::tail_type tail_type;
static const std::size_t type_list_size = element_types::type_list_size; static const size_t type_list_size = element_types::type_list_size;
tuple_vals(const tuple_vals& other) : super(), m_data(other.m_data) { } tuple_vals(const tuple_vals& other) : super(), m_data(other.m_data) { }
...@@ -55,12 +55,12 @@ class tuple_vals : public abstract_tuple ...@@ -55,12 +55,12 @@ class tuple_vals : public abstract_tuple
inline data_type& data_ref() { return m_data; } inline data_type& data_ref() { return m_data; }
virtual void* mutable_at(std::size_t pos) virtual void* mutable_at(size_t pos)
{ {
return tdata_mutable_at(m_data, pos); return tdata_mutable_at(m_data, pos);
} }
virtual std::size_t size() const virtual size_t size() const
{ {
return element_types::type_list_size; return element_types::type_list_size;
} }
...@@ -70,12 +70,12 @@ class tuple_vals : public abstract_tuple ...@@ -70,12 +70,12 @@ class tuple_vals : public abstract_tuple
return new tuple_vals(*this); return new tuple_vals(*this);
} }
virtual const void* at(std::size_t pos) const virtual const void* at(size_t pos) const
{ {
return tdata_at(m_data, pos); return tdata_at(m_data, pos);
} }
virtual const uniform_type_info* utype_at(std::size_t pos) const virtual const uniform_type_info& type_at(size_t pos) const
{ {
return m_types.at(pos); return m_types.at(pos);
} }
......
...@@ -16,21 +16,23 @@ class tuple; ...@@ -16,21 +16,23 @@ class tuple;
template<typename... ElementTypes> template<typename... ElementTypes>
class tuple_view; class tuple_view;
// forward declarations of get(...) // forward declarations of get(const tuple<...>&...)
template<std::size_t N, typename... Types> template<size_t N, typename... Types>
const typename util::type_at<N, util::type_list<Types...>>::type& const typename util::type_at<N, util::type_list<Types...>>::type&
get(const tuple<Types...>& t); get(const tuple<Types...>& t);
template<std::size_t N, typename... Types> // forward declarations of get(const tuple_view<...>&...)
template<size_t N, typename... Types>
const typename util::type_at<N, util::type_list<Types...>>::type& const typename util::type_at<N, util::type_list<Types...>>::type&
get(const tuple_view<Types...>& t); get(const tuple_view<Types...>& t);
// forward declarations of get_ref(...) // forward declarations of get_ref(tuple<...>&...)
template<std::size_t N, typename... Types> template<size_t N, typename... Types>
typename util::type_at<N, util::type_list<Types...>>::type& typename util::type_at<N, util::type_list<Types...>>::type&
get_ref(tuple<Types...>& t); get_ref(tuple<Types...>& t);
template<std::size_t N, typename... Types> // forward declarations of get_ref(tuple_view<...>&...)
template<size_t N, typename... Types>
typename util::type_at<N, util::type_list<Types...>>::type& typename util::type_at<N, util::type_list<Types...>>::type&
get_ref(tuple_view<Types...>& t); get_ref(tuple_view<Types...>& t);
......
#ifndef GET_VIEW_HPP
#define GET_VIEW_HPP
#include <vector>
#include <cstddef>
#include "cppa/match.hpp"
#include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/util/a_matches_b.hpp"
namespace cppa {
template<typename... MatchRules, template <typename...> class Tuple, typename... TupleTypes>
typename tuple_view_type_from_type_list<typename util::filter_type_list<any_type, util::type_list<MatchRules...>>::type>::type
get_view(const Tuple<TupleTypes...>& t)
{
static_assert(util::a_matches_b<util::type_list<MatchRules...>,
util::type_list<TupleTypes...>>::value,
"MatchRules does not match Tuple");
std::vector<size_t> mappings;
util::abstract_type_list::const_iterator begin = t.types().begin();
util::abstract_type_list::const_iterator end = t.types().end();
if (detail::matcher<MatchRules...>::match(begin, end, &mappings))
{
return { t.vals(), std::move(mappings) };
}
throw std::runtime_error("matcher did not return a valid mapping");
}
template<typename... MatchRules>
typename tuple_view_type_from_type_list<typename util::filter_type_list<any_type, util::type_list<MatchRules...>>::type>::type
get_view(const any_tuple& ut)
{
std::vector<size_t> mappings;
if (match<MatchRules...>(ut, mappings))
{
return { ut.vals(), std::move(mappings) };
}
// todo: throw nicer exception
throw std::runtime_error("doesn't match");
}
} // namespace cppa
#endif // GET_VIEW_HPP
#ifndef GROUP_HPP #ifndef GROUP_HPP
#define GROUP_HPP #define GROUP_HPP
#include <string>
#include "cppa/channel.hpp" #include "cppa/channel.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
...@@ -11,34 +13,48 @@ class group : public channel ...@@ -11,34 +13,48 @@ class group : public channel
protected: protected:
virtual void unsubscribe(const channel_ptr& who) = 0; virtual void unsubscribe(const channel_ptr& who) = 0;
public: public:
class subscription; class subscription;
friend class subscription;
class subscription
{
channel_ptr m_self;
intrusive_ptr<group> m_group;
subscription() = delete;
subscription(const subscription&) = delete;
subscription& operator=(const subscription&) = delete;
public:
friend class group::subscription; subscription(const channel_ptr& s, const intrusive_ptr<group>& g);
subscription(subscription&& other);
~subscription();
// NOT thread safe };
class subscription : public ref_counted
{
channel_ptr m_self; class module
intrusive_ptr<group> m_group; {
subscription() = delete; public:
subscription(const subscription&) = delete;
subscription& operator=(const subscription&) = delete;
public: virtual const std::string& name() = 0;
virtual intrusive_ptr<group> get(const std::string& group_name) = 0;
subscription(const channel_ptr& s, const intrusive_ptr<group>& g); };
virtual ~subscription(); virtual subscription subscribe(const channel_ptr& who) = 0;
}; static intrusive_ptr<group> get(const std::string& module_name,
const std::string& group_name);
virtual intrusive_ptr<subscription> subscribe(const channel_ptr& who) = 0; static void add_module(module*);
}; };
......
...@@ -25,7 +25,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, T*>, ...@@ -25,7 +25,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, T*>,
public: public:
intrusive_ptr() : m_ptr(0) { } intrusive_ptr() : m_ptr(nullptr) { }
intrusive_ptr(T* raw_ptr) { set_ptr(raw_ptr); } intrusive_ptr(T* raw_ptr) { set_ptr(raw_ptr); }
...@@ -34,7 +34,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, T*>, ...@@ -34,7 +34,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, T*>,
set_ptr(other.m_ptr); set_ptr(other.m_ptr);
} }
intrusive_ptr(intrusive_ptr&& other) : m_ptr(0) intrusive_ptr(intrusive_ptr&& other) : m_ptr(nullptr)
{ {
swap(other); swap(other);
} }
...@@ -48,7 +48,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, T*>, ...@@ -48,7 +48,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, T*>,
} }
template<typename Y> template<typename Y>
intrusive_ptr(intrusive_ptr<Y>&& other) : m_ptr(0) intrusive_ptr(intrusive_ptr<Y>&& other) : m_ptr(nullptr)
{ {
swap(other); swap(other);
} }
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
#include <type_traits> #include <type_traits>
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp" #include "cppa/tuple_view.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/util/type_at.hpp" #include "cppa/util/type_at.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
...@@ -15,43 +15,43 @@ ...@@ -15,43 +15,43 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<std::size_t N, typename F, typename Tuple, template<size_t N, typename F, typename Tuple,
typename ArgTypeList, typename... Args> typename ArgTypeList, typename... Args>
struct invoke_helper struct invoke_helper
{ {
typedef typename util::reverse_type_list<ArgTypeList>::type::head_type back_type; typedef typename util::reverse_type_list<ArgTypeList>::type::head_type back_type;
typedef typename util::type_at<N, Tuple>::type tuple_val_type; typedef typename util::type_at<N, Tuple>::type tuple_val_type;
typedef typename util::type_list_pop_back<ArgTypeList>::type next_list; typedef typename util::type_list_pop_back<ArgTypeList>::type next_list;
inline static void _(F& f, const Tuple& t, const Args&... args) inline static void _(F& f, const Tuple& t, const Args&... args)
{ {
static_assert(std::is_convertible<tuple_val_type, back_type>::value, static_assert(std::is_convertible<tuple_val_type, back_type>::value,
"tuple element is not convertible to expected argument"); "tuple element is not convertible to expected argument");
invoke_helper<N - 1, F, Tuple, next_list, tuple_val_type, Args...> invoke_helper<N - 1, F, Tuple, next_list, tuple_val_type, Args...>
::_(f, t, t.get<N>(), args...); ::_(f, t, t.get<N>(), args...);
} }
}; };
template<std::size_t N, typename F, typename Tuple, typename... Args> template<size_t N, typename F, typename Tuple, typename... Args>
struct invoke_helper<N, F, Tuple, util::type_list<>, Args...> struct invoke_helper<N, F, Tuple, util::type_list<>, Args...>
{ {
inline static void _(F& f, const Tuple&, const Args&... args) inline static void _(F& f, const Tuple&, const Args&... args)
{ {
f(args...); f(args...);
} }
}; };
template<bool HasCallableTrait, typename Tuple, typename F> template<bool HasCallableTrait, typename Tuple, typename F>
struct invoke_impl struct invoke_impl
{ {
typedef typename util::callable_trait<F>::arg_types arg_types; typedef typename util::callable_trait<F>::arg_types arg_types;
static const std::size_t tuple_size = Tuple::type_list_size - 1; static const size_t tuple_size = Tuple::type_list_size - 1;
inline static void _(F& f, const Tuple& t) inline static void _(F& f, const Tuple& t)
{ {
invoke_helper<tuple_size, F, Tuple, arg_types>::_(f, t); invoke_helper<tuple_size, F, Tuple, arg_types>::_(f, t);
} }
}; };
...@@ -59,15 +59,15 @@ template<typename Tuple, typename F> ...@@ -59,15 +59,15 @@ template<typename Tuple, typename F>
struct invoke_impl<false, Tuple, F> struct invoke_impl<false, Tuple, F>
{ {
typedef typename util::callable_trait<decltype(&F::operator())>::arg_types typedef typename util::callable_trait<decltype(&F::operator())>::arg_types
arg_types; arg_types;
static const std::size_t tuple_size = Tuple::type_list_size - 1; static const size_t tuple_size = Tuple::type_list_size - 1;
inline static void _(F& f, const Tuple& t) inline static void _(F& f, const Tuple& t)
{ {
invoke_helper<tuple_size, F, Tuple, arg_types>::_(f, t); invoke_helper<tuple_size, F, Tuple, arg_types>::_(f, t);
} }
}; };
...@@ -78,8 +78,8 @@ namespace cppa { ...@@ -78,8 +78,8 @@ namespace cppa {
template<typename Tuple, typename F> template<typename Tuple, typename F>
void invoke(F what, const Tuple& args) void invoke(F what, const Tuple& args)
{ {
typedef typename std::remove_pointer<F>::type f_type; typedef typename std::remove_pointer<F>::type f_type;
detail::invoke_impl<std::is_function<f_type>::value, Tuple, F>::_(what, args); detail::invoke_impl<std::is_function<f_type>::value, Tuple, F>::_(what, args);
} }
} // namespace cppa } // namespace cppa
......
...@@ -36,7 +36,7 @@ struct invoke_rules ...@@ -36,7 +36,7 @@ struct invoke_rules
if (arg) m_list.push_back(arg); if (arg) m_list.push_back(arg);
} }
bool operator()(const untyped_tuple& t) const bool operator()(const any_tuple& t) const
{ {
for (auto i = m_list.begin(); i != m_list.end(); ++i) for (auto i = m_list.begin(); i != m_list.end(); ++i)
{ {
...@@ -45,7 +45,7 @@ struct invoke_rules ...@@ -45,7 +45,7 @@ struct invoke_rules
return false; return false;
} }
intrusive_ptr<detail::intermediate> get_intermediate(const untyped_tuple& t) const intrusive_ptr<detail::intermediate> get_intermediate(const any_tuple& t) const
{ {
detail::intermediate* result; detail::intermediate* result;
for (auto i = m_list.begin(); i != m_list.end(); ++i) for (auto i = m_list.begin(); i != m_list.end(); ++i)
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
#include <stdexcept> #include <stdexcept>
#include "cppa/any_type.hpp" #include "cppa/any_type.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp" #include "cppa/tuple_view.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/util/compare_tuples.hpp" #include "cppa/util/compare_tuples.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
...@@ -19,78 +19,48 @@ ...@@ -19,78 +19,48 @@
namespace cppa { namespace cppa {
template<typename... MatchRules> template<typename... MatchRules>
bool match(const untyped_tuple& what) bool match(const any_tuple& what)
{ {
util::abstract_type_list::const_iterator begin = what.types().begin(); util::abstract_type_list::const_iterator begin = what.types().begin();
util::abstract_type_list::const_iterator end = what.types().end(); util::abstract_type_list::const_iterator end = what.types().end();
return detail::matcher<MatchRules...>::match(begin, end); return detail::matcher<MatchRules...>::match(begin, end);
} }
template<typename... MatchRules> template<typename... MatchRules>
bool match(const untyped_tuple& what, std::vector<std::size_t>& mappings) bool match(const any_tuple& what, std::vector<size_t>& mappings)
{ {
util::abstract_type_list::const_iterator begin = what.types().begin(); util::abstract_type_list::const_iterator begin = what.types().begin();
util::abstract_type_list::const_iterator end = what.types().end(); util::abstract_type_list::const_iterator end = what.types().end();
return detail::matcher<MatchRules...>::match(begin, end, &mappings); return detail::matcher<MatchRules...>::match(begin, end, &mappings);
} }
template<typename... MatchRules, class ValuesTuple> template<typename... MatchRules, class ValuesTuple>
bool match(const untyped_tuple& what, const ValuesTuple& vals, bool match(const any_tuple& what, const ValuesTuple& vals,
std::vector<std::size_t>& mappings) std::vector<size_t>& mappings)
{ {
typedef util::type_list<MatchRules...> rules_list; typedef util::type_list<MatchRules...> rules_list;
typedef typename util::filter_type_list<any_type, rules_list>::type typedef typename util::filter_type_list<any_type, rules_list>::type
filtered_rules; filtered_rules;
typedef typename tuple_view_type_from_type_list<filtered_rules>::type typedef typename tuple_view_type_from_type_list<filtered_rules>::type
view_type; view_type;
static_assert(util::eval_type_lists<filtered_rules, static_assert(util::eval_type_lists<filtered_rules,
ValuesTuple, ValuesTuple,
util::is_comparable>::value, util::is_comparable>::value,
"given values are not comparable to matched types"); "given values are not comparable to matched types");
if (match<MatchRules...>(what, mappings)) if (match<MatchRules...>(what, mappings))
{ {
std::vector<std::size_t> tmp(mappings); std::vector<size_t> tmp(mappings);
view_type view(what.vals(), std::move(tmp)); view_type view(what.vals(), std::move(tmp));
return compare_first_elements(view, vals); return compare_first_elements(view, vals);
} }
return false; return false;
} }
template<typename... MatchRules, class ValuesTuple> template<typename... MatchRules, class ValuesTuple>
bool match(const untyped_tuple& what, const ValuesTuple& vals) bool match(const any_tuple& what, const ValuesTuple& vals)
{ {
std::vector<std::size_t> mappings; std::vector<size_t> mappings;
return match<MatchRules...>(what, vals, mappings); return match<MatchRules...>(what, vals, mappings);
}
template<typename... MatchRules, template <typename...> class Tuple, typename... TupleTypes>
typename tuple_view_type_from_type_list<typename util::filter_type_list<any_type, util::type_list<MatchRules...>>::type>::type
get_view(const Tuple<TupleTypes...>& t)
{
static_assert(util::a_matches_b<util::type_list<MatchRules...>,
util::type_list<TupleTypes...>>::value,
"MatchRules does not match Tuple");
std::vector<std::size_t> mappings;
util::abstract_type_list::const_iterator begin = t.types().begin();
util::abstract_type_list::const_iterator end = t.types().end();
if (detail::matcher<MatchRules...>::match(begin, end, &mappings))
{
return { t.vals(), std::move(mappings) };
}
throw std::runtime_error("matcher did not return a valid mapping");
}
template<typename... MatchRules>
typename tuple_view_type_from_type_list<typename util::filter_type_list<any_type, util::type_list<MatchRules...>>::type>::type
get_view(const untyped_tuple& t)
{
std::vector<std::size_t> mappings;
if (match<MatchRules...>(t, mappings))
{
return { t.vals(), std::move(mappings) };
}
// todo: throw nicer exception
throw std::runtime_error("doesn't match");
} }
} // namespace cppa } // namespace cppa
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/channel.hpp" #include "cppa/channel.hpp"
#include "cppa/untyped_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/detail/channel.hpp" #include "cppa/detail/channel.hpp"
...@@ -14,32 +15,29 @@ namespace cppa { ...@@ -14,32 +15,29 @@ namespace cppa {
class message class message
{ {
struct content : ref_counted struct msg_content : ref_counted
{ {
const actor_ptr sender; const actor_ptr sender;
const channel_ptr receiver; const channel_ptr receiver;
const untyped_tuple data; const any_tuple data;
inline content(const actor_ptr& s, inline msg_content(const actor_ptr& s,
const channel_ptr& r, const channel_ptr& r,
const untyped_tuple& ut) const any_tuple& ut)
: ref_counted(), sender(s), receiver(r), data(ut) : ref_counted(), sender(s), receiver(r), data(ut)
{ {
} }
}; };
intrusive_ptr<content> m_content; intrusive_ptr<msg_content> m_content;
public: public:
template<typename... Args> template<typename... Args>
message(const actor_ptr& from, const channel_ptr& to, const Args&... args) message(const actor_ptr& from, const channel_ptr& to, const Args&... args);
: m_content(new content(from, to, tuple<Args...>(args...)))
{
}
message(const actor_ptr& from, message(const actor_ptr& from,
const channel_ptr& to, const channel_ptr& to,
const untyped_tuple& ut); const any_tuple& ut);
message(); message();
...@@ -61,13 +59,19 @@ class message ...@@ -61,13 +59,19 @@ class message
return m_content->receiver; return m_content->receiver;
} }
inline const untyped_tuple& data() const inline const any_tuple& content() const
{ {
return m_content->data; return m_content->data;
} }
}; };
template<typename... Args>
message::message(const actor_ptr& from, const channel_ptr& to, const Args&... args)
: m_content(new msg_content(from, to, any_tuple(tuple<Args...>(args...))))
{
}
bool operator==(const message& lhs, const message& rhs); bool operator==(const message& lhs, const message& rhs);
inline bool operator!=(const message& lhs, const message& rhs) inline bool operator!=(const message& lhs, const message& rhs)
......
...@@ -13,9 +13,9 @@ namespace cppa { ...@@ -13,9 +13,9 @@ namespace cppa {
// forward declarations // forward declarations
class object; class object;
class uniform_type_info; class uniform_type_info;
const uniform_type_info* uniform_typeid(const std::type_info&);
namespace detail { template<typename T> struct object_caster; } namespace detail { template<typename T> struct object_caster; }
bool operator==(const uniform_type_info& lhs, const std::type_info& rhs); bool operator==(const uniform_type_info& lhs, const std::type_info& rhs);
/** /**
* @brief foobar. * @brief foobar.
*/ */
...@@ -34,6 +34,9 @@ class object ...@@ -34,6 +34,9 @@ class object
object copy() const; object copy() const;
static void* new_instance(const uniform_type_info* type,
const void* from);
public: public:
/** /**
...@@ -44,21 +47,26 @@ public: ...@@ -44,21 +47,26 @@ public:
object(void* val, const uniform_type_info* utinfo); object(void* val, const uniform_type_info* utinfo);
/** /**
* @brief Create a void object. * @brief Create an empty object.
* @post {@code type() == uniform_typeid<util::void_type>()} * @post {@code empty() && type() == *uniform_typeid<util::void_type>()}
*/ */
object(); object();
template<typename T>
explicit object(const T& what);
~object(); ~object();
/** /**
* @brief Create an object and move type and value from @p other to this. * @brief Creates an object and moves type and value
* from @p other to @c this.
* @post {@code other.type() == uniform_typeid<util::void_type>()} * @post {@code other.type() == uniform_typeid<util::void_type>()}
*/ */
object(object&& other); object(object&& other);
/** /**
* @brief Create a copy of @p other. * @brief Creates a copy of @p other.
* @post {@code type() == other.type() && equal_to(other)}
*/ */
object(const object& other); object(const object& other);
...@@ -70,17 +78,34 @@ public: ...@@ -70,17 +78,34 @@ public:
object& operator=(const object& other); object& operator=(const object& other);
bool equal(const object& other) const; bool equal_to(const object& other) const;
const uniform_type_info& type() const; const uniform_type_info& type() const;
std::string to_string() const; std::string to_string() const;
const void* value() const;
void* mutable_value();
bool empty() const;
}; };
template<typename T>
object::object(const T& what)
{
m_type = uniform_typeid(typeid(T));
if (!m_type)
{
throw std::logic_error("unknown/unannounced type");
}
m_value = new_instance(m_type, &what);
}
inline bool operator==(const object& lhs, const object& rhs) inline bool operator==(const object& lhs, const object& rhs)
{ {
return lhs.equal(rhs); return lhs.equal_to(rhs);
} }
inline bool operator!=(const object& lhs, const object& rhs) inline bool operator!=(const object& lhs, const object& rhs)
...@@ -98,21 +123,6 @@ inline void assert_type(const object& obj, const std::type_info& tinfo) ...@@ -98,21 +123,6 @@ inline void assert_type(const object& obj, const std::type_info& tinfo)
} }
} }
template<typename T>
struct object_caster
{
static T& _(object& obj)
{
assert_type(obj, typeid(T));
return *reinterpret_cast<T*>(obj.m_value);
}
static const T& _(const object& obj)
{
assert_type(obj, typeid(T));
return *reinterpret_cast<const T*>(obj.m_value);
}
};
} // namespace detail } // namespace detail
template<typename T> template<typename T>
...@@ -121,7 +131,8 @@ T& get_ref(object& obj) ...@@ -121,7 +131,8 @@ T& get_ref(object& obj)
static_assert(util::disjunction<std::is_pointer<T>, static_assert(util::disjunction<std::is_pointer<T>,
std::is_reference<T>>::value == false, std::is_reference<T>>::value == false,
"T is a reference or a pointer type."); "T is a reference or a pointer type.");
return detail::object_caster<T>::_(obj); detail::assert_type(obj, typeid(T));
return *reinterpret_cast<T*>(obj.mutable_value());
} }
template<typename T> template<typename T>
...@@ -130,7 +141,8 @@ const T& get(const object& obj) ...@@ -130,7 +141,8 @@ const T& get(const object& obj)
static_assert(util::disjunction<std::is_pointer<T>, static_assert(util::disjunction<std::is_pointer<T>,
std::is_reference<T>>::value == false, std::is_reference<T>>::value == false,
"T is a reference a pointer type."); "T is a reference a pointer type.");
return detail::object_caster<T>::_(obj); detail::assert_type(obj, typeid(T));
return *reinterpret_cast<const T*>(obj.value());
} }
} // namespace cppa } // namespace cppa
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
#define ON_HPP #define ON_HPP
#include "cppa/match.hpp" #include "cppa/match.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/invoke_rules.hpp" #include "cppa/invoke_rules.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/util/eval_first_n.hpp" #include "cppa/util/eval_first_n.hpp"
#include "cppa/util/filter_type_list.hpp" #include "cppa/util/filter_type_list.hpp"
...@@ -13,11 +13,11 @@ ...@@ -13,11 +13,11 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
// irb_helper is not thread safe // irb_helper is not thread safe
struct irb_helper : ref_counted_impl<std::size_t> struct irb_helper : ref_counted_impl<size_t>
{ {
virtual ~irb_helper() { } virtual ~irb_helper() { }
virtual bool value_cmp(const untyped_tuple&, virtual bool value_cmp(const any_tuple&,
std::vector<std::size_t>&) const = 0; std::vector<size_t>&) const = 0;
}; };
template<typename... Types> template<typename... Types>
...@@ -56,8 +56,8 @@ struct invoke_rule_builder ...@@ -56,8 +56,8 @@ struct invoke_rule_builder
{ {
} }
virtual bool value_cmp(const untyped_tuple& t, virtual bool value_cmp(const any_tuple& t,
std::vector<std::size_t>& v) const std::vector<size_t>& v) const
{ {
return match<Types...>(t, m_values, v); return match<Types...>(t, m_values, v);
} }
...@@ -85,9 +85,9 @@ struct invoke_rule_builder ...@@ -85,9 +85,9 @@ struct invoke_rule_builder
}; };
if (!m_helper) if (!m_helper)
{ {
auto inv = [f](const untyped_tuple& t) -> bool auto inv = [f](const any_tuple& t) -> bool
{ {
std::vector<std::size_t> mappings; std::vector<size_t> mappings;
if (match<Types...>(t, mappings)) if (match<Types...>(t, mappings))
{ {
tuple_view_type tv(t.vals(), std::move(mappings)); tuple_view_type tv(t.vals(), std::move(mappings));
...@@ -96,9 +96,9 @@ struct invoke_rule_builder ...@@ -96,9 +96,9 @@ struct invoke_rule_builder
} }
return false; return false;
}; };
auto gt = [sub_inv](const untyped_tuple& t) -> detail::intermediate* auto gt = [sub_inv](const any_tuple& t) -> detail::intermediate*
{ {
std::vector<std::size_t> mappings; std::vector<size_t> mappings;
if (match<Types...>(t, mappings)) if (match<Types...>(t, mappings))
{ {
tuple_view_type tv(t.vals(), std::move(mappings)); tuple_view_type tv(t.vals(), std::move(mappings));
...@@ -110,9 +110,9 @@ struct invoke_rule_builder ...@@ -110,9 +110,9 @@ struct invoke_rule_builder
} }
else else
{ {
auto inv = [f, m_helper](const untyped_tuple& t) -> bool auto inv = [f, m_helper](const any_tuple& t) -> bool
{ {
std::vector<std::size_t> mappings; std::vector<size_t> mappings;
if (m_helper->value_cmp(t, mappings)) if (m_helper->value_cmp(t, mappings))
{ {
tuple_view_type tv(t.vals(), std::move(mappings)); tuple_view_type tv(t.vals(), std::move(mappings));
...@@ -121,9 +121,9 @@ struct invoke_rule_builder ...@@ -121,9 +121,9 @@ struct invoke_rule_builder
} }
return false; return false;
}; };
auto gt = [sub_inv, m_helper](const untyped_tuple& t) -> detail::intermediate* auto gt = [sub_inv, m_helper](const any_tuple& t) -> detail::intermediate*
{ {
std::vector<std::size_t> mappings; std::vector<size_t> mappings;
if (m_helper->value_cmp(t, mappings)) if (m_helper->value_cmp(t, mappings))
{ {
tuple_view_type tv(t.vals(), std::move(mappings)); tuple_view_type tv(t.vals(), std::move(mappings));
......
...@@ -12,7 +12,7 @@ namespace cppa { ...@@ -12,7 +12,7 @@ namespace cppa {
* @brief (Thread safe) base class for reference counted objects * @brief (Thread safe) base class for reference counted objects
* with an atomic reference count. * with an atomic reference count.
*/ */
typedef detail::ref_counted_impl< std::atomic<std::size_t> > ref_counted; typedef detail::ref_counted_impl< std::atomic<size_t> > ref_counted;
} // namespace cppa } // namespace cppa
......
...@@ -63,13 +63,16 @@ struct chars_to_string ...@@ -63,13 +63,16 @@ struct chars_to_string
namespace cppa { namespace cppa {
// forward declaration // forward declaration
class untyped_tuple; class any_tuple;
/**
* @brief Describes a fixed-length tuple.
*/
template<typename... ElementTypes> template<typename... ElementTypes>
class tuple class tuple
{ {
friend class untyped_tuple; friend class any_tuple;
public: public:
...@@ -110,29 +113,29 @@ class tuple ...@@ -110,29 +113,29 @@ class tuple
typedef typename element_types::tail_type tail_type; typedef typename element_types::tail_type tail_type;
static const std::size_t type_list_size = element_types::type_list_size; static const size_t type_list_size = element_types::type_list_size;
tuple() : m_vals(new vals_t) { } tuple() : m_vals(new vals_t) { }
tuple(const ElementTypes&... args) : m_vals(new vals_t(args...)) { } tuple(const ElementTypes&... args) : m_vals(new vals_t(args...)) { }
template<std::size_t N> template<size_t N>
const typename util::type_at<N, element_types>::type& get() const const typename util::type_at<N, element_types>::type& get() const
{ {
return detail::tdata_get<N>(m_vals->data()); return detail::tdata_get<N>(m_vals->data());
} }
template<std::size_t N> template<size_t N>
typename util::type_at<N, element_types>::type& get_ref() typename util::type_at<N, element_types>::type& get_ref()
{ {
return detail::tdata_get_ref<N>(m_vals->data_ref()); return detail::tdata_get_ref<N>(m_vals->data_ref());
} }
std::size_t size() const { return m_vals->size(); } size_t size() const { return m_vals->size(); }
const void* at(std::size_t p) const { return m_vals->at(p); } const void* at(size_t p) const { return m_vals->at(p); }
const uniform_type_info* utype_at(std::size_t p) const { return m_vals->utype_at(p); } const uniform_type_info* utype_at(size_t p) const { return m_vals->type_at(p); }
const util::abstract_type_list& types() const { return m_vals->types(); } const util::abstract_type_list& types() const { return m_vals->types(); }
...@@ -148,14 +151,14 @@ class tuple ...@@ -148,14 +151,14 @@ class tuple
}; };
template<std::size_t N, typename... Types> template<size_t N, typename... Types>
const typename util::type_at<N, util::type_list<Types...>>::type& const typename util::type_at<N, util::type_list<Types...>>::type&
get(const tuple<Types...>& t) get(const tuple<Types...>& t)
{ {
return t.get<N>(); return t.get<N>();
} }
template<std::size_t N, typename... Types> template<size_t N, typename... Types>
typename util::type_at<N, util::type_list<Types...>>::type& typename util::type_at<N, util::type_list<Types...>>::type&
get_ref(tuple<Types...>& t) get_ref(tuple<Types...>& t)
{ {
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include <vector> #include <vector>
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/a_matches_b.hpp" #include "cppa/util/a_matches_b.hpp"
...@@ -14,71 +13,83 @@ ...@@ -14,71 +13,83 @@
namespace cppa { namespace cppa {
// forward declaration
class any_tuple;
// needed to implement constructor
const cow_ptr<detail::abstract_tuple>& vals_of(const any_tuple&);
/**
* @brief Describes a view of an fixed-length tuple.
*/
template<typename... ElementTypes> template<typename... ElementTypes>
class tuple_view class tuple_view
{ {
public: public:
typedef util::type_list<ElementTypes...> element_types; typedef util::type_list<ElementTypes...> element_types;
static_assert(element_types::type_list_size > 0,
"could not declare an empty tuple_view");
static_assert(element_types::type_list_size > 0, typedef cow_ptr<detail::abstract_tuple> vals_t;
"could not declare an empty tuple_view");
typedef cow_ptr<detail::abstract_tuple> vals_t; tuple_view(const vals_t& vals, std::vector<size_t>&& mappings)
: m_vals(new detail::decorated_tuple<ElementTypes...>(vals, mappings))
{
}
tuple_view(const vals_t& vals, std::vector<std::size_t>&& mappings) tuple_view(const tuple_view&) = default;
: m_vals(new detail::decorated_tuple<ElementTypes...>(vals, mappings))
{
}
tuple_view(const tuple_view&) = default; tuple_view(tuple_view&& other) : m_vals(std::move(other.m_vals))
{
}
const vals_t& vals() const { return m_vals; } const vals_t& vals() const { return m_vals; }
typedef typename element_types::head_type head_type; typedef typename element_types::head_type head_type;
typedef typename element_types::tail_type tail_type; typedef typename element_types::tail_type tail_type;
static const std::size_t type_list_size = element_types::type_list_size; static const size_t type_list_size = element_types::type_list_size;
const element_types& types() const { return m_types; } const element_types& types() const { return m_types; }
template<std::size_t N> template<size_t N>
const typename util::type_at<N, element_types>::type& get() const const typename util::type_at<N, element_types>::type& get() const
{ {
static_assert(N < element_types::type_list_size, "N >= size()"); static_assert(N < element_types::type_list_size, "N >= size()");
return *reinterpret_cast<const typename util::type_at<N, element_types>::type*>(m_vals->at(N)); return *reinterpret_cast<const typename util::type_at<N, element_types>::type*>(m_vals->at(N));
} }
template<std::size_t N> template<size_t N>
typename util::type_at<N, element_types>::type& get_ref() typename util::type_at<N, element_types>::type& get_ref()
{ {
static_assert(N < element_types::type_list_size, "N >= size()"); static_assert(N < element_types::type_list_size, "N >= size()");
return *reinterpret_cast<typename util::type_at<N, element_types>::type*>(m_vals->mutable_at(N)); return *reinterpret_cast<typename util::type_at<N, element_types>::type*>(m_vals->mutable_at(N));
} }
std::size_t size() const { return m_vals->size(); } size_t size() const { return m_vals->size(); }
private: private:
vals_t m_vals; vals_t m_vals;
element_types m_types; element_types m_types;
}; };
template<std::size_t N, typename... Types> template<size_t N, typename... Types>
const typename util::type_at<N, util::type_list<Types...>>::type& const typename util::type_at<N, util::type_list<Types...>>::type&
get(const tuple_view<Types...>& t) get(const tuple_view<Types...>& t)
{ {
return t.get<N>(); return t.get<N>();
} }
template<std::size_t N, typename... Types> template<size_t N, typename... Types>
typename util::type_at<N, util::type_list<Types...>>::type& typename util::type_at<N, util::type_list<Types...>>::type&
get_ref(tuple_view<Types...>& t) get_ref(tuple_view<Types...>& t)
{ {
return t.get_ref<N>(); return t.get_ref<N>();
} }
template<typename TypeList> template<typename TypeList>
...@@ -87,49 +98,49 @@ struct tuple_view_type_from_type_list; ...@@ -87,49 +98,49 @@ struct tuple_view_type_from_type_list;
template<typename... Types> template<typename... Types>
struct tuple_view_type_from_type_list<util::type_list<Types...>> struct tuple_view_type_from_type_list<util::type_list<Types...>>
{ {
typedef tuple_view<Types...> type; typedef tuple_view<Types...> type;
}; };
template<typename... LhsTypes, typename... RhsTypes> template<typename... LhsTypes, typename... RhsTypes>
inline bool operator==(const tuple_view<LhsTypes...>& lhs, inline bool operator==(const tuple_view<LhsTypes...>& lhs,
const tuple_view<RhsTypes...>& rhs) const tuple_view<RhsTypes...>& rhs)
{ {
return util::compare_tuples(lhs, rhs); return util::compare_tuples(lhs, rhs);
} }
template<typename... LhsTypes, typename... RhsTypes> template<typename... LhsTypes, typename... RhsTypes>
inline bool operator==(const tuple<LhsTypes...>& lhs, inline bool operator==(const tuple<LhsTypes...>& lhs,
const tuple_view<RhsTypes...>& rhs) const tuple_view<RhsTypes...>& rhs)
{ {
return util::compare_tuples(lhs, rhs); return util::compare_tuples(lhs, rhs);
} }
template<typename... LhsTypes, typename... RhsTypes> template<typename... LhsTypes, typename... RhsTypes>
inline bool operator==(const tuple_view<LhsTypes...>& lhs, inline bool operator==(const tuple_view<LhsTypes...>& lhs,
const tuple<RhsTypes...>& rhs) const tuple<RhsTypes...>& rhs)
{ {
return util::compare_tuples(lhs, rhs); return util::compare_tuples(lhs, rhs);
} }
template<typename... LhsTypes, typename... RhsTypes> template<typename... LhsTypes, typename... RhsTypes>
inline bool operator!=(const tuple_view<LhsTypes...>& lhs, inline bool operator!=(const tuple_view<LhsTypes...>& lhs,
const tuple_view<RhsTypes...>& rhs) const tuple_view<RhsTypes...>& rhs)
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
template<typename... LhsTypes, typename... RhsTypes> template<typename... LhsTypes, typename... RhsTypes>
inline bool operator!=(const tuple<LhsTypes...>& lhs, inline bool operator!=(const tuple<LhsTypes...>& lhs,
const tuple_view<RhsTypes...>& rhs) const tuple_view<RhsTypes...>& rhs)
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
template<typename... LhsTypes, typename... RhsTypes> template<typename... LhsTypes, typename... RhsTypes>
inline bool operator!=(const tuple_view<LhsTypes...>& lhs, inline bool operator!=(const tuple_view<LhsTypes...>& lhs,
const tuple<RhsTypes...>& rhs) const tuple<RhsTypes...>& rhs)
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
} // namespace cppa } // namespace cppa
......
...@@ -146,13 +146,18 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info> ...@@ -146,13 +146,18 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
*/ */
object deserialize(deserializer* source) const; object deserialize(deserializer* source) const;
protected:
/** /**
* @brief Compares two instances of this type. * @brief Compares two instances of this type.
*/ */
virtual bool equal(const void* instance1, const void* instance2) const = 0; virtual bool equal(const void* instance1, const void* instance2) const = 0;
protected:
/**
* @brief Cast @p instance to the native type and delete it.
*/
virtual void delete_instance(void* instance) const = 0;
/** /**
* @brief Creates an instance of this type, either as a copy of * @brief Creates an instance of this type, either as a copy of
* @p instance or initialized with the default constructor * @p instance or initialized with the default constructor
...@@ -160,11 +165,6 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info> ...@@ -160,11 +165,6 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
*/ */
virtual void* new_instance(const void* instance = nullptr) const = 0; virtual void* new_instance(const void* instance = nullptr) const = 0;
/**
* @brief Cast @p instance to the native type and delete it.
*/
virtual void delete_instance(void* instance) const = 0;
public: public:
/** /**
......
#ifndef UNTYPED_TUPLE_HPP
#define UNTYPED_TUPLE_HPP
#include "cppa/cow_ptr.hpp"
#include "cppa/detail/abstract_tuple.hpp"
namespace cppa {
class untyped_tuple
{
cow_ptr<detail::abstract_tuple> m_vals;
public:
untyped_tuple();
template<typename Tuple>
untyped_tuple(const Tuple& t) : m_vals(t.vals()) { }
inline untyped_tuple(const cow_ptr<detail::abstract_tuple>& vals)
: m_vals(vals)
{
}
std::size_t size() const { return m_vals->size(); }
void* mutable_at(size_t p) { return m_vals->mutable_at(p); }
const void* at(size_t p) const { return m_vals->at(p); }
const uniform_type_info* utype_at(std::size_t p) const { return m_vals->utype_at(p); }
const util::abstract_type_list& types() const { return m_vals->types(); }
const cow_ptr<detail::abstract_tuple>& vals() const
{
return m_vals;
}
};
} // namespace cppa
#endif // UNTYPED_TUPLE_HPP
#ifndef ABSTRACT_TYPE_LIST_HPP #ifndef ABSTRACT_TYPE_LIST_HPP
#define ABSTRACT_TYPE_LIST_HPP #define ABSTRACT_TYPE_LIST_HPP
#include <iterator> #include <memory>
// forward declaration // forward declaration
namespace cppa { class uniform_type_info; } namespace cppa { class uniform_type_info; }
...@@ -11,67 +11,101 @@ namespace cppa { namespace util { ...@@ -11,67 +11,101 @@ namespace cppa { namespace util {
struct abstract_type_list struct abstract_type_list
{ {
class const_iterator : public std::iterator<std::bidirectional_iterator_tag, class abstract_iterator
const uniform_type_info*>
{ {
const uniform_type_info* const* p; public:
virtual ~abstract_iterator();
/**
* @brief
* @return @c false if the iterator is at the end; otherwise @c true.
*/
virtual bool next() = 0;
virtual const uniform_type_info& get() const = 0;
virtual abstract_iterator* copy() const = 0;
};
class const_iterator
{
abstract_iterator* m_iter;
public: public:
inline const_iterator(const uniform_type_info* const* x = 0) : p(x) { } const_iterator(abstract_iterator* x = 0) : m_iter(x) { }
const_iterator(const const_iterator&) = default; const_iterator(const const_iterator& other)
: m_iter((other.m_iter) ? other.m_iter->copy() : nullptr)
{
}
const_iterator& operator=(const const_iterator&) = default; const_iterator(const_iterator&& other) : m_iter(other.m_iter)
{
other.m_iter = nullptr;
}
inline bool operator==(const const_iterator& other) const const_iterator& operator=(const const_iterator& other)
{ {
return p == other.p; delete m_iter;
m_iter = (other.m_iter) ? other.m_iter->copy() : nullptr;
return *this;
} }
inline bool operator!=(const const_iterator& other) const const_iterator& operator=(const_iterator&& other)
{ {
return p != other.p; delete m_iter;
m_iter = other.m_iter;
other.m_iter = nullptr;
return *this;
} }
inline const uniform_type_info& operator*() const ~const_iterator()
{ {
return *(*p); delete m_iter;
} }
inline const uniform_type_info* operator->() const bool operator==(const const_iterator& other) const
{ {
return *p; return m_iter == other.m_iter;
} }
inline const_iterator& operator++() inline bool operator!=(const const_iterator& other) const
{ {
++p; return !(*this == other);
return *this;
} }
const_iterator operator++(int); const uniform_type_info& operator*() const
{
return m_iter->get();
}
inline const_iterator& operator--() const uniform_type_info* operator->() const
{ {
--p; return &(m_iter->get());
return *this;
} }
const_iterator operator--(int); const_iterator& operator++()
{
if (!m_iter->next())
{
delete m_iter;
m_iter = nullptr;
}
return *this;
}
}; };
virtual ~abstract_type_list(); virtual ~abstract_type_list();
virtual abstract_type_list* copy() const = 0;
virtual const_iterator begin() const = 0; virtual const_iterator begin() const = 0;
virtual const_iterator end() const = 0; virtual const_iterator end() const;
virtual const uniform_type_info* at(std::size_t pos) const = 0;
}; };
......
#ifndef UNIFORM_TYPE_INFO_BASE_HPP #ifndef ABSTRACT_UNIFORM_TYPE_INFO_HPP
#define UNIFORM_TYPE_INFO_BASE_HPP #define ABSTRACT_UNIFORM_TYPE_INFO_HPP
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
#include "cppa/detail/to_uniform_name.hpp" #include "cppa/detail/to_uniform_name.hpp"
...@@ -11,7 +11,7 @@ namespace cppa { namespace util { ...@@ -11,7 +11,7 @@ namespace cppa { namespace util {
* except serialize() and deserialize(). * except serialize() and deserialize().
*/ */
template<typename T> template<typename T>
class uniform_type_info_base : public uniform_type_info class abstract_uniform_type_info : public uniform_type_info
{ {
inline static const T& deref(const void* ptr) inline static const T& deref(const void* ptr)
...@@ -26,7 +26,7 @@ class uniform_type_info_base : public uniform_type_info ...@@ -26,7 +26,7 @@ class uniform_type_info_base : public uniform_type_info
protected: protected:
uniform_type_info_base(const std::string& uname abstract_uniform_type_info(const std::string& uname
= detail::to_uniform_name(typeid(T))) = detail::to_uniform_name(typeid(T)))
: uniform_type_info(uname) : uniform_type_info(uname)
{ {
...@@ -58,4 +58,4 @@ class uniform_type_info_base : public uniform_type_info ...@@ -58,4 +58,4 @@ class uniform_type_info_base : public uniform_type_info
} } } }
#endif // UNIFORM_TYPE_INFO_BASE_HPP #endif // ABSTRACT_UNIFORM_TYPE_INFO_HPP
...@@ -9,14 +9,14 @@ ...@@ -9,14 +9,14 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<std::size_t N, template<typename...> class Tuple, typename... Types> template<size_t N, template<typename...> class Tuple, typename... Types>
const typename util::type_at<N, util::type_list<Types...>>::type& const typename util::type_at<N, util::type_list<Types...>>::type&
do_get(const Tuple<Types...>& t) do_get(const Tuple<Types...>& t)
{ {
return ::cppa::get<N, Types...>(t); return ::cppa::get<N, Types...>(t);
} }
template<std::size_t N, typename LhsTuple, typename RhsTuple> template<size_t N, typename LhsTuple, typename RhsTuple>
struct cmp_helper struct cmp_helper
{ {
inline static bool cmp(const LhsTuple& lhs, const RhsTuple& rhs) inline static bool cmp(const LhsTuple& lhs, const RhsTuple& rhs)
...@@ -35,22 +35,22 @@ struct cmp_helper<0, LhsTuple, RhsTuple> ...@@ -35,22 +35,22 @@ struct cmp_helper<0, LhsTuple, RhsTuple>
} }
}; };
template<bool ALessB, std::size_t A, std::size_t B> template<bool ALessB, size_t A, size_t B>
struct min_impl struct min_impl
{ {
static const std::size_t value = A; static const size_t value = A;
}; };
template<std::size_t A, std::size_t B> template<size_t A, size_t B>
struct min_impl<false, A, B> struct min_impl<false, A, B>
{ {
static const std::size_t value = B; static const size_t value = B;
}; };
template<std::size_t A, std::size_t B> template<size_t A, size_t B>
struct min_ struct min_
{ {
static const std::size_t value = min_impl<(A < B), A, B>::value; static const size_t value = min_impl<(A < B), A, B>::value;
}; };
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -9,12 +9,12 @@ ...@@ -9,12 +9,12 @@
namespace cppa { namespace util { namespace cppa { namespace util {
template <std::size_t N, template <size_t N,
class ListA, class ListB, class ListA, class ListB,
template <typename, typename> class What> template <typename, typename> class What>
struct eval_first_n; struct eval_first_n;
template <std::size_t N, typename... TypesA, typename... TypesB, template <size_t N, typename... TypesA, typename... TypesB,
template <typename, typename> class What> template <typename, typename> class What>
struct eval_first_n<N, type_list<TypesA...>, type_list<TypesB...>, What> struct eval_first_n<N, type_list<TypesA...>, type_list<TypesB...>, What>
{ {
......
...@@ -22,7 +22,7 @@ struct if_t<true, IfType, ElseType> ...@@ -22,7 +22,7 @@ struct if_t<true, IfType, ElseType>
typedef IfType type; typedef IfType type;
}; };
template<std::size_t N, typename List> template<size_t N, typename List>
struct n_ struct n_
{ {
...@@ -48,10 +48,10 @@ struct n_<0, List> ...@@ -48,10 +48,10 @@ struct n_<0, List>
namespace cppa { namespace util { namespace cppa { namespace util {
template<std::size_t N, typename List> template<size_t N, typename List>
struct first_n; struct first_n;
template<std::size_t N, typename... ListTypes> template<size_t N, typename... ListTypes>
struct first_n<N, util::type_list<ListTypes...>> struct first_n<N, util::type_list<ListTypes...>>
{ {
typedef typename detail::n_<N, util::type_list<ListTypes...>>::type type; typedef typename detail::n_<N, util::type_list<ListTypes...>>::type type;
......
#ifndef CPPA_UTIL_TYPE_AT_HPP #ifndef CPPA_UTIL_TYPE_AT_HPP
#define CPPA_UTIL_TYPE_AT_HPP #define CPPA_UTIL_TYPE_AT_HPP
// std::size_t // size_t
#include <cstddef> #include <cstddef>
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
namespace cppa { namespace util { namespace cppa { namespace util {
template<std::size_t N, typename TypeList> template<size_t N, typename TypeList>
struct type_at struct type_at
{ {
typedef typename type_at<N-1, typename TypeList::tail_type>::type type; typedef typename type_at<N-1, typename TypeList::tail_type>::type type;
......
...@@ -17,6 +17,41 @@ const uniform_type_info* uniform_typeid(const std::type_info&); ...@@ -17,6 +17,41 @@ const uniform_type_info* uniform_typeid(const std::type_info&);
namespace cppa { namespace util { namespace cppa { namespace util {
class type_list_iterator : public abstract_type_list::abstract_iterator
{
public:
typedef const uniform_type_info* const* ptr_type;
type_list_iterator(ptr_type begin, ptr_type end) : m_pos(begin), m_end(end)
{
}
type_list_iterator(const type_list_iterator&) = default;
bool next()
{
return ++m_pos != m_end;
}
const uniform_type_info& get() const
{
return *(*m_pos);
}
abstract_type_list::abstract_iterator* copy() const
{
return new type_list_iterator(*this);
}
private:
const uniform_type_info* const* m_pos;
const uniform_type_info* const* m_end;
};
template<typename... Types> struct type_list; template<typename... Types> struct type_list;
template<> template<>
...@@ -24,7 +59,7 @@ struct type_list<> ...@@ -24,7 +59,7 @@ struct type_list<>
{ {
typedef void_type head_type; typedef void_type head_type;
typedef type_list<> tail_type; typedef type_list<> tail_type;
static const std::size_t type_list_size = 0; static const size_t type_list_size = 0;
}; };
template<typename Head, typename... Tail> template<typename Head, typename... Tail>
...@@ -35,7 +70,7 @@ struct type_list<Head, Tail...> : abstract_type_list ...@@ -35,7 +70,7 @@ struct type_list<Head, Tail...> : abstract_type_list
typedef type_list<Tail...> tail_type; typedef type_list<Tail...> tail_type;
static const std::size_t type_list_size = tail_type::type_list_size + 1; static const size_t type_list_size = tail_type::type_list_size + 1;
type_list() type_list()
{ {
...@@ -44,17 +79,12 @@ struct type_list<Head, Tail...> : abstract_type_list ...@@ -44,17 +79,12 @@ struct type_list<Head, Tail...> : abstract_type_list
virtual const_iterator begin() const virtual const_iterator begin() const
{ {
return m_arr; return new type_list_iterator(m_arr, m_arr + type_list_size);
}
virtual const_iterator end() const
{
return m_arr + type_list_size;
} }
virtual const uniform_type_info* at(std::size_t pos) const virtual const uniform_type_info& at(size_t pos) const
{ {
return m_arr[pos]; return *m_arr[pos];
} }
virtual type_list* copy() const virtual type_list* copy() const
......
#!/bin/bash
HEADERS=""
SOURCES=""
NLINE="\\n"
BSLASH="\\\\"
function append_hpp_from()
{
for i in "$1"/*.hpp ; do
HEADERS="$HEADERS ${BSLASH}${NLINE} $i"
done
}
function append_cpp_from()
{
for i in "$1/"*.cpp ; do
SOURCES="$SOURCES ${BSLASH}${NLINE} $i"
done
}
append_hpp_from "cppa"
append_hpp_from "cppa/detail"
append_hpp_from "cppa/util"
append_cpp_from "src"
echo "include Makefile.rules"
echo "INCLUDES = -I./"
echo
printf "%b\n" "HEADERS =$HEADERS"
echo
printf "%b\n" "SOURCES =$SOURCES"
echo
echo "OBJECTS = \$(SOURCES:.cpp=.o)"
echo
echo "LIB_NAME = libcppa.dylib"
echo
echo "%.o : %.cpp \$(HEADERS)"
printf "%b\n" "\t\$(CXX) \$(CXXFLAGS) \$(INCLUDES) -fPIC -c \$< -o \$@"
echo
echo "\$(LIB_NAME) : \$(OBJECTS) \$(HEADERS)"
printf "%b\n" "\t\$(CXX) \$(LIBS) -dynamiclib -o \$(LIB_NAME) \$(OBJECTS)"
echo
echo "all : \$(LIB_NAME) \$(OBJECTS)"
echo
echo "clean:"
printf "%b\n" "\trm -f \$(LIB_NAME) \$(OBJECTS)"
include Makefile.rules include Makefile.rules
INCLUDES = -I./ INCLUDES = -I./
#CXXFLAGS = -std=c++0x -pedantic -Wall -Wextra -O2 -I/opt/local/include/ -fPIC HEADERS = \
cppa/actor.hpp \
HEADERS = cppa/actor.hpp \ cppa/actor_behavior.hpp \
cppa/any_type.hpp \ cppa/announce.hpp \
cppa/binary_deserializer.hpp \ cppa/any_tuple.hpp \
cppa/binary_serializer.hpp \ cppa/any_type.hpp \
cppa/channel.hpp \ cppa/binary_deserializer.hpp \
cppa/config.hpp \ cppa/binary_serializer.hpp \
cppa/context.hpp \ cppa/channel.hpp \
cppa/cow_ptr.hpp \ cppa/config.hpp \
cppa/cppa.hpp \ cppa/context.hpp \
cppa/deserializer.hpp \ cppa/cow_ptr.hpp \
cppa/get.hpp \ cppa/cppa.hpp \
cppa/group.hpp \ cppa/deserializer.hpp \
cppa/intrusive_ptr.hpp \ cppa/get.hpp \
cppa/invoke.hpp \ cppa/get_view.hpp \
cppa/invoke_rules.hpp \ cppa/group.hpp \
cppa/match.hpp \ cppa/intrusive_ptr.hpp \
cppa/message.hpp \ cppa/invoke.hpp \
cppa/message_queue.hpp \ cppa/invoke_rules.hpp \
cppa/object.hpp \ cppa/match.hpp \
cppa/on.hpp \ cppa/message.hpp \
cppa/primitive_type.hpp \ cppa/message_queue.hpp \
cppa/primitive_variant.hpp \ cppa/object.hpp \
cppa/ref_counted.hpp \ cppa/on.hpp \
cppa/scheduler.hpp \ cppa/primitive_type.hpp \
cppa/scheduling_hint.hpp \ cppa/primitive_variant.hpp \
cppa/serializer.hpp \ cppa/ref_counted.hpp \
cppa/tuple.hpp \ cppa/scheduler.hpp \
cppa/tuple_view.hpp \ cppa/scheduling_hint.hpp \
cppa/uniform_type_info.hpp \ cppa/serializer.hpp \
cppa/untyped_tuple.hpp \ cppa/tuple.hpp \
cppa/util.hpp \ cppa/tuple_view.hpp \
cppa/detail/abstract_tuple.hpp \ cppa/uniform_type_info.hpp \
cppa/detail/blocking_message_queue.hpp \ cppa/util.hpp \
cppa/detail/converted_thread_context.hpp \ cppa/detail/abstract_tuple.hpp \
cppa/detail/decorated_tuple.hpp \ cppa/detail/blocking_message_queue.hpp \
cppa/detail/channel.hpp \ cppa/detail/channel.hpp \
cppa/detail/intermediate.hpp \ cppa/detail/converted_thread_context.hpp \
cppa/detail/invokable.hpp \ cppa/detail/cpp0x_thread_wrapper.hpp \
cppa/detail/matcher.hpp \ cppa/detail/decorated_tuple.hpp \
cppa/detail/ref_counted_impl.hpp \ cppa/detail/default_uniform_type_info_impl.hpp \
cppa/detail/tdata.hpp \ cppa/detail/demangle.hpp \
cppa/detail/tuple_vals.hpp \ cppa/detail/intermediate.hpp \
cppa/util/a_matches_b.hpp \ cppa/detail/invokable.hpp \
cppa/util/callable_trait.hpp \ cppa/detail/list_member.hpp \
cppa/util/compare_tuples.hpp \ cppa/detail/map_member.hpp \
cppa/util/concat_type_lists.hpp \ cppa/detail/matcher.hpp \
cppa/util/conjunction.hpp \ cppa/detail/mock_scheduler.hpp \
cppa/util/detach.hpp \ cppa/detail/object_array.hpp \
cppa/util/disjunction.hpp \ cppa/detail/object_impl.hpp \
cppa/util/eval_type_lists.hpp \ cppa/detail/pair_member.hpp \
cppa/util/filter_type_list.hpp \ cppa/detail/primitive_member.hpp \
cppa/util/has_copy_member_fun.hpp \ cppa/detail/ptype_to_type.hpp \
cppa/util/is_comparable.hpp \ cppa/detail/ref_counted_impl.hpp \
cppa/util/is_copyable.hpp \ cppa/detail/serialize_tuple.hpp \
cppa/util/is_one_of.hpp \ cppa/detail/swap_bytes.hpp \
cppa/util/is_primitive.hpp \ cppa/detail/tdata.hpp \
cppa/util/pt_token.hpp \ cppa/detail/to_uniform_name.hpp \
cppa/util/remove_const_reference.hpp \ cppa/detail/tuple_vals.hpp \
cppa/util/replace_type.hpp \ cppa/detail/type_to_ptype.hpp \
cppa/util/reverse_type_list.hpp \ cppa/util/a_matches_b.hpp \
cppa/util/rm_ref.hpp \ cppa/util/abstract_type_list.hpp \
cppa/util/shared_spinlock.hpp \ cppa/util/abstract_uniform_type_info.hpp \
cppa/util/single_reader_queue.hpp \ cppa/util/apply.hpp \
cppa/util/type_at.hpp \ cppa/util/callable_trait.hpp \
cppa/util/type_list.hpp \ cppa/util/comparable.hpp \
cppa/util/type_list_apply.hpp \ cppa/util/compare_tuples.hpp \
cppa/util/type_list_pop_back.hpp \ cppa/util/concat_type_lists.hpp \
cppa/util/void_type.hpp cppa/util/conjunction.hpp \
cppa/util/detach.hpp \
cppa/util/disable_if.hpp \
cppa/util/disjunction.hpp \
cppa/util/enable_if.hpp \
cppa/util/eval_first_n.hpp \
cppa/util/eval_type_list.hpp \
cppa/util/eval_type_lists.hpp \
cppa/util/filter_type_list.hpp \
cppa/util/first_n.hpp \
cppa/util/has_copy_member_fun.hpp \
cppa/util/if_else_type.hpp \
cppa/util/is_comparable.hpp \
cppa/util/is_copyable.hpp \
cppa/util/is_forward_iterator.hpp \
cppa/util/is_iterable.hpp \
cppa/util/is_legal_tuple_type.hpp \
cppa/util/is_one_of.hpp \
cppa/util/is_primitive.hpp \
cppa/util/pt_token.hpp \
cppa/util/remove_const_reference.hpp \
cppa/util/replace_type.hpp \
cppa/util/reverse_type_list.hpp \
cppa/util/rm_ref.hpp \
cppa/util/shared_lock_guard.hpp \
cppa/util/shared_spinlock.hpp \
cppa/util/single_reader_queue.hpp \
cppa/util/singly_linked_list.hpp \
cppa/util/type_at.hpp \
cppa/util/type_list.hpp \
cppa/util/type_list_apply.hpp \
cppa/util/type_list_pop_back.hpp \
cppa/util/void_type.hpp \
cppa/util/wrapped_type.hpp
SOURCES = src/abstract_type_list.cpp \ SOURCES = \
src/actor.cpp \ src/abstract_type_list.cpp \
src/actor_behavior.cpp \ src/actor.cpp \
src/binary_deserializer.cpp \ src/actor_behavior.cpp \
src/binary_serializer.cpp \ src/any_tuple.cpp \
src/blocking_message_queue.cpp \ src/binary_deserializer.cpp \
src/channel.cpp \ src/binary_serializer.cpp \
src/context.cpp \ src/blocking_message_queue.cpp \
src/converted_thread_context.cpp \ src/channel.cpp \
src/demangle.cpp \ src/context.cpp \
src/deserializer.cpp \ src/converted_thread_context.cpp \
src/group.cpp \ src/demangle.cpp \
src/message.cpp \ src/deserializer.cpp \
src/mock_scheduler.cpp \ src/group.cpp \
src/object.cpp \ src/message.cpp \
src/primitive_variant.cpp \ src/mock_scheduler.cpp \
src/scheduler.cpp \ src/object.cpp \
src/serializer.cpp \ src/object_array.cpp \
src/shared_spinlock.cpp \ src/primitive_variant.cpp \
src/to_uniform_name.cpp \ src/scheduler.cpp \
src/uniform_type_info.cpp \ src/serializer.cpp \
src/untyped_tuple.cpp src/shared_spinlock.cpp \
src/to_uniform_name.cpp \
src/uniform_type_info.cpp
OBJECTS = $(SOURCES:.cpp=.o) OBJECTS = $(SOURCES:.cpp=.o)
...@@ -110,4 +144,3 @@ all : $(LIB_NAME) $(OBJECTS) ...@@ -110,4 +144,3 @@ all : $(LIB_NAME) $(OBJECTS)
clean: clean:
rm -f $(LIB_NAME) $(OBJECTS) rm -f $(LIB_NAME) $(OBJECTS)
...@@ -6,20 +6,13 @@ abstract_type_list::~abstract_type_list() ...@@ -6,20 +6,13 @@ abstract_type_list::~abstract_type_list()
{ {
} }
abstract_type_list::const_iterator abstract_type_list::const_iterator abstract_type_list::end() const
abstract_type_list::const_iterator::operator++(int)
{ {
const_iterator tmp(*this); return const_iterator(nullptr);
operator++();
return tmp;
} }
abstract_type_list::const_iterator abstract_type_list::abstract_iterator::~abstract_iterator()
abstract_type_list::const_iterator::operator--(int)
{ {
const_iterator tmp(*this);
operator--();
return tmp;
} }
} } // namespace cppa::util } } // namespace cppa::util
#include "cppa/any_tuple.hpp"
namespace {
struct empty_type_list : cppa::util::abstract_type_list
{
virtual abstract_type_list* copy() const
{
return new empty_type_list;
}
virtual const_iterator begin() const
{
return 0;
}
virtual const cppa::uniform_type_info* at(size_t) const
{
throw std::range_error("empty_type_list::at()");
}
};
struct empty_tuple : cppa::detail::abstract_tuple
{
empty_type_list m_types;
virtual size_t size() const
{
return 0;
}
virtual abstract_tuple* copy() const
{
return new empty_tuple;
}
virtual void* mutable_at(size_t)
{
throw std::range_error("empty_tuple::mutable_at()");
}
virtual const void* at(size_t) const
{
throw std::range_error("empty_tuple::at()");
}
virtual const cppa::uniform_type_info& type_at(size_t) const
{
throw std::range_error("empty_tuple::type_at()");
}
virtual const cppa::util::abstract_type_list& types() const
{
return m_types;
}
virtual bool equal_to(const abstract_tuple& other) const
{
return other.size() == 0;
}
virtual void serialize(cppa::serializer&) const
{
}
};
} // namespace <anonymous>
namespace cppa {
any_tuple::any_tuple() : m_vals(new empty_tuple)
{
}
any_tuple::any_tuple(const vals_ptr& vals) : m_vals(vals)
{
}
any_tuple::any_tuple(vals_ptr&& vals) : m_vals(std::move(vals))
{
}
any_tuple::any_tuple(any_tuple&& other) : m_vals(std::move(other.m_vals))
{
}
any_tuple& any_tuple::operator=(any_tuple&& other)
{
m_vals = std::move(other.m_vals);
return *this;
}
size_t any_tuple::size() const
{
return m_vals->size();
}
void* any_tuple::mutable_at(size_t p)
{
return m_vals->mutable_at(p);
}
const void* any_tuple::at(size_t p) const
{
return m_vals->at(p);
}
const uniform_type_info& any_tuple::type_at(size_t p) const
{
return m_vals->type_at(p);
}
const util::abstract_type_list& any_tuple::types() const
{
return m_vals->types();
}
const cow_ptr<detail::abstract_tuple>& any_tuple::vals() const
{
return m_vals;
}
bool any_tuple::equal_to(const any_tuple& other) const
{
return m_vals->equal_to(*other.vals());
}
} // namespace cppa
...@@ -25,7 +25,7 @@ void blocking_message_queue::dequeue(invoke_rules& rules) ...@@ -25,7 +25,7 @@ void blocking_message_queue::dequeue(invoke_rules& rules)
queue_node* amsg = m_queue.pop(); queue_node* amsg = m_queue.pop();
util::singly_linked_list<queue_node> buffer; util::singly_linked_list<queue_node> buffer;
intrusive_ptr<detail::intermediate> imd; intrusive_ptr<detail::intermediate> imd;
while (!(imd = rules.get_intermediate(amsg->msg.data()))) while (!(imd = rules.get_intermediate(amsg->msg.content())))
{ {
buffer.push_back(amsg); buffer.push_back(amsg);
amsg = m_queue.pop(); amsg = m_queue.pop();
......
...@@ -4,61 +4,62 @@ namespace cppa { namespace detail { ...@@ -4,61 +4,62 @@ namespace cppa { namespace detail {
void converted_thread_context::link(intrusive_ptr<actor>& other) void converted_thread_context::link(intrusive_ptr<actor>& other)
{ {
std::lock_guard<std::mutex> guard(m_mtx); std::lock_guard<std::mutex> guard(m_mtx);
if (other && !m_exited && other->establish_backlink(this)) if (other && !m_exited && other->establish_backlink(this))
{ {
m_links.insert(other); m_links.insert(other);
} }
} }
bool converted_thread_context::remove_backlink(const intrusive_ptr<actor>& other) bool converted_thread_context::remove_backlink(const intrusive_ptr<actor>& other)
{ {
if (other && other != this) if (other && other != this)
{ {
std::lock_guard<std::mutex> guard(m_mtx); std::lock_guard<std::mutex> guard(m_mtx);
return m_links.erase(other) > 0; return m_links.erase(other) > 0;
} }
return false; return false;
} }
bool converted_thread_context::establish_backlink(const intrusive_ptr<actor>& other) bool converted_thread_context::establish_backlink(const intrusive_ptr<actor>& other)
{ {
if (other && other != this) if (other && other != this)
{ {
std::lock_guard<std::mutex> guard(m_mtx); std::lock_guard<std::mutex> guard(m_mtx);
return m_links.insert(other).second; return m_links.insert(other).second;
} }
return false; return false;
} }
void converted_thread_context::unlink(intrusive_ptr<actor>& other) void converted_thread_context::unlink(intrusive_ptr<actor>& other)
{ {
std::lock_guard<std::mutex> guard(m_mtx); std::lock_guard<std::mutex> guard(m_mtx);
if (other && !m_exited && other->remove_backlink(this)) if (other && !m_exited && other->remove_backlink(this))
{ {
m_links.erase(other); m_links.erase(other);
} }
} }
void converted_thread_context::join(group_ptr& what) void converted_thread_context::join(group_ptr& what)
{ {
std::lock_guard<std::mutex> guard(m_mtx); std::lock_guard<std::mutex> guard(m_mtx);
if (!m_exited && m_subscriptions.count(what) == 0) if (!m_exited && m_subscriptions.count(what) == 0)
{ {
m_subscriptions[what] = what->subscribe(this); m_subscriptions.insert(std::make_pair(what, what->subscribe(this)));
} //m_subscriptions[what] = what->subscribe(this);
}
} }
void converted_thread_context::leave(const group_ptr& what) void converted_thread_context::leave(const group_ptr& what)
{ {
std::lock_guard<std::mutex> guard(m_mtx); std::lock_guard<std::mutex> guard(m_mtx);
m_subscriptions.erase(what); m_subscriptions.erase(what);
} }
message_queue& converted_thread_context::mailbox() message_queue& converted_thread_context::mailbox()
{ {
return m_mailbox; return m_mailbox;
} }
} } // namespace cppa::detail } } // namespace cppa::detail
#include "cppa/config.hpp"
#include <map>
#include <mutex>
#include <memory>
#include <stdexcept>
#include "cppa/group.hpp" #include "cppa/group.hpp"
namespace cppa { namespace cppa {
group::subscription::subscription(const channel_ptr& s, const intrusive_ptr<group>& g) : m_self(s), m_group(g) namespace {
typedef std::map< std::string, std::unique_ptr<group::module> > modules_map;
std::mutex s_mtx;
modules_map s_mmap;
} // namespace <anonymous>
intrusive_ptr<group> group::get(const std::string& module_name,
const std::string& group_name)
{
std::lock_guard<std::mutex> guard(s_mtx);
auto i = s_mmap.find(module_name);
if (i != s_mmap.end())
{
return (i->second)->get(group_name);
}
std::string error_msg = "no module named \"";
error_msg += module_name;
error_msg += "\" found";
throw std::logic_error(error_msg);
}
void group::add_module(group::module* ptr)
{
auto mname = ptr->name();
std::unique_ptr<group::module> mptr(ptr);
// lifetime scope of guard
{
std::lock_guard<std::mutex> guard(s_mtx);
if (!s_mmap.insert(std::make_pair(mname, std::move(mptr))).second)
{
std::string error_msg = "module name \"";
error_msg += mname;
error_msg += "\" already defined";
throw std::logic_error(error_msg);
}
}
}
group::subscription::subscription(const channel_ptr& s,
const intrusive_ptr<group>& g)
: m_self(s), m_group(g)
{
}
group::subscription::subscription(group::subscription&& other)
: m_self(std::move(other.m_self)), m_group(std::move(other.m_group))
{ {
} }
group::subscription::~subscription() group::subscription::~subscription()
{ {
m_group->unsubscribe(m_self); if (m_group) m_group->unsubscribe(m_self);
} }
} // namespace cppa } // namespace cppa
...@@ -4,12 +4,12 @@ namespace cppa { ...@@ -4,12 +4,12 @@ namespace cppa {
message::message(const actor_ptr& from, message::message(const actor_ptr& from,
const channel_ptr& to, const channel_ptr& to,
const untyped_tuple& ut) const any_tuple& ut)
: m_content(new content(from, to, ut)) : m_content(new msg_content(from, to, ut))
{ {
} }
message::message() : m_content(new content(0, 0, tuple<int>(0))) message::message() : m_content(new msg_content(0, 0, tuple<int>(0)))
{ {
} }
...@@ -17,7 +17,7 @@ bool operator==(const message& lhs, const message& rhs) ...@@ -17,7 +17,7 @@ bool operator==(const message& lhs, const message& rhs)
{ {
return lhs.sender() == rhs.sender() return lhs.sender() == rhs.sender()
&& lhs.receiver() == rhs.receiver() && lhs.receiver() == rhs.receiver()
&& lhs.data().vals()->equal_to(*(rhs.data().vals())); && lhs.content().vals()->equal_to(*(rhs.content().vals()));
} }
} // namespace cppa } // namespace cppa
...@@ -19,13 +19,17 @@ void object::swap(object& other) ...@@ -19,13 +19,17 @@ void object::swap(object& other)
std::swap(m_type, other.m_type); std::swap(m_type, other.m_type);
} }
void* object::new_instance(const uniform_type_info* type, const void* from)
{
return type->new_instance(from);
}
object object::copy() const object object::copy() const
{ {
return (m_value != &s_void) ? object(m_type->new_instance(m_value), m_type) return (m_value != &s_void) ? object(m_type->new_instance(m_value), m_type)
: object(); : object();
} }
object::object(void* val, const uniform_type_info* utype) object::object(void* val, const uniform_type_info* utype)
: m_value(val), m_type(utype) : m_value(val), m_type(utype)
{ {
...@@ -70,7 +74,7 @@ object& object::operator=(const object& other) ...@@ -70,7 +74,7 @@ object& object::operator=(const object& other)
return *this; return *this;
} }
bool object::equal(const object& other) const bool object::equal_to(const object& other) const
{ {
if (m_type == other.m_type) if (m_type == other.m_type)
{ {
...@@ -90,4 +94,19 @@ std::string object::to_string() const ...@@ -90,4 +94,19 @@ std::string object::to_string() const
return ""; return "";
} }
bool object::empty() const
{
return m_value == &s_void;
}
const void* object::value() const
{
return m_value;
}
void* object::mutable_value()
{
return m_value;
}
} // namespace cppa } // namespace cppa
#include "cppa/detail/object_array.hpp"
namespace cppa { namespace detail {
object_array::object_array()
{
}
object_array::object_array(object_array&& other)
: m_elements(std::move(other.m_elements))
{
}
object_array::object_array(const object_array& other)
: m_elements(other.m_elements)
{
}
void object_array::push_back(const object& what)
{
m_elements.push_back(what);
}
void object_array::push_back(object&& what)
{
m_elements.push_back(std::move(what));
}
void* object_array::mutable_at(size_t pos)
{
return m_elements[pos].mutable_value();
}
size_t object_array::size() const
{
return m_elements.size();
}
abstract_tuple* object_array::copy() const
{
return new object_array(*this);
}
const void* object_array::at(size_t pos) const
{
return m_elements[pos].value();
}
const util::abstract_type_list& object_array::types() const
{
return *this;
}
bool object_array::equal_to(const cppa::detail::abstract_tuple& ut) const
{
if (size() == ut.size())
{
for (size_t i = 0; i < size(); ++i)
{
const uniform_type_info& utype = type_at(i);
if (utype == ut.type_at(i))
{
if (!utype.equal(at(i), ut.at(i))) return false;
}
else
{
return false;
}
}
return true;
}
return false;
}
const uniform_type_info& object_array::type_at(size_t pos) const
{
return m_elements[pos].type();
}
util::abstract_type_list::const_iterator object_array::begin() const
{
struct type_iterator : util::abstract_type_list::abstract_iterator
{
typedef std::vector<object>::const_iterator iterator_type;
iterator_type m_pos;
iterator_type m_end;
type_iterator(iterator_type begin, iterator_type end)
: m_pos(begin), m_end(end)
{
}
type_iterator(const type_iterator&) = default;
bool next()
{
return ++m_pos != m_end;
}
const uniform_type_info& get() const
{
return m_pos->type();
}
abstract_iterator* copy() const
{
return new type_iterator(*this);
}
};
return new type_iterator(m_elements.begin(), m_elements.end());
}
} } // namespace cppa::detail
...@@ -11,14 +11,17 @@ ...@@ -11,14 +11,17 @@
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/object.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
#include "cppa/any_type.hpp" #include "cppa/any_type.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
#include "cppa/util/void_type.hpp" #include "cppa/util/void_type.hpp"
#include "cppa/detail/demangle.hpp" #include "cppa/detail/demangle.hpp"
#include "cppa/detail/object_array.hpp"
#include "cppa/detail/to_uniform_name.hpp" #include "cppa/detail/to_uniform_name.hpp"
#include "cppa/detail/default_uniform_type_info_impl.hpp" #include "cppa/detail/default_uniform_type_info_impl.hpp"
...@@ -93,7 +96,7 @@ void push(std::map<int, std::pair<string_set, string_set>>& ints) ...@@ -93,7 +96,7 @@ void push(std::map<int, std::pair<string_set, string_set>>& ints)
namespace cppa { namespace detail { namespace { namespace cppa { namespace detail { namespace {
class actor_ptr_type_info_impl : public util::uniform_type_info_base<actor_ptr> class actor_ptr_type_info : public util::abstract_uniform_type_info<actor_ptr>
{ {
protected: protected:
...@@ -121,6 +124,44 @@ class actor_ptr_type_info_impl : public util::uniform_type_info_base<actor_ptr> ...@@ -121,6 +124,44 @@ class actor_ptr_type_info_impl : public util::uniform_type_info_base<actor_ptr>
}; };
class any_tuple_type_info : public util::abstract_uniform_type_info<any_tuple>
{
protected:
void serialize(const void* instance, serializer* sink) const
{
auto atup = reinterpret_cast<const any_tuple*>(instance);
sink->begin_object(name());
sink->begin_sequence(atup->size());
for (size_t i = 0; i < atup->size(); ++i)
{
atup->type_at(i).serialize(atup->at(i), sink);
}
sink->end_sequence();
sink->end_object();
}
void deserialize(void* instance, deserializer* source) const
{
auto result = new detail::object_array;
auto str = source->seek_object();
if (str != name()) throw std::logic_error("invalid type found: " + str);
source->begin_object(str);
size_t tuple_size = source->begin_sequence();
for (size_t i = 0; i < tuple_size; ++i)
{
auto tname = source->peek_object();
auto utype = uniform_type_info::by_uniform_name(tname);
result->push_back(utype->deserialize(source));
}
source->end_sequence();
source->end_object();
*reinterpret_cast<any_tuple*>(instance) = any_tuple(result);
}
};
class uniform_type_info_map class uniform_type_info_map
{ {
...@@ -164,7 +205,8 @@ class uniform_type_info_map ...@@ -164,7 +205,8 @@ class uniform_type_info_map
insert<std::string>(); insert<std::string>();
insert<std::u16string>(); insert<std::u16string>();
insert<std::u32string>(); insert<std::u32string>();
insert(new actor_ptr_type_info_impl, { raw_name<actor_ptr>() }); insert(new actor_ptr_type_info, { raw_name<actor_ptr>() });
insert(new any_tuple_type_info, { raw_name<any_tuple>() });
insert<float>(); insert<float>();
insert<cppa::util::void_type>(); insert<cppa::util::void_type>();
if (sizeof(double) == sizeof(long double)) if (sizeof(double) == sizeof(long double))
...@@ -236,7 +278,7 @@ class uniform_type_info_map ...@@ -236,7 +278,7 @@ class uniform_type_info_map
return nullptr; return nullptr;
} }
bool insert(std::set<std::string> plain_names, bool insert(std::set<std::string> raw_names,
uniform_type_info* what) uniform_type_info* what)
{ {
if (m_by_uname.count(what->name()) > 0) if (m_by_uname.count(what->name()) > 0)
...@@ -245,7 +287,7 @@ class uniform_type_info_map ...@@ -245,7 +287,7 @@ class uniform_type_info_map
return false; return false;
} }
m_by_uname.insert(std::make_pair(what->name(), what)); m_by_uname.insert(std::make_pair(what->name(), what));
for (const std::string& plain_name : plain_names) for (const std::string& plain_name : raw_names)
{ {
if (!m_by_rname.insert(std::make_pair(plain_name, what)).second) if (!m_by_rname.insert(std::make_pair(plain_name, what)).second)
{ {
...@@ -278,7 +320,6 @@ uniform_type_info_map& s_uniform_type_info_map() ...@@ -278,7 +320,6 @@ uniform_type_info_map& s_uniform_type_info_map()
} } } // namespace cppa::detail::<anonymous> } } } // namespace cppa::detail::<anonymous>
namespace { namespace {
std::atomic<int> s_ids; std::atomic<int> s_ids;
......
#include "cppa/untyped_tuple.hpp"
namespace {
struct empty_type_list : cppa::util::abstract_type_list
{
virtual abstract_type_list* copy() const
{
return new empty_type_list;
}
virtual const_iterator begin() const { return 0; }
virtual const_iterator end() const { return 0; }
virtual const cppa::uniform_type_info* at(std::size_t) const
{
throw std::range_error("empty_type_list::at()");
}
};
struct empty_tuple : cppa::detail::abstract_tuple
{
empty_type_list m_types;
virtual std::size_t size() const { return 0; }
virtual abstract_tuple* copy() const { return new empty_tuple; }
virtual void* mutable_at(std::size_t)
{
throw std::range_error("empty_tuple::mutable_at()");
}
virtual const void* at(std::size_t) const
{
throw std::range_error("empty_tuple::at()");
}
virtual const cppa::uniform_type_info* utype_at(std::size_t) const
{
throw std::range_error("empty_tuple::utype_at()");
}
virtual const cppa::util::abstract_type_list& types() const
{
return m_types;
}
virtual bool equal_to(const abstract_tuple& other) const
{
return other.size() == 0;
}
virtual void serialize(cppa::serializer&) const
{
}
};
} // namespace <anonymous>
namespace cppa {
untyped_tuple::untyped_tuple() : m_vals(new empty_tuple) { }
} // namespace cppa
...@@ -53,7 +53,7 @@ int main(int argc, char** c_argv) ...@@ -53,7 +53,7 @@ int main(int argc, char** c_argv)
else else
{ {
std::cout << std::boolalpha; std::cout << std::boolalpha;
std::size_t errors = 0; size_t errors = 0;
RUN_TEST(test__primitive_variant); RUN_TEST(test__primitive_variant);
RUN_TEST(test__uniform_type); RUN_TEST(test__uniform_type);
RUN_TEST(test__intrusive_ptr); RUN_TEST(test__intrusive_ptr);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#define CPPA_TEST(name) \ #define CPPA_TEST(name) \
struct cppa_test_scope \ struct cppa_test_scope \
{ \ { \
std::size_t error_count; \ size_t error_count; \
cppa_test_scope() : error_count(0) { } \ cppa_test_scope() : error_count(0) { } \
~cppa_test_scope() \ ~cppa_test_scope() \
{ \ { \
...@@ -40,18 +40,22 @@ if (!(line_of_code)) \ ...@@ -40,18 +40,22 @@ if (!(line_of_code)) \
} ((void) 0) } ((void) 0)
#endif #endif
#define CPPA_ERROR(err_msg) \
std::cerr << err_msg << std::endl; \
++cppa_ts.error_count
#define CPPA_CHECK_EQUAL(lhs_loc, rhs_loc) CPPA_CHECK(((lhs_loc) == (rhs_loc))) #define CPPA_CHECK_EQUAL(lhs_loc, rhs_loc) CPPA_CHECK(((lhs_loc) == (rhs_loc)))
std::size_t test__uniform_type(); size_t test__uniform_type();
std::size_t test__type_list(); size_t test__type_list();
std::size_t test__a_matches_b(); size_t test__a_matches_b();
std::size_t test__atom(); size_t test__atom();
std::size_t test__tuple(); size_t test__tuple();
std::size_t test__spawn(); size_t test__spawn();
std::size_t test__intrusive_ptr(); size_t test__intrusive_ptr();
std::size_t test__serialization(); size_t test__serialization();
std::size_t test__local_group(); size_t test__local_group();
std::size_t test__primitive_variant(); size_t test__primitive_variant();
void test__queue_performance(); void test__queue_performance();
......
...@@ -7,41 +7,41 @@ ...@@ -7,41 +7,41 @@
using namespace cppa; using namespace cppa;
using namespace cppa::util; using namespace cppa::util;
std::size_t test__a_matches_b() size_t test__a_matches_b()
{ {
CPPA_TEST(test__a_matches_b); CPPA_TEST(test__a_matches_b);
typedef type_list<int, any_type*> int_star; typedef type_list<int, any_type*> int_star;
typedef type_list<int, float, int> int_float_int; typedef type_list<int, float, int> int_float_int;
typedef type_list<int, int, std::string> int_int_string; typedef type_list<int, int, std::string> int_int_string;
typedef type_list<int, int, const std::string&> int_int_const_string_ref; typedef type_list<int, int, const std::string&> int_int_const_string_ref;
typedef typename first_n<2, int_float_int>::type int_float; typedef typename first_n<2, int_float_int>::type int_float;
typedef type_list_apply<int_int_const_string_ref, typedef type_list_apply<int_int_const_string_ref,
remove_const_reference>::type remove_const_reference>::type
int_int_string2; int_int_string2;
CPPA_CHECK((std::is_same<int, remove_const_reference<const int&>::type>::value)); CPPA_CHECK((std::is_same<int, remove_const_reference<const int&>::type>::value));
CPPA_CHECK((a_matches_b<int_star, int_float_int>::value)); CPPA_CHECK((a_matches_b<int_star, int_float_int>::value));
CPPA_CHECK((a_matches_b<int_float_int, int_float_int>::value)); CPPA_CHECK((a_matches_b<int_float_int, int_float_int>::value));
CPPA_CHECK((a_matches_b<int_int_string, int_int_string>::value)); CPPA_CHECK((a_matches_b<int_int_string, int_int_string>::value));
CPPA_CHECK((a_matches_b<int_int_string, int_int_string2>::value)); CPPA_CHECK((a_matches_b<int_int_string, int_int_string2>::value));
CPPA_CHECK(!(a_matches_b<int_int_string, int_int_const_string_ref>::value)); CPPA_CHECK(!(a_matches_b<int_int_string, int_int_const_string_ref>::value));
CPPA_CHECK(!(a_matches_b<type_list<float>, CPPA_CHECK(!(a_matches_b<type_list<float>,
type_list<int, float, int>>::value)); type_list<int, float, int>>::value));
CPPA_CHECK((std::is_same<util::type_list<int, float>, int_float>::value)); CPPA_CHECK((std::is_same<util::type_list<int, float>, int_float>::value));
CPPA_CHECK((a_matches_b<type_list<any_type*, float>, CPPA_CHECK((a_matches_b<type_list<any_type*, float>,
type_list<int, float, int>>::value) == false); type_list<int, float, int>>::value) == false);
CPPA_CHECK((a_matches_b<type_list<any_type*, float>, CPPA_CHECK((a_matches_b<type_list<any_type*, float>,
type_list<int, int, float>>::value)); type_list<int, int, float>>::value));
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
...@@ -18,67 +18,67 @@ struct _tostring; ...@@ -18,67 +18,67 @@ struct _tostring;
template<char C0, char... Str> template<char C0, char... Str>
struct _tostring<C0, Str...> struct _tostring<C0, Str...>
{ {
inline static void _(std::string& s) inline static void _(std::string& s)
{ {
s += C0; s += C0;
_tostring<Str...>::_(s); _tostring<Str...>::_(s);
} }
}; };
template<> template<>
struct _tostring<> struct _tostring<>
{ {
inline static void _(std::string&) { } inline static void _(std::string&) { }
}; };
class atom_base class atom_base
{ {
std::string m_str; std::string m_str;
unsigned int m_hash; unsigned int m_hash;
public: public:
atom_base(std::string&& str) : m_str(str), m_hash(hash_of(m_str)) atom_base(std::string&& str) : m_str(str), m_hash(hash_of(m_str))
{ {
} }
atom_base(atom_base&& rval) atom_base(atom_base&& rval)
: m_str(std::move(rval.m_str)), m_hash(hash_of(m_str)) : m_str(std::move(rval.m_str)), m_hash(hash_of(m_str))
{ {
} }
unsigned int hash() const unsigned int hash() const
{ {
return m_hash; return m_hash;
} }
const std::string& value() const const std::string& value() const
{ {
return m_str; return m_str;
} }
}; };
bool operator==(const atom_base& lhs, const atom_base& rhs) bool operator==(const atom_base& lhs, const atom_base& rhs)
{ {
return (lhs.hash() == rhs.hash()) && (lhs.value() == rhs.value()); return (lhs.hash() == rhs.hash()) && (lhs.value() == rhs.value());
} }
bool operator!=(const atom_base& lhs, const atom_base& rhs) bool operator!=(const atom_base& lhs, const atom_base& rhs)
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
bool operator!=(const atom_base& lhs, const std::string& rhs) bool operator!=(const atom_base& lhs, const std::string& rhs)
{ {
return lhs.value() == rhs; return lhs.value() == rhs;
} }
bool operator!=(const std::string& lhs, const atom_base& rhs) bool operator!=(const std::string& lhs, const atom_base& rhs)
{ {
return lhs == rhs.value(); return lhs == rhs.value();
} }
// template<char...> // template<char...>
...@@ -87,36 +87,36 @@ bool operator!=(const std::string& lhs, const atom_base& rhs) ...@@ -87,36 +87,36 @@ bool operator!=(const std::string& lhs, const atom_base& rhs)
template<char... Str> template<char... Str>
class atom : public atom_base class atom : public atom_base
{ {
static std::string to_string() static std::string to_string()
{ {
std::string result; std::string result;
_tostring<Str...>::_(result); _tostring<Str...>::_(result);
return result; return result;
} }
public: public:
atom() : atom_base(to_string()) { } atom() : atom_base(to_string()) { }
atom(atom&& rval) : atom_base(rval) { } atom(atom&& rval) : atom_base(rval) { }
}; };
std::size_t test__atom() size_t test__atom()
{ {
CPPA_TEST(test__atom); CPPA_TEST(test__atom);
atom<'f','o','o'> a1; atom<'f','o','o'> a1;
atom_base a2("foo"); atom_base a2("foo");
atom_base a3 = atom<'a','b','c'>(); atom_base a3 = atom<'a','b','c'>();
CPPA_CHECK(a1 == a2); CPPA_CHECK(a1 == a2);
CPPA_CHECK(a1 != a3); CPPA_CHECK(a1 != a3);
// atom<"foobar"> a1; // atom<"foobar"> a1;
// CPPA_CHECK(a1 == a3); // CPPA_CHECK(a1 == a3);
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
...@@ -15,22 +15,22 @@ int class1_instances = 0; ...@@ -15,22 +15,22 @@ int class1_instances = 0;
} }
struct class0 : cppa::detail::ref_counted_impl<std::size_t> struct class0 : cppa::detail::ref_counted_impl<size_t>
{ {
class0() { ++class0_instances; } class0() { ++class0_instances; }
virtual ~class0() { --class0_instances; } virtual ~class0() { --class0_instances; }
virtual class0* create() const { return new class0; } virtual class0* create() const { return new class0; }
}; };
struct class1 : class0 struct class1 : class0
{ {
class1() { ++class1_instances; } class1() { ++class1_instances; }
virtual ~class1() { --class1_instances; } virtual ~class1() { --class1_instances; }
virtual class1* create() const { return new class1; } virtual class1* create() const { return new class1; }
}; };
typedef intrusive_ptr<class0> class0_ptr; typedef intrusive_ptr<class0> class0_ptr;
...@@ -38,67 +38,67 @@ typedef intrusive_ptr<class1> class1_ptr; ...@@ -38,67 +38,67 @@ typedef intrusive_ptr<class1> class1_ptr;
class0* get_test_rc() class0* get_test_rc()
{ {
return new class0; return new class0;
} }
class0_ptr get_test_ptr() class0_ptr get_test_ptr()
{ {
return get_test_rc(); return get_test_rc();
} }
std::size_t test__intrusive_ptr() size_t test__intrusive_ptr()
{ {
CPPA_TEST(test__intrusive_ptr); CPPA_TEST(test__intrusive_ptr);
{ {
class0_ptr p(new class0); class0_ptr p(new class0);
CPPA_CHECK_EQUAL(class0_instances, 1); CPPA_CHECK_EQUAL(class0_instances, 1);
CPPA_CHECK(p->unique()); CPPA_CHECK(p->unique());
} }
CPPA_CHECK_EQUAL(class0_instances, 0); CPPA_CHECK_EQUAL(class0_instances, 0);
{ {
class0_ptr p; class0_ptr p;
p = new class0; p = new class0;
CPPA_CHECK_EQUAL(class0_instances, 1); CPPA_CHECK_EQUAL(class0_instances, 1);
CPPA_CHECK(p->unique()); CPPA_CHECK(p->unique());
} }
CPPA_CHECK_EQUAL(class0_instances, 0); CPPA_CHECK_EQUAL(class0_instances, 0);
{ {
class0_ptr p1; class0_ptr p1;
p1 = get_test_rc(); p1 = get_test_rc();
class0_ptr p2 = p1; class0_ptr p2 = p1;
CPPA_CHECK_EQUAL(class0_instances, 1); CPPA_CHECK_EQUAL(class0_instances, 1);
CPPA_CHECK_EQUAL(p1->unique(), false); CPPA_CHECK_EQUAL(p1->unique(), false);
} }
CPPA_CHECK_EQUAL(class0_instances, 0); CPPA_CHECK_EQUAL(class0_instances, 0);
{ {
std::list<class0_ptr> pl; std::list<class0_ptr> pl;
pl.push_back(get_test_ptr()); pl.push_back(get_test_ptr());
pl.push_back(get_test_rc()); pl.push_back(get_test_rc());
pl.push_back(pl.front()->create()); pl.push_back(pl.front()->create());
CPPA_CHECK(pl.front()->unique()); CPPA_CHECK(pl.front()->unique());
CPPA_CHECK_EQUAL(class0_instances, 3); CPPA_CHECK_EQUAL(class0_instances, 3);
} }
CPPA_CHECK_EQUAL(class0_instances, 0); CPPA_CHECK_EQUAL(class0_instances, 0);
{ {
class0_ptr p1(new class0); class0_ptr p1(new class0);
p1 = new class1; p1 = new class1;
CPPA_CHECK_EQUAL(class0_instances, 1); CPPA_CHECK_EQUAL(class0_instances, 1);
CPPA_CHECK_EQUAL(class1_instances, 1); CPPA_CHECK_EQUAL(class1_instances, 1);
class1_ptr p2(new class1); class1_ptr p2(new class1);
p1 = p2; p1 = p2;
CPPA_CHECK_EQUAL(class0_instances, 1); CPPA_CHECK_EQUAL(class0_instances, 1);
CPPA_CHECK_EQUAL(class1_instances, 1); CPPA_CHECK_EQUAL(class1_instances, 1);
CPPA_CHECK_EQUAL(p1, p2); CPPA_CHECK_EQUAL(p1, p2);
} }
CPPA_CHECK_EQUAL(class0_instances, 0); CPPA_CHECK_EQUAL(class0_instances, 0);
CPPA_CHECK_EQUAL(class1_instances, 0); CPPA_CHECK_EQUAL(class1_instances, 0);
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
#include "cppa/config.hpp"
#include <map>
#include <list>
#include <mutex>
#include <iostream>
#include <algorithm>
#include "test.hpp" #include "test.hpp"
#include "hash_of.hpp" #include "hash_of.hpp"
...@@ -8,164 +16,119 @@ ...@@ -8,164 +16,119 @@
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include <map>
#include <list>
#include <iostream>
#include <algorithm>
#include <boost/thread/mutex.hpp>
using std::cout; using std::cout;
using std::endl; using std::endl;
/*
using namespace cppa; using namespace cppa;
namespace {
class local_group : public group class local_group : public group
{ {
boost::mutex m_mtx; friend class local_group_module;
std::list<channel_ptr> m_subscribers;
inline std::list<channel_ptr>::iterator find(const channel_ptr& what) std::mutex m_mtx;
{ std::list<channel_ptr> m_subscribers;
return std::find(m_subscribers.begin(), m_subscribers.end(), what);
}
public: inline std::list<channel_ptr>::iterator find(const channel_ptr& what)
{
return std::find(m_subscribers.begin(), m_subscribers.end(), what);
}
virtual void enqueue(const message& msg) local_group() = default;
{
boost::mutex::scoped_lock guard(m_mtx);
for (auto i = m_subscribers.begin(); i != m_subscribers.end(); ++i)
{
(*i)->enqueue(msg);
}
}
virtual intrusive_ptr<group::subscription> subscribe(const channel_ptr& who)
{
boost::mutex::scoped_lock guard(m_mtx);
auto i = find(who);
if (i == m_subscribers.end())
{
m_subscribers.push_back(who);
return new group::subscription(who, this);
}
return new group::subscription(0, 0);
}
virtual void unsubscribe(const channel_ptr& who)
{
boost::mutex::scoped_lock guard(m_mtx);
auto i = find(who);
if (i != m_subscribers.end())
{
m_subscribers.erase(i);
}
}
}; public:
//local_group* m_local_group = new local_group; virtual void enqueue(const message& msg)
{
std::lock_guard<std::mutex> guard(m_mtx);
for (auto i = m_subscribers.begin(); i != m_subscribers.end(); ++i)
{
(*i)->enqueue(msg);
}
}
virtual group::subscription subscribe(const channel_ptr& who)
{
std::lock_guard<std::mutex> guard(m_mtx);
auto i = find(who);
if (i == m_subscribers.end())
{
m_subscribers.push_back(who);
return { who, this };
}
return { nullptr, nullptr };
}
virtual void unsubscribe(const channel_ptr& who)
{
std::lock_guard<std::mutex> guard(m_mtx);
auto i = find(who);
if (i != m_subscribers.end())
{
m_subscribers.erase(i);
}
}
intrusive_ptr<local_group> m_local_group(new local_group); };
intrusive_ptr<local_group> local(const char*) class local_group_module : public group::module
{ {
return m_local_group;
}
} // namespace <anonymous> std::string m_name;
std::mutex m_mtx;
struct storage std::map<std::string, group_ptr> m_instances;
{
std::map<std::string, intrusive_ptr<object>> m_map;
public: public:
template<typename T> local_group_module() : m_name("local")
T& get(const std::string& key) {
{ }
auto uti = uniform_type_info::by_type_info(typeid(T));
auto i = m_map.find(key); const std::string& name()
if (i == m_map.end()) {
{ return m_name;
i = m_map.insert(std::make_pair(key, uti->create())).first; }
}
else if (uti != i->second->type()) group_ptr get(const std::string& group_name)
{ {
// todo: throw nicer exception std::lock_guard<std::mutex> guard(m_mtx);
throw std::runtime_error("invalid type"); auto i = m_instances.find(group_name);
} if (i == m_instances.end())
return *reinterpret_cast<T*>(i->second->mutable_value()); {
} group_ptr result(new local_group);
m_instances.insert(std::make_pair(group_name, result));
return result;
}
else return i->second;
}
}; };
void consumer(actor_ptr main_actor) void worker()
{ {
int result = 0; receive(on<int>() >> [](int value) {
for (int i = 0; i < 5; ++i) reply(value);
{ });
receive(on<int>() >> [&](int x) {
result += x;
});
}
send(main_actor, result);
} }
void producer(actor_ptr consume_actor) size_t test__local_group()
{ {
receive(on<int>() >> [&](int i) { CPPA_TEST(test__local_group);
send(consume_actor, i); group::add_module(new local_group_module);
}); auto foo_group = group::get("local", "foo");
} for (int i = 0; i < 5; ++i)
{
std::size_t test__local_group() // spawn workers in group local:foo
{ spawn(worker)->join(foo_group);
}
CPPA_TEST(test__local_group); send(foo_group, 2);
int result = 0;
std::list<intrusive_ptr<group::subscription>> m_subscriptions; for (int i = 0; i < 5; ++i)
{
actor_ptr self_ptr = self(); receive(on<int>() >> [&result](int value) { result += value; });
}
auto consume_actor = spawn(consumer, self_ptr); CPPA_CHECK_EQUAL(result, 10);
await_all_others_done();
auto lg = local("foobar"); return CPPA_TEST_RESULT;
for (int i = 0; i < 5; ++i)
{
auto fa = spawn(producer, consume_actor);
auto sptr = lg->subscribe(fa);
m_subscriptions.push_back(sptr);
}
send(lg, 1);
await_all_actors_done();
receive(on<int>() >> [&](int x) {
CPPA_CHECK_EQUAL(x, 5);
});
return CPPA_TEST_RESULT;
}
*/
std::size_t test__local_group()
{
CPPA_TEST(test__local_group);
CPPA_CHECK_EQUAL(true, true);
return CPPA_TEST_RESULT;
} }
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
using namespace cppa; using namespace cppa;
std::size_t test__primitive_variant() size_t test__primitive_variant()
{ {
CPPA_TEST(test__primitive_variant); CPPA_TEST(test__primitive_variant);
std::uint32_t forty_two = 42; std::uint32_t forty_two = 42;
......
...@@ -17,61 +17,61 @@ using std::endl; ...@@ -17,61 +17,61 @@ using std::endl;
struct queue_element struct queue_element
{ {
queue_element* next; queue_element* next;
std::size_t value; size_t value;
queue_element(std::size_t val) : next(0), value(val) { } queue_element(size_t val) : next(0), value(val) { }
}; };
template<typename T> template<typename T>
class singly_linked_list class singly_linked_list
{ {
typedef T element_type; typedef T element_type;
element_type* m_head; element_type* m_head;
element_type* m_tail; element_type* m_tail;
public: public:
singly_linked_list() : m_head(0), m_tail(0) { } singly_linked_list() : m_head(0), m_tail(0) { }
singly_linked_list& operator=(singly_linked_list&& other) singly_linked_list& operator=(singly_linked_list&& other)
{ {
m_head = other.m_head; m_head = other.m_head;
m_tail = other.m_tail; m_tail = other.m_tail;
other.m_head = 0; other.m_head = 0;
other.m_tail = 0; other.m_tail = 0;
return *this; return *this;
} }
inline bool empty() const { return m_head == 0; } inline bool empty() const { return m_head == 0; }
void push_back(element_type* e) void push_back(element_type* e)
{ {
if (!m_head) if (!m_head)
{ {
m_head = m_tail = e; m_head = m_tail = e;
} }
else else
{ {
m_tail->next = e; m_tail->next = e;
m_tail = e; m_tail = e;
} }
} }
element_type* pop_front() element_type* pop_front()
{ {
element_type* result = m_head; element_type* result = m_head;
if (result) if (result)
{ {
m_head = result->next; m_head = result->next;
if (!m_head) if (!m_head)
{ {
m_tail = 0; m_tail = 0;
} }
} }
return result; return result;
} }
}; };
...@@ -79,167 +79,167 @@ template<typename T> ...@@ -79,167 +79,167 @@ template<typename T>
class locked_queue class locked_queue
{ {
typedef boost::unique_lock<boost::mutex> lock_type; typedef boost::unique_lock<boost::mutex> lock_type;
public: public:
typedef T element_type; typedef T element_type;
element_type* pop() element_type* pop()
{ {
if (!m_priv.empty()) if (!m_priv.empty())
{ {
return m_priv.pop_front(); return m_priv.pop_front();
} }
else else
{ {
// lifetime scope of guard // lifetime scope of guard
{ {
lock_type guard(m_mtx); lock_type guard(m_mtx);
while (m_pub.empty()) while (m_pub.empty())
{ {
m_cv.wait(guard); m_cv.wait(guard);
} }
m_priv = std::move(m_pub); m_priv = std::move(m_pub);
} }
// tail recursion // tail recursion
return pop(); return pop();
} }
} }
void push(element_type* new_element) void push(element_type* new_element)
{ {
lock_type guard(m_mtx); lock_type guard(m_mtx);
if (m_pub.empty()) if (m_pub.empty())
{ {
m_cv.notify_one(); m_cv.notify_one();
} }
m_pub.push_back(new_element); m_pub.push_back(new_element);
} }
private: private:
boost::mutex m_mtx; boost::mutex m_mtx;
boost::condition_variable m_cv; boost::condition_variable m_cv;
singly_linked_list<element_type> m_pub; singly_linked_list<element_type> m_pub;
singly_linked_list<element_type> m_priv; singly_linked_list<element_type> m_priv;
}; };
namespace { namespace {
//const std::size_t num_slaves = 1000; //const size_t num_slaves = 1000;
//const std::size_t num_slave_msgs = 90000; //const size_t num_slave_msgs = 90000;
// 900 000 // 900 000
//const std::size_t num_msgs = (num_slaves) * (num_slave_msgs); //const size_t num_msgs = (num_slaves) * (num_slave_msgs);
// uint32::max = 4 294 967 296 // uint32::max = 4 294 967 296
// (n (n+1)) / 2 = 4 050 045 000 // (n (n+1)) / 2 = 4 050 045 000
//const std::size_t calc_result = ((num_msgs)*(num_msgs + 1)) / 2; //const size_t calc_result = ((num_msgs)*(num_msgs + 1)) / 2;
} // namespace <anonymous> } // namespace <anonymous>
template<typename Queue> template<typename Queue>
void slave(Queue& q, std::size_t from, std::size_t to) void slave(Queue& q, size_t from, size_t to)
{ {
for (std::size_t x = from; x < to; ++x) for (size_t x = from; x < to; ++x)
{ {
q.push_back(new queue_element(x)); q.push_back(new queue_element(x));
} }
} }
template<typename Queue, std::size_t num_slaves, std::size_t num_slave_msgs> template<typename Queue, size_t num_slaves, size_t num_slave_msgs>
void master(Queue& q) void master(Queue& q)
{ {
static const std::size_t num_msgs = (num_slaves) * (num_slave_msgs); static const size_t num_msgs = (num_slaves) * (num_slave_msgs);
static const std::size_t calc_result = ((num_msgs)*(num_msgs + 1)) / 2; static const size_t calc_result = ((num_msgs)*(num_msgs + 1)) / 2;
boost::timer t0; boost::timer t0;
for (std::size_t i = 0; i < num_slaves; ++i) for (size_t i = 0; i < num_slaves; ++i)
{ {
std::size_t from = (i * num_slave_msgs) + 1; size_t from = (i * num_slave_msgs) + 1;
std::size_t to = from + num_slave_msgs; size_t to = from + num_slave_msgs;
boost::thread(slave<Queue>, boost::ref(q), from, to).detach(); boost::thread(slave<Queue>, boost::ref(q), from, to).detach();
} }
std::size_t result = 0; size_t result = 0;
std::size_t min_val = calc_result; size_t min_val = calc_result;
std::size_t max_val = 0; size_t max_val = 0;
for (std::size_t i = 0; i < num_msgs; ++i) for (size_t i = 0; i < num_msgs; ++i)
{ {
queue_element* e = q.pop(); queue_element* e = q.pop();
result += e->value; result += e->value;
min_val = std::min(min_val, e->value); min_val = std::min(min_val, e->value);
max_val = std::max(max_val, e->value); max_val = std::max(max_val, e->value);
delete e; delete e;
} }
if (result != calc_result) if (result != calc_result)
{ {
cerr << "ERROR: result = " << result cerr << "ERROR: result = " << result
<< " (should be: " << calc_result << ")" << endl << " (should be: " << calc_result << ")" << endl
<< "min: " << min_val << endl << "min: " << min_val << endl
<< "max: " << max_val << endl; << "max: " << max_val << endl;
} }
cout << t0.elapsed() << " " << num_slaves << endl; cout << t0.elapsed() << " " << num_slaves << endl;
} }
namespace { const std::size_t slave_messages = 1000000; } namespace { const size_t slave_messages = 1000000; }
template<std::size_t Pos, std::size_t Max, std::size_t Step, template<size_t Pos, size_t Max, size_t Step,
template<std::size_t> class Stmt> template<size_t> class Stmt>
struct static_for struct static_for
{ {
template<typename... Args> template<typename... Args>
static inline void _(const Args&... args) static inline void _(const Args&... args)
{ {
Stmt<Pos>::_(args...); Stmt<Pos>::_(args...);
static_for<Pos + Step, Max, Step, Stmt>::_(args...); static_for<Pos + Step, Max, Step, Stmt>::_(args...);
} }
}; };
template<std::size_t Max, std::size_t Step, template<size_t Max, size_t Step,
template<std::size_t> class Stmt> template<size_t> class Stmt>
struct static_for<Max, Max, Step, Stmt> struct static_for<Max, Max, Step, Stmt>
{ {
template<typename... Args> template<typename... Args>
static inline void _(const Args&... args) static inline void _(const Args&... args)
{ {
Stmt<Max>::_(args...); Stmt<Max>::_(args...);
} }
}; };
template<typename What> template<typename What>
struct type_token struct type_token
{ {
typedef What type; typedef What type;
}; };
template<std::size_t NumThreads> template<size_t NumThreads>
struct test_step struct test_step
{ {
template<typename QueueToken> template<typename QueueToken>
static inline void _(QueueToken) static inline void _(QueueToken)
{ {
typename QueueToken::type q; typename QueueToken::type q;
boost::thread t0(master<typename QueueToken::type, NumThreads, slave_messages>, boost::ref(q)); boost::thread t0(master<typename QueueToken::type, NumThreads, slave_messages>, boost::ref(q));
t0.join(); t0.join();
} }
}; };
template<typename Queue> template<typename Queue>
void test_q_impl() void test_q_impl()
{ {
typedef type_token<Queue> queue_token; typedef type_token<Queue> queue_token;
static_for<10, 50, 5, test_step>::_(queue_token()); static_for<10, 50, 5, test_step>::_(queue_token());
} }
void test__queue_performance() void test__queue_performance()
{ {
cout << "locked_queue:" << endl; cout << "locked_queue:" << endl;
// test_q_impl<locked_queue<queue_element>>(); // test_q_impl<locked_queue<queue_element>>();
cout << endl; cout << endl;
cout << "single_reader_queue:" << endl; cout << "single_reader_queue:" << endl;
test_q_impl<single_reader_queue<queue_element>>(); test_q_impl<single_reader_queue<queue_element>>();
} }
...@@ -25,10 +25,11 @@ ...@@ -25,10 +25,11 @@
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/message.hpp" #include "cppa/message.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
#include "cppa/get_view.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/serializer.hpp" #include "cppa/serializer.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
#include "cppa/deserializer.hpp" #include "cppa/deserializer.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/primitive_type.hpp" #include "cppa/primitive_type.hpp"
#include "cppa/primitive_variant.hpp" #include "cppa/primitive_variant.hpp"
#include "cppa/binary_serializer.hpp" #include "cppa/binary_serializer.hpp"
...@@ -42,8 +43,9 @@ ...@@ -42,8 +43,9 @@
#include "cppa/util/if_else_type.hpp" #include "cppa/util/if_else_type.hpp"
#include "cppa/util/wrapped_type.hpp" #include "cppa/util/wrapped_type.hpp"
#include "cppa/util/is_primitive.hpp" #include "cppa/util/is_primitive.hpp"
#include "cppa/util/uniform_type_info_base.hpp" #include "cppa/util/abstract_uniform_type_info.hpp"
#include "cppa/detail/object_array.hpp"
#include "cppa/detail/type_to_ptype.hpp" #include "cppa/detail/type_to_ptype.hpp"
#include "cppa/detail/ptype_to_type.hpp" #include "cppa/detail/ptype_to_type.hpp"
#include "cppa/detail/default_uniform_type_info_impl.hpp" #include "cppa/detail/default_uniform_type_info_impl.hpp"
...@@ -372,7 +374,7 @@ class string_deserializer : public deserializer ...@@ -372,7 +374,7 @@ class string_deserializer : public deserializer
}; };
class message_uti : public util::uniform_type_info_base<message> class message_uti : public util::abstract_uniform_type_info<message>
{ {
public: public:
...@@ -380,20 +382,21 @@ class message_uti : public util::uniform_type_info_base<message> ...@@ -380,20 +382,21 @@ class message_uti : public util::uniform_type_info_base<message>
virtual void serialize(const void* instance, serializer* sink) const virtual void serialize(const void* instance, serializer* sink) const
{ {
const message& msg = *reinterpret_cast<const message*>(instance); const message& msg = *reinterpret_cast<const message*>(instance);
const untyped_tuple& data = msg.data(); const any_tuple& data = msg.content();
sink->begin_object("cppa::message"); sink->begin_object(name());
sink->begin_sequence(data.size()); uniform_typeid<any_tuple>()->serialize(&data, sink);
for (size_t i = 0; i < data.size(); ++i)
{
const uniform_type_info* ut = data.utype_at(i);
ut->serialize(data.at(i), sink);
}
sink->end_sequence();
sink->end_object(); sink->end_object();
} }
virtual void deserialize(void* instance, deserializer* source) const virtual void deserialize(void* instance, deserializer* source) const
{ {
auto tname = source->seek_object();
if (tname != name()) throw 42;
source->begin_object(tname);
any_tuple content;
uniform_typeid<any_tuple>()->deserialize(&content, source);
source->end_object();
*reinterpret_cast<message*>(instance) = message(0, 0, content);
} }
}; };
...@@ -413,13 +416,71 @@ std::string to_string(const T& what) ...@@ -413,13 +416,71 @@ std::string to_string(const T& what)
return osstr.str(); return osstr.str();
} }
std::size_t test__serialization() size_t test__serialization()
{ {
CPPA_TEST(test__serialization); CPPA_TEST(test__serialization);
announce(typeid(message), new message_uti); announce(typeid(message), new message_uti);
//message msg(0, 0, 42, std::string("Hello World"), 23.32);
//cout << to_string(msg) << endl; auto oarr = new detail::object_array;
oarr->push_back(object(static_cast<std::uint32_t>(42)));
oarr->push_back(object(std::string("foo")));
any_tuple atuple1(oarr);
try
{
auto tv1 = get_view<std::uint32_t, std::string>(atuple1);
CPPA_CHECK_EQUAL(tv1.size(), 2);
CPPA_CHECK_EQUAL(get<0>(tv1), 42);
CPPA_CHECK_EQUAL(get<1>(tv1), "foo");
}
catch (std::exception& e)
{
CPPA_ERROR("exception: " << e.what());
}
{
// serialize b1 to buf
binary_serializer bs;
bs << atuple1;
// deserialize b2 from buf
binary_deserializer bd(bs.data(), bs.size());
any_tuple atuple2;
uniform_typeid<any_tuple>()->deserialize(&atuple2, &bd);
try
{
auto tview = get_view<std::uint32_t, std::string>(atuple2);
CPPA_CHECK_EQUAL(tview.size(), 2);
CPPA_CHECK_EQUAL(get<0>(tview), 42);
CPPA_CHECK_EQUAL(get<1>(tview), "foo");
}
catch (std::exception& e)
{
CPPA_ERROR("exception: " << e.what());
}
}
{
message msg1(0, 0, 42, std::string("Hello World!"));
//cout << "msg = " << to_string(msg1) << endl;
binary_serializer bs;
bs << msg1;
binary_deserializer bd(bs.data(), bs.size());
object obj;
bd >> obj;
if (obj.type() == typeid(message))
{
auto& content = get<message>(obj).content();
auto cview = get_view<decltype(42), std::string>(content);
CPPA_CHECK_EQUAL(cview.size(), 2);
CPPA_CHECK_EQUAL(get<0>(cview), 42);
CPPA_CHECK_EQUAL(get<1>(cview), "Hello World!");
}
else
{
CPPA_ERROR("obj.type() != typeid(message)");
}
}
CPPA_CHECK_EQUAL((is_iterable<int>::value), false); CPPA_CHECK_EQUAL((is_iterable<int>::value), false);
// std::string is primitive and thus not identified by is_iterable // std::string is primitive and thus not identified by is_iterable
......
...@@ -19,7 +19,7 @@ void pong() ...@@ -19,7 +19,7 @@ void pong()
}); });
} }
std::size_t test__spawn() size_t test__spawn()
{ {
CPPA_TEST(test__spawn); CPPA_TEST(test__spawn);
{ {
...@@ -30,6 +30,6 @@ std::size_t test__spawn() ...@@ -30,6 +30,6 @@ std::size_t test__spawn()
CPPA_CHECK_EQUAL(value, 42); CPPA_CHECK_EQUAL(value, 42);
}); });
} }
await_all_actors_done(); await_all_others_done();
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
This diff is collapsed.
...@@ -14,7 +14,7 @@ using std::is_same; ...@@ -14,7 +14,7 @@ using std::is_same;
using namespace cppa::util; using namespace cppa::util;
std::size_t test__type_list() size_t test__type_list()
{ {
CPPA_TEST(test__type_list); CPPA_TEST(test__type_list);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "test.hpp" #include "test.hpp"
#include "cppa/get_view.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
#include "cppa/serializer.hpp" #include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp" #include "cppa/deserializer.hpp"
...@@ -57,7 +58,7 @@ bool announce4 = announce<foo>(&foo::value); ...@@ -57,7 +58,7 @@ bool announce4 = announce<foo>(&foo::value);
} // namespace <anonymous> } // namespace <anonymous>
std::size_t test__uniform_type() size_t test__uniform_type()
{ {
CPPA_TEST(test__uniform_type); CPPA_TEST(test__uniform_type);
{ {
...@@ -79,14 +80,16 @@ std::size_t test__uniform_type() ...@@ -79,14 +80,16 @@ std::size_t test__uniform_type()
// the uniform_type_info implementation is correct // the uniform_type_info implementation is correct
std::set<std::string> expected = std::set<std::string> expected =
{ {
"@_::foo", // <anonymous namespace>::foo "@_::foo", // <anonymous namespace>::foo
"@i8", "@i16", "@i32", "@i64", // signed integer names "@i8", "@i16", "@i32", "@i64", // signed integer names
"@u8", "@u16", "@u32", "@u64", // unsigned integer names "@u8", "@u16", "@u32", "@u64", // unsigned integer names
"@str", "@u16str", "@u32str", // strings "@str", "@u16str", "@u32str", // strings
"float", "double", // floating points "float", "double", // floating points
"@0", // cppa::util::void_type "@0", // cppa::util::void_type
"cppa::any_type", // default announced cppa type // default announced cppa types
"cppa::intrusive_ptr<cppa::actor>" // default announced cppa type "cppa::any_type",
"cppa::any_tuple",
"cppa::intrusive_ptr<cppa::actor>"
}; };
if (sizeof(double) != sizeof(long double)) if (sizeof(double) != sizeof(long double))
{ {
......
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