Commit 904adf60 authored by neverlord's avatar neverlord

any_tuple, serialization stuff and group modules

parent 767ab3f4
all:
./create_libcppa_Makefile.sh > libcppa.Makefile
make -f libcppa.Makefile
make -C unit_testing
make -C queue_performances
......
......@@ -17,7 +17,6 @@ cppa/config.hpp
unit_testing/test__tuple.cpp
cppa/detail/abstract_tuple.hpp
cppa/tuple_view.hpp
cppa/untyped_tuple.hpp
cppa/any_type.hpp
cppa/detail/matcher.hpp
cppa/detail/tuple_vals.hpp
......@@ -64,15 +63,12 @@ src/deserializer.cpp
cppa/util/eval_type_list.hpp
cppa/util/is_legal_tuple_type.hpp
cppa/util/replace_type.hpp
src/untyped_tuple.cpp
cppa/util/abstract_type_list.hpp
cppa/detail/serialize_tuple.hpp
unit_testing/test__atom.cpp
unit_testing/test__queue_performance.cpp
cppa/detail/actor_public.hpp
cppa/util/single_reader_queue.hpp
cppa/util/singly_linked_list.hpp
cppa/detail/actor_private.hpp
unit_testing/test__local_group.cpp
unit_testing/hash_of.cpp
unit_testing/hash_of.hpp
......@@ -128,7 +124,6 @@ cppa/util/is_primitive.hpp
cppa/util/is_iterable.hpp
src/primitive_variant.cpp
unit_testing/test__primitive_variant.cpp
cppa/util/uniform_type_info_base.hpp
cppa/detail/primitive_member.hpp
cppa/detail/list_member.hpp
cppa/detail/pair_member.hpp
......@@ -147,3 +142,9 @@ src/message.cpp
cppa/util/shared_spinlock.hpp
src/shared_spinlock.cpp
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 @@
#include <typeinfo>
#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"
namespace cppa {
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)
{
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
......@@ -124,7 +124,7 @@ void reply(const Arg0& arg0, const Args&... 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();
}
......
......@@ -12,15 +12,15 @@ struct abstract_tuple : ref_counted
{
// mutators
virtual void* mutable_at(std::size_t pos) = 0;
virtual void* mutable_at(size_t pos) = 0;
// accessors
virtual std::size_t size() const = 0;
virtual size_t size() 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 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
bool m_exited;
// manages group subscriptions
std::map<group_ptr, intrusive_ptr<group::subscription>> m_subscriptions;
std::map<group_ptr, group::subscription> m_subscriptions;
// manages actor links
std::set<actor_ptr> m_links;
......
......@@ -25,17 +25,17 @@ class decorated_tuple : public abstract_tuple
typedef cow_ptr<abstract_tuple> ptr_type;
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)
{
}
virtual void* mutable_at(std::size_t pos)
virtual void* mutable_at(size_t pos)
{
return m_decorated->mutable_at(m_mappings[pos]);
}
virtual std::size_t size() const
virtual size_t size() const
{
return m_mappings.size();
}
......@@ -45,14 +45,14 @@ class decorated_tuple : public abstract_tuple
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]);
}
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
......@@ -68,7 +68,7 @@ class decorated_tuple : public abstract_tuple
private:
ptr_type m_decorated;
std::vector<std::size_t> m_mappings;
std::vector<size_t> m_mappings;
element_types m_types;
decorated_tuple(const decorated_tuple& other)
......
......@@ -8,7 +8,7 @@
#include "cppa/util/is_iterable.hpp"
#include "cppa/util/is_primitive.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/list_member.hpp"
......@@ -80,7 +80,7 @@ struct has_default_uniform_type_info_impl
};
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>
......@@ -194,7 +194,7 @@ class default_uniform_type_info_impl : public util::uniform_type_info_base<T>
// pr.first = member pointer
// pr.second = meta object to handle pr.first
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)
{
m_members.push_back({ pr.second, pr.first });
......
......@@ -6,7 +6,7 @@
namespace cppa { namespace detail {
// 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;
......
......@@ -8,7 +8,7 @@ namespace cppa { namespace detail {
class intermediate;
// 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;
......@@ -17,8 +17,8 @@ class invokable : public ref_counted_impl<std::size_t>
public:
invokable() = default;
virtual bool invoke(const untyped_tuple&) const = 0;
virtual intermediate* get_intermediate(const untyped_tuple&) const = 0;
virtual bool invoke(const any_tuple&) const = 0;
virtual intermediate* get_intermediate(const any_tuple&) const = 0;
};
......@@ -33,12 +33,12 @@ class invokable_impl : public invokable
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);
}
virtual intermediate* get_intermediate(const untyped_tuple& t) const
virtual intermediate* get_intermediate(const any_tuple& t) const
{
return m_get(t);
}
......
#ifndef 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 {
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;
......
#ifndef 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/pair_member.hpp"
......@@ -46,7 +46,7 @@ struct meta_value_type<std::pair<const T1, T2>>
};
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;
......
......@@ -16,8 +16,8 @@ struct matcher<Head, Tail...>
{
static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr,
std::size_t pos = 0)
std::vector<size_t>* res = nullptr,
size_t pos = 0)
{
auto head_uti = uniform_typeid<Head>();
if (begin != end)
......@@ -42,8 +42,8 @@ struct matcher<any_type, Tail...>
{
static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr,
std::size_t pos = 0)
std::vector<size_t>* res = nullptr,
size_t pos = 0)
{
if (begin != end)
{
......@@ -60,8 +60,8 @@ struct matcher<any_type*, Next, Tail...>
{
static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr,
std::size_t pos = 0)
std::vector<size_t>* res = nullptr,
size_t pos = 0)
{
bool result = false;
while (!result)
......@@ -90,8 +90,8 @@ struct matcher<any_type*>
{
static bool match(util::abstract_type_list::const_iterator&,
util::abstract_type_list::const_iterator&,
std::vector<std::size_t>* = nullptr,
std::size_t = 0)
std::vector<size_t>* = nullptr,
size_t = 0)
{
return true;
}
......@@ -102,8 +102,8 @@ struct matcher<>
{
static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* = nullptr,
std::size_t = 0)
std::vector<size_t>* = nullptr,
size_t = 0)
{
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 @@
#define PAIR_MEMBER_HPP
#include <utility>
#include "cppa/util/uniform_type_info_base.hpp"
#include "cppa/util/abstract_uniform_type_info.hpp"
namespace cppa { namespace detail {
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;
......
......@@ -6,13 +6,13 @@
#include "cppa/primitive_type.hpp"
#include "cppa/primitive_variant.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 {
// uniform_type_info implementation for primitive data types.
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;
......
......@@ -10,7 +10,7 @@ namespace cppa { class serializer; }
namespace cppa { namespace detail {
template<typename List, std::size_t Pos = 0>
template<typename List, size_t Pos = 0>
struct serialize_tuple
{
template<typename T>
......@@ -22,7 +22,7 @@ struct serialize_tuple
}
};
template<std::size_t Pos>
template<size_t Pos>
struct serialize_tuple<util::type_list<>, Pos>
{
template<typename T>
......
......@@ -16,14 +16,14 @@ struct byte_access
inline byte_access(T val = 0) : value(val) { }
};
template<std::size_t SizeOfT, typename T>
template<size_t SizeOfT, typename T>
struct byte_swapper
{
static T _(byte_access<T> from)
{
byte_access<T> to;
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];
}
......
......@@ -20,7 +20,7 @@ struct tdata<>
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;
......@@ -53,7 +53,7 @@ struct tdata<Head, Tail...> : tdata<Tail...>
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;
......@@ -80,10 +80,10 @@ struct tdata<Head, Tail...> : tdata<Tail...>
};
template<std::size_t N, typename... ElementTypes>
template<size_t N, typename... ElementTypes>
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...>
{
typedef typename tdata_upcast_helper<N-1, Tail...>::type type;
......@@ -95,7 +95,7 @@ struct tdata_upcast_helper<0, Head, Tail...>
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&
tdata_get(const tdata<ElementTypes...>& tv)
{
......@@ -104,7 +104,7 @@ tdata_get(const tdata<ElementTypes...>& tv)
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&
tdata_get_ref(tdata<ElementTypes...>& tv)
{
......
......@@ -26,13 +26,13 @@ class tuple_vals : public abstract_tuple
element_types m_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);
}
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);
}
......@@ -43,7 +43,7 @@ class tuple_vals : public abstract_tuple
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) { }
......@@ -55,12 +55,12 @@ class tuple_vals : public abstract_tuple
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);
}
virtual std::size_t size() const
virtual size_t size() const
{
return element_types::type_list_size;
}
......@@ -70,12 +70,12 @@ class tuple_vals : public abstract_tuple
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);
}
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);
}
......
......@@ -16,21 +16,23 @@ class tuple;
template<typename... ElementTypes>
class tuple_view;
// forward declarations of get(...)
template<std::size_t N, typename... Types>
// forward declarations of get(const tuple<...>&...)
template<size_t N, typename... Types>
const typename util::type_at<N, util::type_list<Types...>>::type&
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&
get(const tuple_view<Types...>& t);
// forward declarations of get_ref(...)
template<std::size_t N, typename... Types>
// forward declarations of get_ref(tuple<...>&...)
template<size_t N, typename... Types>
typename util::type_at<N, util::type_list<Types...>>::type&
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&
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
#define GROUP_HPP
#include <string>
#include "cppa/channel.hpp"
#include "cppa/ref_counted.hpp"
......@@ -17,10 +19,9 @@ class group : public channel
class subscription;
friend class group::subscription;
friend class subscription;
// NOT thread safe
class subscription : public ref_counted
class subscription
{
channel_ptr m_self;
......@@ -33,12 +34,27 @@ class group : public channel
public:
subscription(const channel_ptr& s, const intrusive_ptr<group>& g);
subscription(subscription&& other);
~subscription();
virtual ~subscription();
};
class module
{
public:
virtual const std::string& name() = 0;
virtual intrusive_ptr<group> get(const std::string& group_name) = 0;
};
virtual intrusive_ptr<subscription> subscribe(const channel_ptr& who) = 0;
virtual subscription subscribe(const channel_ptr& who) = 0;
static intrusive_ptr<group> get(const std::string& module_name,
const std::string& group_name);
static void add_module(module*);
};
......
......@@ -25,7 +25,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, T*>,
public:
intrusive_ptr() : m_ptr(0) { }
intrusive_ptr() : m_ptr(nullptr) { }
intrusive_ptr(T* raw_ptr) { set_ptr(raw_ptr); }
......@@ -34,7 +34,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, T*>,
set_ptr(other.m_ptr);
}
intrusive_ptr(intrusive_ptr&& other) : m_ptr(0)
intrusive_ptr(intrusive_ptr&& other) : m_ptr(nullptr)
{
swap(other);
}
......@@ -48,7 +48,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, T*>,
}
template<typename Y>
intrusive_ptr(intrusive_ptr<Y>&& other) : m_ptr(0)
intrusive_ptr(intrusive_ptr<Y>&& other) : m_ptr(nullptr)
{
swap(other);
}
......
......@@ -4,8 +4,8 @@
#include <type_traits>
#include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/util/type_at.hpp"
#include "cppa/util/type_list.hpp"
......@@ -15,7 +15,7 @@
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>
struct invoke_helper
{
......@@ -31,7 +31,7 @@ struct invoke_helper
}
};
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...>
{
inline static void _(F& f, const Tuple&, const Args&... args)
......@@ -46,7 +46,7 @@ struct invoke_impl
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)
{
......@@ -62,7 +62,7 @@ struct invoke_impl<false, Tuple, F>
typedef typename util::callable_trait<decltype(&F::operator())>::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)
{
......
......@@ -36,7 +36,7 @@ struct invoke_rules
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)
{
......@@ -45,7 +45,7 @@ struct invoke_rules
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;
for (auto i = m_list.begin(); i != m_list.end(); ++i)
......
......@@ -5,8 +5,8 @@
#include <stdexcept>
#include "cppa/any_type.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/util/compare_tuples.hpp"
#include "cppa/util/type_list.hpp"
......@@ -19,7 +19,7 @@
namespace cppa {
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 end = what.types().end();
......@@ -27,7 +27,7 @@ bool match(const untyped_tuple& what)
}
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 end = what.types().end();
......@@ -35,8 +35,8 @@ bool match(const untyped_tuple& what, std::vector<std::size_t>& mappings)
}
template<typename... MatchRules, class ValuesTuple>
bool match(const untyped_tuple& what, const ValuesTuple& vals,
std::vector<std::size_t>& mappings)
bool match(const any_tuple& what, const ValuesTuple& vals,
std::vector<size_t>& mappings)
{
typedef util::type_list<MatchRules...> rules_list;
typedef typename util::filter_type_list<any_type, rules_list>::type
......@@ -49,7 +49,7 @@ bool match(const untyped_tuple& what, const ValuesTuple& vals,
"given values are not comparable to matched types");
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));
return compare_first_elements(view, vals);
}
......@@ -57,42 +57,12 @@ bool match(const untyped_tuple& what, const ValuesTuple& vals,
}
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);
}
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
#endif // MATCH_HPP
......@@ -4,7 +4,8 @@
#include "cppa/actor.hpp"
#include "cppa/tuple.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/detail/channel.hpp"
......@@ -14,32 +15,29 @@ namespace cppa {
class message
{
struct content : ref_counted
struct msg_content : ref_counted
{
const actor_ptr sender;
const channel_ptr receiver;
const untyped_tuple data;
inline content(const actor_ptr& s,
const any_tuple data;
inline msg_content(const actor_ptr& s,
const channel_ptr& r,
const untyped_tuple& ut)
const any_tuple& ut)
: ref_counted(), sender(s), receiver(r), data(ut)
{
}
};
intrusive_ptr<content> m_content;
intrusive_ptr<msg_content> m_content;
public:
template<typename... 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, const channel_ptr& to, const Args&... args);
message(const actor_ptr& from,
const channel_ptr& to,
const untyped_tuple& ut);
const any_tuple& ut);
message();
......@@ -61,13 +59,19 @@ class message
return m_content->receiver;
}
inline const untyped_tuple& data() const
inline const any_tuple& content() const
{
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);
inline bool operator!=(const message& lhs, const message& rhs)
......
......@@ -13,9 +13,9 @@ namespace cppa {
// forward declarations
class object;
class uniform_type_info;
const uniform_type_info* uniform_typeid(const std::type_info&);
namespace detail { template<typename T> struct object_caster; }
bool operator==(const uniform_type_info& lhs, const std::type_info& rhs);
/**
* @brief foobar.
*/
......@@ -34,6 +34,9 @@ class object
object copy() const;
static void* new_instance(const uniform_type_info* type,
const void* from);
public:
/**
......@@ -44,21 +47,26 @@ public:
object(void* val, const uniform_type_info* utinfo);
/**
* @brief Create a void object.
* @post {@code type() == uniform_typeid<util::void_type>()}
* @brief Create an empty object.
* @post {@code empty() && type() == *uniform_typeid<util::void_type>()}
*/
object();
template<typename T>
explicit object(const T& what);
~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>()}
*/
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);
......@@ -70,17 +78,34 @@ public:
object& operator=(const object& other);
bool equal(const object& other) const;
bool equal_to(const object& other) const;
const uniform_type_info& type() 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)
{
return lhs.equal(rhs);
return lhs.equal_to(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)
}
}
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
template<typename T>
......@@ -121,7 +131,8 @@ T& get_ref(object& obj)
static_assert(util::disjunction<std::is_pointer<T>,
std::is_reference<T>>::value == false,
"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>
......@@ -130,7 +141,8 @@ const T& get(const object& obj)
static_assert(util::disjunction<std::is_pointer<T>,
std::is_reference<T>>::value == false,
"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
......
......@@ -2,8 +2,8 @@
#define ON_HPP
#include "cppa/match.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/util/eval_first_n.hpp"
#include "cppa/util/filter_type_list.hpp"
......@@ -13,11 +13,11 @@
namespace cppa { namespace detail {
// 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 bool value_cmp(const untyped_tuple&,
std::vector<std::size_t>&) const = 0;
virtual bool value_cmp(const any_tuple&,
std::vector<size_t>&) const = 0;
};
template<typename... Types>
......@@ -56,8 +56,8 @@ struct invoke_rule_builder
{
}
virtual bool value_cmp(const untyped_tuple& t,
std::vector<std::size_t>& v) const
virtual bool value_cmp(const any_tuple& t,
std::vector<size_t>& v) const
{
return match<Types...>(t, m_values, v);
}
......@@ -85,9 +85,9 @@ struct invoke_rule_builder
};
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))
{
tuple_view_type tv(t.vals(), std::move(mappings));
......@@ -96,9 +96,9 @@ struct invoke_rule_builder
}
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))
{
tuple_view_type tv(t.vals(), std::move(mappings));
......@@ -110,9 +110,9 @@ struct invoke_rule_builder
}
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))
{
tuple_view_type tv(t.vals(), std::move(mappings));
......@@ -121,9 +121,9 @@ struct invoke_rule_builder
}
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))
{
tuple_view_type tv(t.vals(), std::move(mappings));
......
......@@ -12,7 +12,7 @@ namespace cppa {
* @brief (Thread safe) base class for reference counted objects
* 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
......
......@@ -63,13 +63,16 @@ struct chars_to_string
namespace cppa {
// forward declaration
class untyped_tuple;
class any_tuple;
/**
* @brief Describes a fixed-length tuple.
*/
template<typename... ElementTypes>
class tuple
{
friend class untyped_tuple;
friend class any_tuple;
public:
......@@ -110,29 +113,29 @@ class tuple
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(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
{
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()
{
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(); }
......@@ -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&
get(const tuple<Types...>& t)
{
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&
get_ref(tuple<Types...>& t)
{
......
......@@ -4,7 +4,6 @@
#include <vector>
#include "cppa/tuple.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/a_matches_b.hpp"
......@@ -14,6 +13,14 @@
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>
class tuple_view
{
......@@ -27,38 +34,42 @@ class tuple_view
typedef cow_ptr<detail::abstract_tuple> vals_t;
tuple_view(const vals_t& vals, std::vector<std::size_t>&& mappings)
tuple_view(const vals_t& vals, std::vector<size_t>&& mappings)
: 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; }
typedef typename element_types::head_type head_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; }
template<std::size_t N>
template<size_t N>
const typename util::type_at<N, element_types>::type& get() const
{
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));
}
template<std::size_t N>
template<size_t N>
typename util::type_at<N, element_types>::type& get_ref()
{
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));
}
std::size_t size() const { return m_vals->size(); }
size_t size() const { return m_vals->size(); }
private:
......@@ -67,14 +78,14 @@ class tuple_view
};
template<std::size_t N, typename... Types>
template<size_t N, typename... Types>
const typename util::type_at<N, util::type_list<Types...>>::type&
get(const tuple_view<Types...>& t)
{
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&
get_ref(tuple_view<Types...>& t)
{
......
......@@ -146,13 +146,18 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
*/
object deserialize(deserializer* source) const;
protected:
/**
* @brief Compares two instances of this type.
*/
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
* @p instance or initialized with the default constructor
......@@ -160,11 +165,6 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
*/
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:
/**
......
#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
#define ABSTRACT_TYPE_LIST_HPP
#include <iterator>
#include <memory>
// forward declaration
namespace cppa { class uniform_type_info; }
......@@ -11,67 +11,101 @@ namespace cppa { namespace util {
struct abstract_type_list
{
class const_iterator : public std::iterator<std::bidirectional_iterator_tag,
const uniform_type_info*>
class abstract_iterator
{
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:
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;
return !(*this == other);
}
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 *this;
return &(m_iter->get());
}
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* copy() const = 0;
virtual const_iterator begin() const = 0;
virtual const_iterator end() const = 0;
virtual const uniform_type_info* at(std::size_t pos) const = 0;
virtual const_iterator end() const;
};
......
#ifndef UNIFORM_TYPE_INFO_BASE_HPP
#define UNIFORM_TYPE_INFO_BASE_HPP
#ifndef ABSTRACT_UNIFORM_TYPE_INFO_HPP
#define ABSTRACT_UNIFORM_TYPE_INFO_HPP
#include "cppa/uniform_type_info.hpp"
#include "cppa/detail/to_uniform_name.hpp"
......@@ -11,7 +11,7 @@ namespace cppa { namespace util {
* except serialize() and deserialize().
*/
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)
......@@ -26,7 +26,7 @@ class uniform_type_info_base : public uniform_type_info
protected:
uniform_type_info_base(const std::string& uname
abstract_uniform_type_info(const std::string& uname
= detail::to_uniform_name(typeid(T)))
: uniform_type_info(uname)
{
......@@ -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 @@
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&
do_get(const Tuple<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
{
inline static bool cmp(const LhsTuple& lhs, const RhsTuple& rhs)
......@@ -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
{
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>
{
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_
{
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
......
......@@ -9,12 +9,12 @@
namespace cppa { namespace util {
template <std::size_t N,
template <size_t N,
class ListA, class ListB,
template <typename, typename> class What>
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>
struct eval_first_n<N, type_list<TypesA...>, type_list<TypesB...>, What>
{
......
......@@ -22,7 +22,7 @@ struct if_t<true, IfType, ElseType>
typedef IfType type;
};
template<std::size_t N, typename List>
template<size_t N, typename List>
struct n_
{
......@@ -48,10 +48,10 @@ struct n_<0, List>
namespace cppa { namespace util {
template<std::size_t N, typename List>
template<size_t N, typename List>
struct first_n;
template<std::size_t N, typename... ListTypes>
template<size_t N, typename... ListTypes>
struct first_n<N, util::type_list<ListTypes...>>
{
typedef typename detail::n_<N, util::type_list<ListTypes...>>::type type;
......
#ifndef CPPA_UTIL_TYPE_AT_HPP
#define CPPA_UTIL_TYPE_AT_HPP
// std::size_t
// size_t
#include <cstddef>
#include "cppa/util/type_list.hpp"
namespace cppa { namespace util {
template<std::size_t N, typename TypeList>
template<size_t N, typename TypeList>
struct type_at
{
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&);
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<>
......@@ -24,7 +59,7 @@ struct type_list<>
{
typedef void_type head_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>
......@@ -35,7 +70,7 @@ struct type_list<Head, Tail...> : abstract_type_list
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()
{
......@@ -44,17 +79,12 @@ struct type_list<Head, Tail...> : abstract_type_list
virtual const_iterator begin() const
{
return m_arr;
}
virtual const_iterator end() const
{
return m_arr + type_list_size;
return new type_list_iterator(m_arr, 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
......
#!/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
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/announce.hpp \
cppa/any_tuple.hpp \
cppa/any_type.hpp \
cppa/binary_deserializer.hpp \
cppa/binary_serializer.hpp \
......@@ -15,6 +16,7 @@ HEADERS = cppa/actor.hpp \
cppa/cppa.hpp \
cppa/deserializer.hpp \
cppa/get.hpp \
cppa/get_view.hpp \
cppa/group.hpp \
cppa/intrusive_ptr.hpp \
cppa/invoke.hpp \
......@@ -33,31 +35,58 @@ HEADERS = cppa/actor.hpp \
cppa/tuple.hpp \
cppa/tuple_view.hpp \
cppa/uniform_type_info.hpp \
cppa/untyped_tuple.hpp \
cppa/util.hpp \
cppa/detail/abstract_tuple.hpp \
cppa/detail/blocking_message_queue.hpp \
cppa/detail/channel.hpp \
cppa/detail/converted_thread_context.hpp \
cppa/detail/cpp0x_thread_wrapper.hpp \
cppa/detail/decorated_tuple.hpp \
cppa/detail/channel.hpp \
cppa/detail/default_uniform_type_info_impl.hpp \
cppa/detail/demangle.hpp \
cppa/detail/intermediate.hpp \
cppa/detail/invokable.hpp \
cppa/detail/list_member.hpp \
cppa/detail/map_member.hpp \
cppa/detail/matcher.hpp \
cppa/detail/mock_scheduler.hpp \
cppa/detail/object_array.hpp \
cppa/detail/object_impl.hpp \
cppa/detail/pair_member.hpp \
cppa/detail/primitive_member.hpp \
cppa/detail/ptype_to_type.hpp \
cppa/detail/ref_counted_impl.hpp \
cppa/detail/serialize_tuple.hpp \
cppa/detail/swap_bytes.hpp \
cppa/detail/tdata.hpp \
cppa/detail/to_uniform_name.hpp \
cppa/detail/tuple_vals.hpp \
cppa/detail/type_to_ptype.hpp \
cppa/util/a_matches_b.hpp \
cppa/util/abstract_type_list.hpp \
cppa/util/abstract_uniform_type_info.hpp \
cppa/util/apply.hpp \
cppa/util/callable_trait.hpp \
cppa/util/comparable.hpp \
cppa/util/compare_tuples.hpp \
cppa/util/concat_type_lists.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 \
......@@ -65,17 +94,22 @@ HEADERS = cppa/actor.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/void_type.hpp \
cppa/util/wrapped_type.hpp
SOURCES = src/abstract_type_list.cpp \
SOURCES = \
src/abstract_type_list.cpp \
src/actor.cpp \
src/actor_behavior.cpp \
src/any_tuple.cpp \
src/binary_deserializer.cpp \
src/binary_serializer.cpp \
src/blocking_message_queue.cpp \
......@@ -88,13 +122,13 @@ SOURCES = src/abstract_type_list.cpp \
src/message.cpp \
src/mock_scheduler.cpp \
src/object.cpp \
src/object_array.cpp \
src/primitive_variant.cpp \
src/scheduler.cpp \
src/serializer.cpp \
src/shared_spinlock.cpp \
src/to_uniform_name.cpp \
src/uniform_type_info.cpp \
src/untyped_tuple.cpp
src/uniform_type_info.cpp
OBJECTS = $(SOURCES:.cpp=.o)
......@@ -110,4 +144,3 @@ all : $(LIB_NAME) $(OBJECTS)
clean:
rm -f $(LIB_NAME) $(OBJECTS)
......@@ -6,20 +6,13 @@ abstract_type_list::~abstract_type_list()
{
}
abstract_type_list::const_iterator
abstract_type_list::const_iterator::operator++(int)
abstract_type_list::const_iterator abstract_type_list::end() const
{
const_iterator tmp(*this);
operator++();
return tmp;
return const_iterator(nullptr);
}
abstract_type_list::const_iterator
abstract_type_list::const_iterator::operator--(int)
abstract_type_list::abstract_iterator::~abstract_iterator()
{
const_iterator tmp(*this);
operator--();
return tmp;
}
} } // 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)
queue_node* amsg = m_queue.pop();
util::singly_linked_list<queue_node> buffer;
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);
amsg = m_queue.pop();
......
......@@ -46,7 +46,8 @@ void converted_thread_context::join(group_ptr& what)
std::lock_guard<std::mutex> guard(m_mtx);
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);
}
}
......
#include "cppa/config.hpp"
#include <map>
#include <mutex>
#include <memory>
#include <stdexcept>
#include "cppa/group.hpp"
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()
{
m_group->unsubscribe(m_self);
if (m_group) m_group->unsubscribe(m_self);
}
} // namespace cppa
......@@ -4,12 +4,12 @@ namespace cppa {
message::message(const actor_ptr& from,
const channel_ptr& to,
const untyped_tuple& ut)
: m_content(new content(from, to, ut))
const any_tuple& 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)
{
return lhs.sender() == rhs.sender()
&& lhs.receiver() == rhs.receiver()
&& lhs.data().vals()->equal_to(*(rhs.data().vals()));
&& lhs.content().vals()->equal_to(*(rhs.content().vals()));
}
} // namespace cppa
......@@ -19,13 +19,17 @@ void object::swap(object& other)
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
{
return (m_value != &s_void) ? object(m_type->new_instance(m_value), m_type)
: object();
}
object::object(void* val, const uniform_type_info* utype)
: m_value(val), m_type(utype)
{
......@@ -70,7 +74,7 @@ object& object::operator=(const object& other)
return *this;
}
bool object::equal(const object& other) const
bool object::equal_to(const object& other) const
{
if (m_type == other.m_type)
{
......@@ -90,4 +94,19 @@ std::string object::to_string() const
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
#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 @@
#include "cppa/config.hpp"
#include "cppa/actor.hpp"
#include "cppa/object.hpp"
#include "cppa/announce.hpp"
#include "cppa/any_type.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/detail/demangle.hpp"
#include "cppa/detail/object_array.hpp"
#include "cppa/detail/to_uniform_name.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)
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:
......@@ -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
{
......@@ -164,7 +205,8 @@ class uniform_type_info_map
insert<std::string>();
insert<std::u16string>();
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<cppa::util::void_type>();
if (sizeof(double) == sizeof(long double))
......@@ -236,7 +278,7 @@ class uniform_type_info_map
return nullptr;
}
bool insert(std::set<std::string> plain_names,
bool insert(std::set<std::string> raw_names,
uniform_type_info* what)
{
if (m_by_uname.count(what->name()) > 0)
......@@ -245,7 +287,7 @@ class uniform_type_info_map
return false;
}
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)
{
......@@ -278,7 +320,6 @@ uniform_type_info_map& s_uniform_type_info_map()
} } } // namespace cppa::detail::<anonymous>
namespace {
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)
else
{
std::cout << std::boolalpha;
std::size_t errors = 0;
size_t errors = 0;
RUN_TEST(test__primitive_variant);
RUN_TEST(test__uniform_type);
RUN_TEST(test__intrusive_ptr);
......
......@@ -7,7 +7,7 @@
#define CPPA_TEST(name) \
struct cppa_test_scope \
{ \
std::size_t error_count; \
size_t error_count; \
cppa_test_scope() : error_count(0) { } \
~cppa_test_scope() \
{ \
......@@ -40,18 +40,22 @@ if (!(line_of_code)) \
} ((void) 0)
#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)))
std::size_t test__uniform_type();
std::size_t test__type_list();
std::size_t test__a_matches_b();
std::size_t test__atom();
std::size_t test__tuple();
std::size_t test__spawn();
std::size_t test__intrusive_ptr();
std::size_t test__serialization();
std::size_t test__local_group();
std::size_t test__primitive_variant();
size_t test__uniform_type();
size_t test__type_list();
size_t test__a_matches_b();
size_t test__atom();
size_t test__tuple();
size_t test__spawn();
size_t test__intrusive_ptr();
size_t test__serialization();
size_t test__local_group();
size_t test__primitive_variant();
void test__queue_performance();
......
......@@ -7,7 +7,7 @@
using namespace cppa;
using namespace cppa::util;
std::size_t test__a_matches_b()
size_t test__a_matches_b()
{
CPPA_TEST(test__a_matches_b);
......
......@@ -101,7 +101,7 @@ class atom : public atom_base
};
std::size_t test__atom()
size_t test__atom()
{
CPPA_TEST(test__atom);
......
......@@ -15,7 +15,7 @@ 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; }
......@@ -46,7 +46,7 @@ class0_ptr get_test_ptr()
return get_test_rc();
}
std::size_t test__intrusive_ptr()
size_t test__intrusive_ptr()
{
CPPA_TEST(test__intrusive_ptr);
......
#include "cppa/config.hpp"
#include <map>
#include <list>
#include <mutex>
#include <iostream>
#include <algorithm>
#include "test.hpp"
#include "hash_of.hpp"
......@@ -8,26 +16,17 @@
#include "cppa/ref_counted.hpp"
#include "cppa/intrusive_ptr.hpp"
#include <map>
#include <list>
#include <iostream>
#include <algorithm>
#include <boost/thread/mutex.hpp>
using std::cout;
using std::endl;
/*
using namespace cppa;
namespace {
class local_group : public group
{
boost::mutex m_mtx;
friend class local_group_module;
std::mutex m_mtx;
std::list<channel_ptr> m_subscribers;
inline std::list<channel_ptr>::iterator find(const channel_ptr& what)
......@@ -35,32 +34,34 @@ class local_group : public group
return std::find(m_subscribers.begin(), m_subscribers.end(), what);
}
local_group() = default;
public:
virtual void enqueue(const message& msg)
{
boost::mutex::scoped_lock guard(m_mtx);
std::lock_guard<std::mutex> 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)
virtual group::subscription subscribe(const channel_ptr& who)
{
boost::mutex::scoped_lock guard(m_mtx);
std::lock_guard<std::mutex> guard(m_mtx);
auto i = find(who);
if (i == m_subscribers.end())
{
m_subscribers.push_back(who);
return new group::subscription(who, this);
return { who, this };
}
return new group::subscription(0, 0);
return { nullptr, nullptr };
}
virtual void unsubscribe(const channel_ptr& who)
{
boost::mutex::scoped_lock guard(m_mtx);
std::lock_guard<std::mutex> guard(m_mtx);
auto i = find(who);
if (i != m_subscribers.end())
{
......@@ -70,102 +71,64 @@ class local_group : public group
};
//local_group* m_local_group = new local_group;
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;
std::map<std::string, group_ptr> m_instances;
struct storage
{
std::map<std::string, intrusive_ptr<object>> m_map;
public:
template<typename T>
T& get(const std::string& key)
local_group_module() : m_name("local")
{
auto uti = uniform_type_info::by_type_info(typeid(T));
auto i = m_map.find(key);
if (i == m_map.end())
}
const std::string& name()
{
i = m_map.insert(std::make_pair(key, uti->create())).first;
return m_name;
}
else if (uti != i->second->type())
group_ptr get(const std::string& group_name)
{
// todo: throw nicer exception
throw std::runtime_error("invalid type");
std::lock_guard<std::mutex> guard(m_mtx);
auto i = m_instances.find(group_name);
if (i == m_instances.end())
{
group_ptr result(new local_group);
m_instances.insert(std::make_pair(group_name, result));
return result;
}
return *reinterpret_cast<T*>(i->second->mutable_value());
else return i->second;
}
};
void consumer(actor_ptr main_actor)
{
int result = 0;
for (int i = 0; i < 5; ++i)
{
receive(on<int>() >> [&](int x) {
result += x;
});
}
send(main_actor, result);
}
void producer(actor_ptr consume_actor)
void worker()
{
receive(on<int>() >> [&](int i) {
send(consume_actor, i);
receive(on<int>() >> [](int value) {
reply(value);
});
}
std::size_t test__local_group()
size_t test__local_group()
{
CPPA_TEST(test__local_group);
std::list<intrusive_ptr<group::subscription>> m_subscriptions;
actor_ptr self_ptr = self();
auto consume_actor = spawn(consumer, self_ptr);
auto lg = local("foobar");
group::add_module(new local_group_module);
auto foo_group = group::get("local", "foo");
for (int i = 0; i < 5; ++i)
{
auto fa = spawn(producer, consume_actor);
auto sptr = lg->subscribe(fa);
m_subscriptions.push_back(sptr);
// spawn workers in group local:foo
spawn(worker)->join(foo_group);
}
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);
send(foo_group, 2);
int result = 0;
for (int i = 0; i < 5; ++i)
{
receive(on<int>() >> [&result](int value) { result += value; });
}
CPPA_CHECK_EQUAL(result, 10);
await_all_others_done();
return CPPA_TEST_RESULT;
}
......@@ -4,7 +4,7 @@
using namespace cppa;
std::size_t test__primitive_variant()
size_t test__primitive_variant()
{
CPPA_TEST(test__primitive_variant);
std::uint32_t forty_two = 42;
......
......@@ -18,8 +18,8 @@ using std::endl;
struct queue_element
{
queue_element* next;
std::size_t value;
queue_element(std::size_t val) : next(0), value(val) { }
size_t value;
queue_element(size_t val) : next(0), value(val) { }
};
template<typename T>
......@@ -128,46 +128,46 @@ class locked_queue
namespace {
//const std::size_t num_slaves = 1000;
//const std::size_t num_slave_msgs = 90000;
//const size_t num_slaves = 1000;
//const size_t num_slave_msgs = 90000;
// 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
// (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>
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));
}
}
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)
{
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;
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;
std::size_t to = from + num_slave_msgs;
size_t from = (i * num_slave_msgs) + 1;
size_t to = from + num_slave_msgs;
boost::thread(slave<Queue>, boost::ref(q), from, to).detach();
}
std::size_t result = 0;
std::size_t min_val = calc_result;
std::size_t max_val = 0;
for (std::size_t i = 0; i < num_msgs; ++i)
size_t result = 0;
size_t min_val = calc_result;
size_t max_val = 0;
for (size_t i = 0; i < num_msgs; ++i)
{
queue_element* e = q.pop();
result += e->value;
......@@ -185,10 +185,10 @@ void master(Queue& q)
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<std::size_t> class Stmt>
template<size_t Pos, size_t Max, size_t Step,
template<size_t> class Stmt>
struct static_for
{
template<typename... Args>
......@@ -199,8 +199,8 @@ struct static_for
}
};
template<std::size_t Max, std::size_t Step,
template<std::size_t> class Stmt>
template<size_t Max, size_t Step,
template<size_t> class Stmt>
struct static_for<Max, Max, Step, Stmt>
{
template<typename... Args>
......@@ -216,7 +216,7 @@ struct type_token
typedef What type;
};
template<std::size_t NumThreads>
template<size_t NumThreads>
struct test_step
{
template<typename QueueToken>
......
......@@ -25,10 +25,11 @@
#include "cppa/tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/announce.hpp"
#include "cppa/get_view.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/serializer.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/primitive_type.hpp"
#include "cppa/primitive_variant.hpp"
#include "cppa/binary_serializer.hpp"
......@@ -42,8 +43,9 @@
#include "cppa/util/if_else_type.hpp"
#include "cppa/util/wrapped_type.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/ptype_to_type.hpp"
#include "cppa/detail/default_uniform_type_info_impl.hpp"
......@@ -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:
......@@ -380,20 +382,21 @@ class message_uti : public util::uniform_type_info_base<message>
virtual void serialize(const void* instance, serializer* sink) const
{
const message& msg = *reinterpret_cast<const message*>(instance);
const untyped_tuple& data = msg.data();
sink->begin_object("cppa::message");
sink->begin_sequence(data.size());
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();
const any_tuple& data = msg.content();
sink->begin_object(name());
uniform_typeid<any_tuple>()->serialize(&data, sink);
sink->end_object();
}
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)
return osstr.str();
}
std::size_t test__serialization()
size_t test__serialization()
{
CPPA_TEST(test__serialization);
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);
// std::string is primitive and thus not identified by is_iterable
......
......@@ -19,7 +19,7 @@ void pong()
});
}
std::size_t test__spawn()
size_t test__spawn()
{
CPPA_TEST(test__spawn);
{
......@@ -30,6 +30,6 @@ std::size_t test__spawn()
CPPA_CHECK_EQUAL(value, 42);
});
}
await_all_actors_done();
await_all_others_done();
return CPPA_TEST_RESULT;
}
......@@ -12,10 +12,11 @@
#include "cppa/tuple.hpp"
#include "cppa/match.hpp"
#include "cppa/invoke.hpp"
#include "cppa/get_view.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/detail/invokable.hpp"
......@@ -39,7 +40,7 @@ void fun(const std::string&)
} // namespace <anonymous>
std::size_t test__tuple()
size_t test__tuple()
{
CPPA_TEST(test__tuple);
......@@ -58,14 +59,14 @@ std::size_t test__tuple()
tuple<int, std::string, int> t5(42, "foo", 24);
tuple<int> t6;
// untyped tuples under test
untyped_tuple ut0 = t1;
any_tuple ut0 = t1;
// tuple views under test
auto tv0 = get_view<any_type*, float, any_type*, int, any_type>(t1);
auto tv1 = get_view<any_type*, int, any_type*>(tv0);
auto tv2 = get_view<int, any_type*, std::string>(t1);
auto tv3 = get_view<any_type*, int, std::string>(t1);
// untyped_tuple ut1 = tv0;
// any_tuple ut1 = tv0;
CPPA_CHECK(t6.get<0>() == 0);
CPPA_CHECK(tv2.get<0>() == t1.get<0>());
......@@ -86,7 +87,7 @@ std::size_t test__tuple()
}
{
std::vector<std::size_t> tv3_mappings;
std::vector<size_t> tv3_mappings;
match<any_type*, int, std::string>(t1, tv3_mappings);
CPPA_CHECK_EQUAL(tv3_mappings.size(), 2);
CPPA_CHECK(tv3_mappings[0] == 2);
......
......@@ -14,7 +14,7 @@ using std::is_same;
using namespace cppa::util;
std::size_t test__type_list()
size_t test__type_list()
{
CPPA_TEST(test__type_list);
......
......@@ -15,6 +15,7 @@
#include "test.hpp"
#include "cppa/get_view.hpp"
#include "cppa/announce.hpp"
#include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp"
......@@ -57,7 +58,7 @@ bool announce4 = announce<foo>(&foo::value);
} // namespace <anonymous>
std::size_t test__uniform_type()
size_t test__uniform_type()
{
CPPA_TEST(test__uniform_type);
{
......@@ -85,8 +86,10 @@ std::size_t test__uniform_type()
"@str", "@u16str", "@u32str", // strings
"float", "double", // floating points
"@0", // cppa::util::void_type
"cppa::any_type", // default announced cppa type
"cppa::intrusive_ptr<cppa::actor>" // default announced cppa type
// default announced cppa types
"cppa::any_type",
"cppa::any_tuple",
"cppa::intrusive_ptr<cppa::actor>"
};
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