Commit 68086d89 authored by neverlord's avatar neverlord

tuple -> cow_tuple + pattern tweaks

parent 964a41f5
...@@ -83,6 +83,7 @@ nobase_library_include_HEADERS = \ ...@@ -83,6 +83,7 @@ nobase_library_include_HEADERS = \
cppa/channel.hpp \ cppa/channel.hpp \
cppa/config.hpp \ cppa/config.hpp \
cppa/cow_ptr.hpp \ cppa/cow_ptr.hpp \
cppa/cow_tuple.hpp \
cppa/cppa.hpp \ cppa/cppa.hpp \
cppa/deserializer.hpp \ cppa/deserializer.hpp \
cppa/detail/abstract_scheduled_actor.hpp \ cppa/detail/abstract_scheduled_actor.hpp \
...@@ -172,7 +173,6 @@ nobase_library_include_HEADERS = \ ...@@ -172,7 +173,6 @@ nobase_library_include_HEADERS = \
cppa/serializer.hpp \ cppa/serializer.hpp \
cppa/stacked_event_based_actor.hpp \ cppa/stacked_event_based_actor.hpp \
cppa/to_string.hpp \ cppa/to_string.hpp \
cppa/tuple.hpp \
cppa/tuple_cast.hpp \ cppa/tuple_cast.hpp \
cppa/type_value_pair.hpp \ cppa/type_value_pair.hpp \
cppa/uniform_type_info.hpp \ cppa/uniform_type_info.hpp \
......
...@@ -59,7 +59,7 @@ struct testee : fsm_actor<testee> ...@@ -59,7 +59,7 @@ struct testee : fsm_actor<testee>
}, },
on(atom("spread"), arg_match) >> [=](int x) on(atom("spread"), arg_match) >> [=](int x)
{ {
any_tuple msg = make_tuple(atom("spread"), x - 1); any_tuple msg = make_cow_tuple(atom("spread"), x - 1);
spawn(new testee(this)) << msg; spawn(new testee(this)) << msg;
spawn(new testee(this)) << msg; spawn(new testee(this)) << msg;
become become
...@@ -91,7 +91,7 @@ void stacked_testee(actor_ptr parent) ...@@ -91,7 +91,7 @@ void stacked_testee(actor_ptr parent)
}, },
on(atom("spread"), arg_match) >> [&](int x) on(atom("spread"), arg_match) >> [&](int x)
{ {
any_tuple msg = make_tuple(atom("spread"), x-1); any_tuple msg = make_cow_tuple(atom("spread"), x-1);
spawn(stacked_testee, self) << msg; spawn(stacked_testee, self) << msg;
spawn(stacked_testee, self) << msg; spawn(stacked_testee, self) << msg;
receive receive
......
...@@ -79,7 +79,7 @@ void receiver(int64_t max) ...@@ -79,7 +79,7 @@ void receiver(int64_t max)
void sender(actor_ptr whom, int64_t count) void sender(actor_ptr whom, int64_t count)
{ {
any_tuple msg = make_tuple(atom("msg")); any_tuple msg = make_cow_tuple(atom("msg"));
for (int64_t i = 0; i < count; ++i) for (int64_t i = 0; i < count; ++i)
{ {
whom->enqueue(nullptr, msg); whom->enqueue(nullptr, msg);
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#include "cppa/on.hpp" #include "cppa/on.hpp"
#include "cppa/atom.hpp" #include "cppa/atom.hpp"
#include "cppa/match.hpp" #include "cppa/match.hpp"
#include "cppa/tuple.hpp" #include "cppa/cow_tuple.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
using std::cout; using std::cout;
...@@ -77,12 +77,12 @@ int main(int argc, char** argv) ...@@ -77,12 +77,12 @@ int main(int argc, char** argv)
return 1; return 1;
} }
auto num_loops = rd<int64_t>(argv[1]); auto num_loops = rd<int64_t>(argv[1]);
any_tuple m1 = make_tuple(atom("msg1"), 0); any_tuple m1 = make_cow_tuple(atom("msg1"), 0);
any_tuple m2 = make_tuple(atom("msg2"), 0.0); any_tuple m2 = make_cow_tuple(atom("msg2"), 0.0);
any_tuple m3 = cppa::make_tuple(atom("msg3"), list<int>{0}); any_tuple m3 = cppa::make_cow_tuple(atom("msg3"), list<int>{0});
any_tuple m4 = make_tuple(atom("msg4"), 0, "0"); any_tuple m4 = make_cow_tuple(atom("msg4"), 0, "0");
any_tuple m5 = make_tuple(atom("msg5"), 0, 0, 0); any_tuple m5 = make_cow_tuple(atom("msg5"), 0, 0, 0);
any_tuple m6 = make_tuple(atom("msg6"), 0, 0.0, "0"); any_tuple m6 = make_cow_tuple(atom("msg6"), 0, 0.0, "0");
int64_t m1matched = 0; int64_t m1matched = 0;
int64_t m2matched = 0; int64_t m2matched = 0;
int64_t m3matched = 0; int64_t m3matched = 0;
......
cppa/ref_counted.hpp cppa/ref_counted.hpp
cppa/tuple.hpp cppa/cow_tuple.hpp
unit_testing/main.cpp unit_testing/main.cpp
cppa/util/void_type.hpp cppa/util/void_type.hpp
cppa/util/type_list.hpp cppa/util/type_list.hpp
......
...@@ -166,7 +166,7 @@ class abstract_actor : public Base ...@@ -166,7 +166,7 @@ class abstract_actor : public Base
// send exit message without lock // send exit message without lock
if (reason != exit_reason::not_exited) if (reason != exit_reason::not_exited)
{ {
other->enqueue(this, make_tuple(atom(":Exit"), reason)); other->enqueue(this, make_cow_tuple(atom(":Exit"), reason));
} }
return false; return false;
} }
...@@ -210,7 +210,7 @@ class abstract_actor : public Base ...@@ -210,7 +210,7 @@ class abstract_actor : public Base
// send exit messages // send exit messages
for (actor_ptr& aptr : mlinks) for (actor_ptr& aptr : mlinks)
{ {
aptr->enqueue(this, make_tuple(atom(":Exit"), reason)); aptr->enqueue(this, make_cow_tuple(atom(":Exit"), reason));
} }
for (attachable_ptr& ptr : mattachables) for (attachable_ptr& ptr : mattachables)
{ {
...@@ -226,7 +226,7 @@ class abstract_actor : public Base ...@@ -226,7 +226,7 @@ class abstract_actor : public Base
// send exit message if already exited // send exit message if already exited
if (exited()) if (exited())
{ {
other->enqueue(this, make_tuple(atom(":Exit"), other->enqueue(this, make_cow_tuple(atom(":Exit"),
m_exit_reason.load())); m_exit_reason.load()));
} }
// add link if not already linked to other // add link if not already linked to other
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#include <iostream> #include <iostream>
#include "cppa/tuple.hpp" #include "cppa/cow_tuple.hpp"
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/cow_ptr.hpp" #include "cppa/cow_ptr.hpp"
...@@ -69,13 +69,13 @@ class any_tuple ...@@ -69,13 +69,13 @@ class any_tuple
* @brief Creates a tuple from @p t. * @brief Creates a tuple from @p t.
*/ */
template<typename... Args> template<typename... Args>
any_tuple(tuple<Args...> const& t) : m_vals(t.vals()) { } any_tuple(cow_tuple<Args...> const& t) : m_vals(t.vals()) { }
/** /**
* @brief Creates a tuple and moves the content from @p t. * @brief Creates a tuple and moves the content from @p t.
*/ */
template<typename... Args> template<typename... Args>
any_tuple(tuple<Args...>&& t) : m_vals(std::move(t.m_vals)) { } any_tuple(cow_tuple<Args...>&& t) : m_vals(std::move(t.m_vals)) { }
explicit any_tuple(detail::abstract_tuple*); explicit any_tuple(detail::abstract_tuple*);
......
...@@ -60,17 +60,17 @@ class local_actor; ...@@ -60,17 +60,17 @@ class local_actor;
/** /**
* @ingroup CopyOnWrite * @ingroup CopyOnWrite
* @brief A fixed-length copy-on-write tuple. * @brief A fixed-length copy-on-write cow_tuple.
*/ */
template<typename... ElementTypes> template<typename... ElementTypes>
class tuple class cow_tuple
{ {
static_assert(sizeof...(ElementTypes) > 0, "tuple is empty"); static_assert(sizeof...(ElementTypes) > 0, "tuple is empty");
static_assert(util::tl_forall<util::type_list<ElementTypes...>, static_assert(util::tl_forall<util::type_list<ElementTypes...>,
util::is_legal_tuple_type>::value, util::is_legal_tuple_type>::value,
"illegal types in tuple definition: " "illegal types in cow_tuple definition: "
"pointers and references are prohibited"); "pointers and references are prohibited");
friend class any_tuple; friend class any_tuple;
...@@ -82,7 +82,7 @@ class tuple ...@@ -82,7 +82,7 @@ class tuple
struct priv_ctor { }; struct priv_ctor { };
tuple(priv_ctor, cow_ptr<detail::abstract_tuple>&& ptr) : m_vals(std::move(ptr)) { } cow_tuple(priv_ctor, cow_ptr<detail::abstract_tuple>&& ptr) : m_vals(std::move(ptr)) { }
public: public:
...@@ -94,50 +94,50 @@ class tuple ...@@ -94,50 +94,50 @@ class tuple
/** /**
* @brief Initializes each element with its default constructor. * @brief Initializes each element with its default constructor.
*/ */
tuple() : m_vals(new data_type) cow_tuple() : m_vals(new data_type)
{ {
} }
/** /**
* @brief Initializes the tuple with @p args. * @brief Initializes the cow_tuple with @p args.
* @param args Initialization values. * @param args Initialization values.
*/ */
tuple(ElementTypes const&... args) : m_vals(new data_type(args...)) cow_tuple(ElementTypes const&... args) : m_vals(new data_type(args...))
{ {
} }
/** /**
* @brief Initializes the tuple with @p args. * @brief Initializes the cow_tuple with @p args.
* @param args Initialization values. * @param args Initialization values.
*/ */
tuple(ElementTypes&&... args) : m_vals(new data_type(std::move(args)...)) cow_tuple(ElementTypes&&... args) : m_vals(new data_type(std::move(args)...))
{ {
} }
tuple(tuple&&) = default; cow_tuple(cow_tuple&&) = default;
tuple(tuple const&) = default; cow_tuple(cow_tuple const&) = default;
tuple& operator=(tuple&&) = default; cow_tuple& operator=(cow_tuple&&) = default;
tuple& operator=(tuple const&) = default; cow_tuple& operator=(cow_tuple const&) = default;
inline static tuple from(cow_ptr_type ptr) inline static cow_tuple from(cow_ptr_type ptr)
{ {
return {priv_ctor{}, std::move(ptr)}; return {priv_ctor{}, std::move(ptr)};
} }
inline static tuple from(cow_ptr_type ptr, inline static cow_tuple from(cow_ptr_type ptr,
util::fixed_vector<size_t, num_elements> const& mv) util::fixed_vector<size_t, num_elements> const& mv)
{ {
return {priv_ctor{}, decorated_type::create(std::move(ptr), mv)}; return {priv_ctor{}, decorated_type::create(std::move(ptr), mv)};
} }
inline static tuple offset_subtuple(cow_ptr_type ptr, size_t offset) inline static cow_tuple offset_subtuple(cow_ptr_type ptr, size_t offset)
{ {
CPPA_REQUIRE(offset > 0); CPPA_REQUIRE(offset > 0);
return {priv_ctor{}, decorated_type::create(std::move(ptr), offset)}; return {priv_ctor{}, decorated_type::create(std::move(ptr), offset)};
} }
/** /**
* @brief Gets the size of this tuple. * @brief Gets the size of this cow_tuple.
*/ */
inline size_t size() const inline size_t size() const
{ {
...@@ -177,12 +177,12 @@ class tuple ...@@ -177,12 +177,12 @@ class tuple
}; };
template<typename TypeList> template<typename TypeList>
struct tuple_from_type_list; struct cow_tuple_from_type_list;
template<typename... Types> template<typename... Types>
struct tuple_from_type_list< util::type_list<Types...> > struct cow_tuple_from_type_list< util::type_list<Types...> >
{ {
typedef tuple<Types...> type; typedef cow_tuple<Types...> type;
}; };
#ifdef CPPA_DOCUMENTATION #ifdef CPPA_DOCUMENTATION
...@@ -190,87 +190,85 @@ struct tuple_from_type_list< util::type_list<Types...> > ...@@ -190,87 +190,85 @@ struct tuple_from_type_list< util::type_list<Types...> >
/** /**
* @ingroup CopyOnWrite * @ingroup CopyOnWrite
* @brief Gets a const-reference to the <tt>N</tt>th element of @p tup. * @brief Gets a const-reference to the <tt>N</tt>th element of @p tup.
* @param tup The tuple object. * @param tup The cow_tuple object.
* @returns A const-reference of type T, whereas T is the type of the * @returns A const-reference of type T, whereas T is the type of the
* <tt>N</tt>th element of @p tup. * <tt>N</tt>th element of @p tup.
* @relates tuple * @relates cow_tuple
*/ */
template<size_t N, typename T> template<size_t N, typename T>
T const& get(tuple<...> const& tup); T const& get(cow_tuple<...> const& tup);
/** /**
* @ingroup CopyOnWrite * @ingroup CopyOnWrite
* @brief Gets a reference to the <tt>N</tt>th element of @p tup. * @brief Gets a reference to the <tt>N</tt>th element of @p tup.
* @param tup The tuple object. * @param tup The cow_tuple object.
* @returns A reference of type T, whereas T is the type of the * @returns A reference of type T, whereas T is the type of the
* <tt>N</tt>th element of @p tup. * <tt>N</tt>th element of @p tup.
* @note Detaches @p tup if there are two or more references to the tuple data. * @note Detaches @p tup if there are two or more references to the cow_tuple data.
* @relates tuple * @relates cow_tuple
*/ */
template<size_t N, typename T> template<size_t N, typename T>
T& get_ref(tuple<...>& tup); T& get_ref(cow_tuple<...>& tup);
/** /**
* @ingroup ImplicitConversion * @ingroup ImplicitConversion
* @brief Creates a new tuple from @p args. * @brief Creates a new cow_tuple from @p args.
* @param args Values for the tuple elements. * @param args Values for the cow_tuple elements.
* @returns A tuple object containing the values @p args. * @returns A cow_tuple object containing the values @p args.
* @relates tuple * @relates cow_tuple
*/ */
template<typename... Types> template<typename... Args>
tuple<Types...> make_tuple(Types const&... args); cow_tuple<Args...> make_cow_tuple(Args&&... args);
#else #else
template<size_t N, typename... Types> template<size_t N, typename... Types>
const typename util::at<N, Types...>::type& get(tuple<Types...> const& tup) const typename util::at<N, Types...>::type& get(cow_tuple<Types...> const& tup)
{ {
typedef typename util::at<N, Types...>::type result_type; typedef typename util::at<N, Types...>::type result_type;
return *reinterpret_cast<result_type const*>(tup.at(N)); return *reinterpret_cast<result_type const*>(tup.at(N));
} }
template<size_t N, typename... Types> template<size_t N, typename... Types>
typename util::at<N, Types...>::type& get_ref(tuple<Types...>& tup) typename util::at<N, Types...>::type& get_ref(cow_tuple<Types...>& tup)
{ {
typedef typename util::at<N, Types...>::type result_type; typedef typename util::at<N, Types...>::type result_type;
return *reinterpret_cast<result_type*>(tup.mutable_at(N)); return *reinterpret_cast<result_type*>(tup.mutable_at(N));
} }
template<typename... Types> template<typename... Args>
typename tuple_from_type_list< cow_tuple<typename detail::strip_and_convert<Args>::type...>
typename util::tl_apply<util::type_list<Types...>, make_cow_tuple(Args&&... args)
detail::implicit_conversions>::type>::type
make_tuple(Types const&... args)
{ {
return { args... }; return {std::forward<Args>(args)...};
} }
#endif #endif
/** /**
* @brief Compares two tuples. * @brief Compares two cow_tuples.
* @param lhs First tuple object. * @param lhs First cow_tuple object.
* @param rhs Second tuple object. * @param rhs Second cow_tuple object.
* @returns @p true if @p lhs and @p rhs are equal; otherwise @p false. * @returns @p true if @p lhs and @p rhs are equal; otherwise @p false.
* @relates tuple * @relates cow_tuple
*/ */
template<typename... LhsTypes, typename... RhsTypes> template<typename... LhsTypes, typename... RhsTypes>
inline bool operator==(tuple<LhsTypes...> const& lhs, inline bool operator==(cow_tuple<LhsTypes...> const& lhs,
tuple<RhsTypes...> const& rhs) cow_tuple<RhsTypes...> const& rhs)
{ {
return util::compare_tuples(lhs, rhs); return util::compare_tuples(lhs, rhs);
} }
/** /**
* @brief Compares two tuples. * @brief Compares two cow_tuples.
* @param lhs First tuple object. * @param lhs First cow_tuple object.
* @param rhs Second tuple object. * @param rhs Second cow_tuple object.
* @returns @p true if @p lhs and @p rhs are not equal; otherwise @p false. * @returns @p true if @p lhs and @p rhs are not equal; otherwise @p false.
* @relates tuple * @relates cow_tuple
*/ */
template<typename... LhsTypes, typename... RhsTypes> template<typename... LhsTypes, typename... RhsTypes>
inline bool operator!=(tuple<LhsTypes...> const& lhs, inline bool operator!=(cow_tuple<LhsTypes...> const& lhs,
tuple<RhsTypes...> const& rhs) cow_tuple<RhsTypes...> const& rhs)
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include "cppa/on.hpp" #include "cppa/on.hpp"
#include "cppa/atom.hpp" #include "cppa/atom.hpp"
#include "cppa/self.hpp" #include "cppa/self.hpp"
#include "cppa/tuple.hpp" #include "cppa/cow_tuple.hpp"
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/channel.hpp" #include "cppa/channel.hpp"
#include "cppa/receive.hpp" #include "cppa/receive.hpp"
...@@ -140,7 +140,7 @@ ...@@ -140,7 +140,7 @@
* tuple @p x and @p y, whereas @p y is a copy of @p x: * tuple @p x and @p y, whereas @p y is a copy of @p x:
* *
* @code * @code
* auto x = make_tuple(1, 2, 3); * auto x = make_cow_tuple(1, 2, 3);
* auto y = x; * auto y = x;
* @endcode * @endcode
* *
...@@ -193,7 +193,7 @@ ...@@ -193,7 +193,7 @@
* send(a1, atom("hello"), "hello a1!"); * send(a1, atom("hello"), "hello a1!");
* *
* // send a message to a1, a2 and a3 * // send a message to a1, a2 and a3
* auto msg = make_tuple(atom("compute"), 1, 2, 3); * auto msg = make_cow_tuple(atom("compute"), 1, 2, 3);
* auto s = self; // cache self pointer * auto s = self; // cache self pointer
* // note: this is more efficient then using send() three times because * // note: this is more efficient then using send() three times because
* // send() would create a new tuple each time; * // send() would create a new tuple each time;
...@@ -385,7 +385,7 @@ ...@@ -385,7 +385,7 @@
* send(self, u"hello unicode world!"); * send(self, u"hello unicode world!");
* *
* // x has the type cppa::tuple<std::string, std::string> * // x has the type cppa::tuple<std::string, std::string>
* auto x = make_tuple("hello", "tuple"); * auto x = make_cow_tuple("hello", "tuple");
* *
* receive * receive
* ( * (
...@@ -551,7 +551,7 @@ void send(channel_ptr& whom, Arg0 const& arg0, Args const&... args); ...@@ -551,7 +551,7 @@ void send(channel_ptr& whom, Arg0 const& arg0, Args const&... args);
* *
* <b>Usage example:</b> * <b>Usage example:</b>
* @code * @code
* self << make_tuple(1, 2, 3); * self << make_cow_tuple(1, 2, 3);
* @endcode * @endcode
* @returns @p whom. * @returns @p whom.
*/ */
...@@ -563,7 +563,7 @@ template<class C, typename Arg0, typename... Args> ...@@ -563,7 +563,7 @@ template<class C, typename Arg0, typename... Args>
void send(intrusive_ptr<C>& whom, Arg0 const& arg0, Args const&... args) void send(intrusive_ptr<C>& whom, Arg0 const& arg0, Args const&... args)
{ {
static_assert(std::is_base_of<channel, C>::value, "C is not a channel"); static_assert(std::is_base_of<channel, C>::value, "C is not a channel");
if (whom) whom->enqueue(self, make_tuple(arg0, args...)); if (whom) whom->enqueue(self, make_cow_tuple(arg0, args...));
} }
template<class C, typename Arg0, typename... Args> template<class C, typename Arg0, typename... Args>
...@@ -571,14 +571,14 @@ void send(intrusive_ptr<C>&& whom, Arg0 const& arg0, Args const&... args) ...@@ -571,14 +571,14 @@ void send(intrusive_ptr<C>&& whom, Arg0 const& arg0, Args const&... args)
{ {
static_assert(std::is_base_of<channel, C>::value, "C is not a channel"); static_assert(std::is_base_of<channel, C>::value, "C is not a channel");
intrusive_ptr<C> tmp(std::move(whom)); intrusive_ptr<C> tmp(std::move(whom));
if (tmp) tmp->enqueue(self, make_tuple(arg0, args...)); if (tmp) tmp->enqueue(self, make_cow_tuple(arg0, args...));
} }
// matches "send(this, ...)" in event-based actors // matches "send(this, ...)" in event-based actors
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
void send(local_actor* whom, Arg0 const& arg0, Args const&... args) void send(local_actor* whom, Arg0 const& arg0, Args const&... args)
{ {
whom->enqueue(whom, make_tuple(arg0, args...)); whom->enqueue(whom, make_cow_tuple(arg0, args...));
} }
......
...@@ -173,21 +173,6 @@ class abstract_tuple : public ref_counted ...@@ -173,21 +173,6 @@ class abstract_tuple : public ref_counted
}; };
inline bool full_eq(abstract_tuple::const_iterator const& lhs,
type_value_pair const& rhs)
{
return lhs.type() == rhs.first
&& ( rhs.second == nullptr
|| lhs.type()->equals(lhs.value(), rhs.second));
}
inline bool full_eq_v2(type_value_pair const& lhs,
abstract_tuple::const_iterator const& rhs)
{
return full_eq(rhs, lhs);
}
inline bool full_eq_v3(abstract_tuple::const_iterator const& lhs, inline bool full_eq_v3(abstract_tuple::const_iterator const& lhs,
abstract_tuple::const_iterator const& rhs) abstract_tuple::const_iterator const& rhs)
{ {
...@@ -195,29 +180,16 @@ inline bool full_eq_v3(abstract_tuple::const_iterator const& lhs, ...@@ -195,29 +180,16 @@ inline bool full_eq_v3(abstract_tuple::const_iterator const& lhs,
&& lhs.type()->equals(lhs.value(), rhs.value()); && lhs.type()->equals(lhs.value(), rhs.value());
} }
inline bool values_only_eq(abstract_tuple::const_iterator const& lhs,
type_value_pair const& rhs)
{
return rhs.second == nullptr
|| lhs.type()->equals(lhs.value(), rhs.second);
}
inline bool values_only_eq_v2(type_value_pair const& lhs,
abstract_tuple::const_iterator const& rhs)
{
return values_only_eq(rhs, lhs);
}
inline bool types_only_eq(abstract_tuple::const_iterator const& lhs, inline bool types_only_eq(abstract_tuple::const_iterator const& lhs,
type_value_pair const& rhs) uniform_type_info const* rhs)
{ {
return lhs.type() == rhs.first; return lhs.type() == rhs;
} }
inline bool types_only_eq_v2(type_value_pair const& lhs, inline bool types_only_eq_v2(uniform_type_info const* lhs,
abstract_tuple::const_iterator const& rhs) abstract_tuple::const_iterator const& rhs)
{ {
return lhs.first == rhs.type(); return lhs == rhs.type();
} }
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#define ADDRESSED_MESSAGE_HPP #define ADDRESSED_MESSAGE_HPP
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/tuple.hpp" #include "cppa/cow_tuple.hpp"
#include "cppa/channel.hpp" #include "cppa/channel.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
......
...@@ -146,10 +146,10 @@ class decorated_tuple : public abstract_tuple ...@@ -146,10 +146,10 @@ class decorated_tuple : public abstract_tuple
}; };
template<typename TypeList> template<typename TypeList>
struct decorated_tuple_from_type_list; struct decorated_cow_tuple_from_type_list;
template<typename... Types> template<typename... Types>
struct decorated_tuple_from_type_list< util::type_list<Types...> > struct decorated_cow_tuple_from_type_list< util::type_list<Types...> >
{ {
typedef decorated_tuple<Types...> type; typedef decorated_tuple<Types...> type;
}; };
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "cppa/self.hpp" #include "cppa/self.hpp"
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/is_array_of.hpp" #include "cppa/util/is_array_of.hpp"
#include "cppa/util/replace_type.hpp" #include "cppa/util/replace_type.hpp"
...@@ -74,6 +75,13 @@ struct implicit_conversions ...@@ -74,6 +75,13 @@ struct implicit_conversions
}; };
template<typename T>
struct strip_and_convert
{
typedef typename implicit_conversions<typename util::rm_ref<T>::type>::type
type;
};
} } // namespace cppa::detail } } // namespace cppa::detail
#endif // IMPLICIT_CONVERSIONS_HPP #endif // IMPLICIT_CONVERSIONS_HPP
...@@ -87,7 +87,7 @@ template<typename Fun, class FunArgs, class TupleTypes> ...@@ -87,7 +87,7 @@ template<typename Fun, class FunArgs, class TupleTypes>
struct iimpl : intermediate struct iimpl : intermediate
{ {
typedef Fun functor_type; typedef Fun functor_type;
typedef typename tuple_from_type_list<TupleTypes>::type tuple_type; typedef typename cow_tuple_from_type_list<TupleTypes>::type tuple_type;
functor_type m_fun; functor_type m_fun;
tuple_type m_default_args; tuple_type m_default_args;
tuple_type m_args; tuple_type m_args;
...@@ -358,19 +358,20 @@ struct select_invokable_impl<Fun, pattern<anything> > ...@@ -358,19 +358,20 @@ struct select_invokable_impl<Fun, pattern<anything> >
dummy_policy> type; dummy_policy> type;
}; };
template<class Pattern, typename Fun, typename Data> template<class Pattern, typename Fun>
std::unique_ptr<invokable> get_invokable_impl(Fun&& fun, Data&& dt) std::unique_ptr<invokable> get_invokable_impl(Fun&& fun,
std::unique_ptr<value_matcher>&& vm)
{ {
typedef typename select_invokable_impl<Fun, Pattern>::type result; typedef typename select_invokable_impl<Fun, Pattern>::type result;
return std::unique_ptr<invokable>( return std::unique_ptr<invokable>{
new result(std::forward<Fun>(fun), std::forward<Data>(dt))); new result(std::forward<Fun>(fun), std::move(vm))};
} }
template<class Pattern, typename Fun> template<class Pattern, typename Fun>
std::unique_ptr<invokable> get_invokable_impl(Fun&& fun) std::unique_ptr<invokable> get_invokable_impl(Fun&& fun)
{ {
typedef typename select_invokable_impl<Fun, typename Pattern::types>::type result; typedef typename select_invokable_impl<Fun, typename Pattern::types>::type result;
return std::unique_ptr<invokable>(new result(std::forward<Fun>(fun))); return std::unique_ptr<invokable>{new result(std::forward<Fun>(fun))};
} }
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -77,8 +77,7 @@ struct matcher<wildcard_position::nil, T...> ...@@ -77,8 +77,7 @@ struct matcher<wildcard_position::nil, T...>
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn) static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
{ {
CPPA_REQUIRE(tup.size() == sizeof...(T)); CPPA_REQUIRE(tup.size() == sizeof...(T));
return std::equal(ptrn.begin(), ptrn.vend(), tup.begin(), return ptrn._matches_values(tup);
detail::values_only_eq_v2);
} }
}; };
...@@ -113,8 +112,7 @@ struct matcher<wildcard_position::trailing, T...> ...@@ -113,8 +112,7 @@ struct matcher<wildcard_position::trailing, T...>
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn) static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
{ {
return std::equal(ptrn.begin(), ptrn.vend(), tup.begin(), return ptrn._matches_values(tup);
detail::values_only_eq_v2);
} }
}; };
...@@ -169,12 +167,7 @@ struct matcher<wildcard_position::leading, T...> ...@@ -169,12 +167,7 @@ struct matcher<wildcard_position::leading, T...>
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn) static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
{ {
auto tbegin = tup.begin(); return ptrn._matches_values(tup);
// skip unmatched elements
tbegin += (tup.size() - size);
// skip leading wildcard ++(ptr.begin())
return std::equal(++(ptrn.begin()), ptrn.vend(), tbegin,
detail::values_only_eq_v2);
} }
}; };
...@@ -231,19 +224,7 @@ struct matcher<wildcard_position::in_between, T...> ...@@ -231,19 +224,7 @@ struct matcher<wildcard_position::in_between, T...>
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn) static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
{ {
// first range return ptrn._matches_values(tup);
auto tbegin = tup.begin();
auto tend = tbegin + wc_pos;
if (std::equal(tbegin, tend, ptrn.begin(), detail::values_only_eq))
{
// second range
tbegin = tend = tup.end();
tbegin -= (size - (wc_pos + 1));
auto pbegin = ptrn.begin();
pbegin += (wc_pos + 1);
return std::equal(tbegin, tend, pbegin, detail::values_only_eq);
}
return false;
} }
}; };
...@@ -335,19 +316,7 @@ struct matcher<wildcard_position::multiple, T...> ...@@ -335,19 +316,7 @@ struct matcher<wildcard_position::multiple, T...>
pattern<T...> const& ptrn, pattern<T...> const& ptrn,
typename pattern<T...>::mapping_vector const& mv) typename pattern<T...>::mapping_vector const& mv)
{ {
auto i = mv.begin(); return ptrn._matches_values(tup, &mv);
for (auto j = ptrn.begin(); j != ptrn.end(); ++j)
{
if (j.type() != nullptr)
{
if ( j.value() != nullptr
&& j.type()->equals(tup.at(*i), j.value()) == false)
{
return false;
}
++i;
}
}
} }
}; };
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "cppa/util/arg_match_t.hpp" #include "cppa/util/arg_match_t.hpp"
#include "cppa/detail/abstract_tuple.hpp" #include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace cppa { namespace cppa {
class uniform_type_info; class uniform_type_info;
...@@ -275,10 +276,11 @@ struct tdata_from_type_list<cppa::util::type_list<T...>> ...@@ -275,10 +276,11 @@ struct tdata_from_type_list<cppa::util::type_list<T...>>
namespace cppa { namespace cppa {
template<typename... Tn> template<typename... Args>
inline detail::tdata<Tn...> make_tdata(Tn const&... args) detail::tdata<typename detail::implicit_conversions<typename util::rm_ref<Args>::type>::type...>
mk_tdata(Args&&... args)
{ {
return detail::tdata<Tn...>(args...); return {std::forward<Args>(args)...};
} }
template<size_t N, typename... Tn> template<size_t N, typename... Tn>
......
...@@ -62,23 +62,17 @@ struct types_array_impl ...@@ -62,23 +62,17 @@ struct types_array_impl
static constexpr bool builtin_only = true; static constexpr bool builtin_only = true;
// all types are builtin, perform lookup on constuction // all types are builtin, perform lookup on constuction
uniform_type_info const* data[sizeof...(T)]; uniform_type_info const* data[sizeof...(T)];
type_value_pair pairs[sizeof...(T)];
types_array_impl() types_array_impl()
: data{ta_util<cppa_tinf,util::is_builtin<T>::value,T>::get()...} : data{ta_util<cppa_tinf,util::is_builtin<T>::value,T>::get()...}
{ {
for (size_t i = 0; i < sizeof...(T); ++i)
{
pairs[i].first = data[i];
pairs[i].second = nullptr;
}
} }
inline uniform_type_info const* operator[](size_t p) const inline uniform_type_info const* operator[](size_t p) const
{ {
return data[p]; return data[p];
} }
typedef type_value_pair_const_iterator const_iterator; typedef uniform_type_info const* const* const_iterator;
inline const_iterator begin() const { return pairs; } inline const_iterator begin() const { return std::begin(data); }
inline const_iterator end() const { return pairs + sizeof...(T); } inline const_iterator end() const { return std::end(data); }
}; };
template<typename... T> template<typename... T>
...@@ -90,7 +84,7 @@ struct types_array_impl<false, T...> ...@@ -90,7 +84,7 @@ struct types_array_impl<false, T...>
// contains uniform_type_infos for builtin types and lazy initializes // contains uniform_type_infos for builtin types and lazy initializes
// non-builtin types at runtime // non-builtin types at runtime
mutable std::atomic<uniform_type_info const*> data[sizeof...(T)]; mutable std::atomic<uniform_type_info const*> data[sizeof...(T)];
mutable std::atomic<type_value_pair const*> pairs; mutable std::atomic<uniform_type_info const* *> pairs;
// pairs[sizeof...(T)]; // pairs[sizeof...(T)];
types_array_impl() types_array_impl()
: tinfo_data{ta_util<std_tinf,util::is_builtin<T>::value,T>::get()...} : tinfo_data{ta_util<std_tinf,util::is_builtin<T>::value,T>::get()...}
...@@ -120,17 +114,16 @@ struct types_array_impl<false, T...> ...@@ -120,17 +114,16 @@ struct types_array_impl<false, T...>
} }
return result; return result;
} }
typedef type_value_pair_const_iterator const_iterator; typedef uniform_type_info const* const* const_iterator;
inline const_iterator begin() const inline const_iterator begin() const
{ {
auto result = pairs.load(); auto result = pairs.load();
if (result == nullptr) if (result == nullptr)
{ {
auto parr = new type_value_pair[sizeof...(T)]; auto parr = new uniform_type_info const*[sizeof...(T)];
for (size_t i = 0; i < sizeof...(T); ++i) for (size_t i = 0; i < sizeof...(T); ++i)
{ {
parr[i].first = (*this)[i]; parr[i] = (*this)[i];
parr[i].second = nullptr;
} }
if (!pairs.compare_exchange_weak(result, parr, std::memory_order_relaxed)) if (!pairs.compare_exchange_weak(result, parr, std::memory_order_relaxed))
{ {
......
...@@ -42,7 +42,7 @@ namespace cppa { ...@@ -42,7 +42,7 @@ namespace cppa {
namespace detail { template<typename...> class tdata; } namespace detail { template<typename...> class tdata; }
// forward declaration of tuple // forward declaration of tuple
template<typename...> class tuple; template<typename...> class cow_tuple;
// forward declaration of get(detail::tdata<...> const&) // forward declaration of get(detail::tdata<...> const&)
template<size_t N, typename... Tn> template<size_t N, typename... Tn>
...@@ -50,7 +50,7 @@ const typename util::at<N, Tn...>::type& get(detail::tdata<Tn...> const&); ...@@ -50,7 +50,7 @@ const typename util::at<N, Tn...>::type& get(detail::tdata<Tn...> const&);
// forward declarations of get(tuple<...> const&) // forward declarations of get(tuple<...> const&)
template<size_t N, typename... Tn> template<size_t N, typename... Tn>
const typename util::at<N, Tn...>::type& get(tuple<Tn...> const&); const typename util::at<N, Tn...>::type& get(cow_tuple<Tn...> const&);
// forward declarations of get_ref(detail::tdata<...>&) // forward declarations of get_ref(detail::tdata<...>&)
template<size_t N, typename... Tn> template<size_t N, typename... Tn>
...@@ -58,7 +58,7 @@ typename util::at<N, Tn...>::type& get_ref(detail::tdata<Tn...>&); ...@@ -58,7 +58,7 @@ typename util::at<N, Tn...>::type& get_ref(detail::tdata<Tn...>&);
// forward declarations of get_ref(tuple<...>&) // forward declarations of get_ref(tuple<...>&)
template<size_t N, typename... Tn> template<size_t N, typename... Tn>
typename util::at<N, Tn...>::type& get_ref(tuple<Tn...>&); typename util::at<N, Tn...>::type& get_ref(cow_tuple<Tn...>&);
} // namespace cppa } // namespace cppa
......
...@@ -103,10 +103,10 @@ struct pmatch_each_helper ...@@ -103,10 +103,10 @@ struct pmatch_each_helper
namespace cppa { namespace cppa {
//inline detail::match_helper match(any_tuple t) inline detail::match_helper match(any_tuple t)
//{ {
// return std::move(t); return std::move(t);
//} }
/** /**
* @brief Match expression. * @brief Match expression.
......
...@@ -101,17 +101,13 @@ class rvalue_builder ...@@ -101,17 +101,13 @@ class rvalue_builder
typedef typename pattern_from_type_list<converted_types>::type typedef typename pattern_from_type_list<converted_types>::type
pattern_type; pattern_type;
typedef typename pattern_type::data_type pattern_data; std::unique_ptr<value_matcher> m_vm;
pattern_data m_data;
bool m_has_values;
template<typename F> template<typename F>
partial_function cr_rvalue(F&& f, std::integral_constant<bool, true>) partial_function cr_rvalue(F&& f, std::integral_constant<bool, true>)
{ {
return m_has_values ? get_invokable_impl<pattern_type>(std::forward<F>(f), return get_invokable_impl<pattern_type>(std::forward<F>(f),
std::move(m_data)) std::move(m_vm));
: get_invokable_impl<pattern_type>(std::forward<F>(f));
} }
template<typename F> template<typename F>
...@@ -124,22 +120,18 @@ class rvalue_builder ...@@ -124,22 +120,18 @@ class rvalue_builder
typedef typename tl_apply<raw_types,rm_ref>::type new_types; typedef typename tl_apply<raw_types,rm_ref>::type new_types;
typedef typename tl_concat<converted_types,new_types>::type types; typedef typename tl_concat<converted_types,new_types>::type types;
typedef typename pattern_from_type_list<types>::type epattern; typedef typename pattern_from_type_list<types>::type epattern;
return m_has_values ? get_invokable_impl<epattern>(std::forward<F>(f), return get_invokable_impl<epattern>(std::forward<F>(f),
std::move(m_data)) std::move(m_vm));
: get_invokable_impl<epattern>(std::forward<F>(f));
} }
public: public:
template<typename... Args> template<typename... Args>
rvalue_builder(Args&&... args) : m_data(std::forward<Args>(args)...) rvalue_builder(Args&&... args)
: m_vm(pattern_type::get_value_matcher(std::forward<Args>(args)...))
{ {
static constexpr bool all_boxed =
util::tl_forall<util::type_list<Args...>, is_boxed>::value;
m_has_values = !all_boxed;
} }
template<typename F> template<typename F>
partial_function operator>>(F&& f) partial_function operator>>(F&& f)
{ {
......
...@@ -31,16 +31,21 @@ ...@@ -31,16 +31,21 @@
#ifndef LIBCPPA_PATTERN_HPP #ifndef LIBCPPA_PATTERN_HPP
#define LIBCPPA_PATTERN_HPP #define LIBCPPA_PATTERN_HPP
#include <iostream>
#include <list> #include <list>
#include <memory>
#include <vector> #include <vector>
#include <cstddef> #include <cstddef>
#include <type_traits> #include <type_traits>
#include "cppa/option.hpp" #include "cppa/option.hpp"
#include "cppa/anything.hpp" #include "cppa/anything.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/type_value_pair.hpp" #include "cppa/type_value_pair.hpp"
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
#include "cppa/util/tbind.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/arg_match_t.hpp" #include "cppa/util/arg_match_t.hpp"
#include "cppa/util/fixed_vector.hpp" #include "cppa/util/fixed_vector.hpp"
...@@ -76,8 +81,150 @@ constexpr wildcard_position get_wildcard_position() ...@@ -76,8 +81,150 @@ constexpr wildcard_position get_wildcard_position()
: wildcard_position::nil; : wildcard_position::nil;
} }
template<class ExtendedType, class BasicType> struct value_matcher
ExtendedType* extend_pattern(BasicType const* p); {
const bool is_dummy;
inline value_matcher(bool dummy_impl = false) : is_dummy(dummy_impl) { }
virtual ~value_matcher();
virtual bool operator()(any_tuple const&) = 0;
};
struct dummy_matcher : value_matcher
{
inline dummy_matcher() : value_matcher(true) { }
bool operator()(any_tuple const&);
};
struct cmp_helper
{
size_t i;
any_tuple const& tup;
cmp_helper(any_tuple const& tp, size_t pos = 0) : i(pos), tup(tp) { }
template<typename T>
inline bool operator()(T const& what)
{
return what == tup.get_as<T>(i++);
}
template<typename T>
inline bool operator()(util::wrapped<T> const&)
{
++i;
return true;
}
};
template<wildcard_position WP, class PatternTypes, class ValueTypes>
class value_matcher_impl;
template<typename... Ts, typename... Vs>
class value_matcher_impl<wildcard_position::nil,
util::type_list<Ts...>,
util::type_list<Vs...> > : public value_matcher
{
detail::tdata<Vs...> m_values;
public:
template<typename... Args>
value_matcher_impl(Args&&... args) : m_values(std::forward<Args>(args)...) { }
bool operator()(any_tuple const& tup)
{
cmp_helper h{tup};
return util::static_foreach<0, sizeof...(Vs)>::eval(m_values, h);
}
};
template<typename... Ts, typename... Vs>
class value_matcher_impl<wildcard_position::trailing,
util::type_list<Ts...>,
util::type_list<Vs...> >
: public value_matcher_impl<wildcard_position::nil,
util::type_list<Ts...>,
util::type_list<Vs...> >
{
typedef value_matcher_impl<wildcard_position::nil,
util::type_list<Ts...>,
util::type_list<Vs...> >
super;
public:
template<typename... Args>
value_matcher_impl(Args&&... args) : super(std::forward<Args>(args)...) { }
};
template<typename... Ts, typename... Vs>
class value_matcher_impl<wildcard_position::leading,
util::type_list<Ts...>,
util::type_list<Vs...> > : public value_matcher
{
detail::tdata<Vs...> m_values;
public:
template<typename... Args>
value_matcher_impl(Args&&... args) : m_values(std::forward<Args>(args)...) { }
bool operator()(any_tuple const& tup)
{
cmp_helper h{tup, tup.size() - sizeof...(Ts)};
return util::static_foreach<0, sizeof...(Vs)>::eval(m_values, h);
}
};
template<typename... Ts, typename... Vs>
class value_matcher_impl<wildcard_position::in_between,
util::type_list<Ts...>,
util::type_list<Vs...> > : public value_matcher
{
detail::tdata<Vs...> m_values;
public:
template<typename... Args>
value_matcher_impl(Args&&... args) : m_values(std::forward<Args>(args)...) { }
bool operator()(any_tuple const& tup)
{
static constexpr size_t wcpos =
static_cast<size_t>(util::tl_find<util::type_list<Ts...>, anything>::value);
static_assert(wcpos < sizeof...(Ts), "illegal wildcard position");
cmp_helper h0{tup, 0};
cmp_helper h1{tup, tup.size() - (sizeof...(Ts) - (wcpos + 1))};
static constexpr size_t range_end = (sizeof...(Vs) > wcpos)
? wcpos
: sizeof...(Vs);
return util::static_foreach<0, range_end>::eval(m_values, h0)
&& util::static_foreach<range_end + 1, sizeof...(Vs)>::eval(m_values, h1);
}
};
template<typename... Ts, typename... Vs>
class value_matcher_impl<wildcard_position::multiple,
util::type_list<Ts...>,
util::type_list<Vs...> > : public value_matcher
{
public:
template<typename... Args>
value_matcher_impl(Args&&...) { }
bool operator()(any_tuple const&)
{
throw std::runtime_error("not implemented yet, sorry");
}
};
template<typename... Types> template<typename... Types>
class pattern class pattern
...@@ -85,9 +232,6 @@ class pattern ...@@ -85,9 +232,6 @@ class pattern
static_assert(sizeof...(Types) > 0, "empty pattern"); static_assert(sizeof...(Types) > 0, "empty pattern");
template<class ExtendedType, class BasicType>
friend ExtendedType* extend_pattern(BasicType const* p);
pattern(pattern const&) = delete; pattern(pattern const&) = delete;
pattern& operator=(pattern const&) = delete; pattern& operator=(pattern const&) = delete;
...@@ -109,13 +253,19 @@ class pattern ...@@ -109,13 +253,19 @@ class pattern
typedef util::fixed_vector<size_t, filtered_types::size> mapping_vector; typedef util::fixed_vector<size_t, filtered_types::size> mapping_vector;
typedef type_value_pair_const_iterator const_iterator; typedef uniform_type_info const* const_iterator;
typedef std::reverse_iterator<const_iterator> reverse_const_iterator; typedef std::reverse_iterator<const_iterator> reverse_const_iterator;
inline const_iterator begin() const { return std::begin(m_ptrs); } inline const_iterator begin() const
{
return detail::static_types_array<Types...>::arr.begin();
}
inline const_iterator end() const { return std::end(m_ptrs); } inline const_iterator end() const
{
return detail::static_types_array<Types...>::arr.end();
}
inline reverse_const_iterator rbegin() const inline reverse_const_iterator rbegin() const
{ {
...@@ -127,83 +277,63 @@ class pattern ...@@ -127,83 +277,63 @@ class pattern
return reverse_const_iterator{begin()}; return reverse_const_iterator{begin()};
} }
inline const_iterator vend() const { return m_vend; } inline bool has_values() const { return m_vm->is_dummy == false; }
inline bool has_values() const { return m_has_values; }
pattern() : m_has_values(false) // @warning does NOT check types
bool _matches_values(any_tuple const& tup) const
{ {
auto& arr = detail::static_types_array<Types...>::arr; return (*m_vm)(tup);
for (size_t i = 0; i < size; ++i)
{
m_ptrs[i].first = arr[i];
m_ptrs[i].second = nullptr;
}
m_vend = begin();
} }
template<typename... Args> pattern() : m_vm(new dummy_matcher)
pattern(head_type const& arg0, Args&&... args)
: m_data(arg0, std::forward<Args>(args)...)
{ {
init<head_type, Args...>();
} }
template<typename... Args> template<typename... Args>
pattern(head_type&& arg0, Args&&... args) pattern(head_type arg0, Args&&... args)
: m_data(std::move(arg0), std::forward<Args>(args)...) : m_vm(get_value_matcher(std::move(arg0), std::forward<Args>(args)...))
{ {
init<head_type, Args...>();
} }
template<typename... Args> template<typename... Args>
pattern(util::wrapped<head_type> const& arg0, Args const&... args) pattern(util::wrapped<head_type> const& arg0, Args&&... args)
: m_data(arg0, std::forward<Args>(args)...) : m_vm(get_value_matcher(arg0, std::forward<Args>(args)...))
{ {
init<util::wrapped<head_type>, Args...>();
} }
template<typename... Args> template<typename... Args>
pattern(detail::tdata<Args...> const& data) : m_data(data) pattern(detail::tdata<Args...> const& data)
{ {
init<Args...>(); m_vm.reset(new value_matcher_impl<wildcard_pos, types, util::type_list<Args...> >{data});
} }
template<typename... Args> pattern(std::unique_ptr<value_matcher>&& vm) : m_vm(std::move(vm)) { }
pattern(detail::tdata<Args...>&& data) : m_data(std::move(data))
static inline value_matcher* get_value_matcher()
{ {
init<Args...>(); return new dummy_matcher;
} }
typedef detail::tdata<option<Types>...> data_type;
private:
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
void init() static value_matcher* get_value_matcher(Arg0&& arg0, Args&&... args)
{ {
typedef typename util::type_list<Arg0, Args...>::back arg_n; using namespace util;
static constexpr bool ignore_arg_n = typedef typename tl_filter_not<
std::is_same<arg_n, util::arg_match_t>::value; type_list<typename detail::strip_and_convert<Arg0>::type,
// ignore extra arg_match_t argument typename detail::strip_and_convert<Args>::type...>,
static constexpr size_t args_size = sizeof...(Args) tbind<std::is_same, wrapped<arg_match_t> >::type
+ (ignore_arg_n ? 0 : 1); >::type
static_assert(args_size <= size, "too many arguments"); arg_types;
auto& arr = detail::static_types_array<Types...>::arr; static_assert(arg_types::size <= size, "too many arguments");
// "polymophic lambda" if (tl_forall<arg_types, detail::is_boxed>::value)
init_helper f(m_ptrs, arr);
// init elements [0, N)
util::static_foreach<0, args_size>::_(m_data, f);
// init elements [N, size)
for (size_t i = args_size; i < size; ++i)
{ {
m_ptrs[i].first = arr[i]; return new dummy_matcher;
m_ptrs[i].second = nullptr;
} }
init_vend(); return new value_matcher_impl<wildcard_pos, types, arg_types>{std::forward<Arg0>(arg0), std::forward<Args>(args)...};
m_has_values = (vend() != begin());
} }
private:
typedef type_value_pair tvp_array[size]; typedef type_value_pair tvp_array[size];
// a polymophic functor // a polymophic functor
...@@ -223,41 +353,10 @@ class pattern ...@@ -223,41 +353,10 @@ class pattern
} }
}; };
inline void init_vend() std::unique_ptr<value_matcher> m_vm;
{
m_vend = std::find_if(
rbegin(), rend(),
[](type_value_pair const& tvp) { return tvp.second != 0; }
).base();
}
bool m_has_values;
detail::tdata<option<Types>...> m_data;
tvp_array m_ptrs;
const_iterator m_vend;
}; };
template<class ExtendedType, class BasicType>
ExtendedType* extend_pattern(BasicType const* p)
{
ExtendedType* et = new ExtendedType;
if (p->has_values())
{
detail::tdata_set(et->m_data, p->m_data);
et->m_has_values = true;
typedef typename ExtendedType::types extended_types;
typedef typename
detail::static_types_array_from_type_list<extended_types>::type
tarr;
auto& arr = tarr::arr;
typename ExtendedType::init_helper f(et->m_ptrs, arr);
util::static_foreach<0, BasicType::size>::_(et->m_data, f);
et->init_vend();
}
return et;
}
template<typename TypeList> template<typename TypeList>
struct pattern_from_type_list; struct pattern_from_type_list;
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include "cppa/self.hpp" #include "cppa/self.hpp"
#include "cppa/atom.hpp" #include "cppa/atom.hpp"
#include "cppa/tuple.hpp" #include "cppa/cow_tuple.hpp"
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/attachable.hpp" #include "cppa/attachable.hpp"
#include "cppa/local_actor.hpp" #include "cppa/local_actor.hpp"
...@@ -112,8 +112,8 @@ class scheduler ...@@ -112,8 +112,8 @@ class scheduler
Duration const& rel_time, Data const&... data) Duration const& rel_time, Data const&... data)
{ {
static_assert(sizeof...(Data) > 0, "no message to send"); static_assert(sizeof...(Data) > 0, "no message to send");
any_tuple data_tup = make_tuple(data...); any_tuple data_tup = make_cow_tuple(data...);
any_tuple tup = make_tuple(util::duration(rel_time), to, data_tup); any_tuple tup = make_cow_tuple(util::duration(rel_time), to, data_tup);
future_send_helper()->enqueue(self, std::move(tup)); future_send_helper()->enqueue(self, std::move(tup));
} }
......
...@@ -48,12 +48,12 @@ namespace cppa { ...@@ -48,12 +48,12 @@ namespace cppa {
template<typename... T> template<typename... T>
auto moving_tuple_cast(any_tuple& tup, pattern<T...> const& p) auto moving_tuple_cast(any_tuple& tup, pattern<T...> const& p)
-> option< -> option<
typename tuple_from_type_list< typename cow_tuple_from_type_list<
typename pattern<T...>::filtered_types typename pattern<T...>::filtered_types
>::type> >::type>
{ {
typedef typename pattern<T...>::filtered_types filtered_types; typedef typename pattern<T...>::filtered_types filtered_types;
typedef typename tuple_from_type_list<filtered_types>::type tuple_type; typedef typename cow_tuple_from_type_list<filtered_types>::type tuple_type;
static constexpr auto impl = static constexpr auto impl =
get_wildcard_position<util::type_list<T...>>(); get_wildcard_position<util::type_list<T...>>();
return detail::tuple_cast_impl<impl, tuple_type, T...>::safe(tup, p); return detail::tuple_cast_impl<impl, tuple_type, T...>::safe(tup, p);
...@@ -66,7 +66,7 @@ auto moving_tuple_cast(any_tuple& tup, pattern<T...> const& p) ...@@ -66,7 +66,7 @@ auto moving_tuple_cast(any_tuple& tup, pattern<T...> const& p)
template<typename... T> template<typename... T>
auto moving_tuple_cast(any_tuple& tup) auto moving_tuple_cast(any_tuple& tup)
-> option< -> option<
typename tuple_from_type_list< typename cow_tuple_from_type_list<
typename util::tl_filter_not<util::type_list<T...>, typename util::tl_filter_not<util::type_list<T...>,
is_anything>::type is_anything>::type
>::type> >::type>
...@@ -91,7 +91,7 @@ auto moving_tuple_cast(any_tuple& tup, util::type_list<T...> const&) ...@@ -91,7 +91,7 @@ auto moving_tuple_cast(any_tuple& tup, util::type_list<T...> const&)
template<typename... T> template<typename... T>
auto tuple_cast(any_tuple tup, pattern<T...> const& p) auto tuple_cast(any_tuple tup, pattern<T...> const& p)
-> option< -> option<
typename tuple_from_type_list< typename cow_tuple_from_type_list<
typename pattern<T...>::filtered_types typename pattern<T...>::filtered_types
>::type> >::type>
{ {
...@@ -104,7 +104,7 @@ auto tuple_cast(any_tuple tup, pattern<T...> const& p) ...@@ -104,7 +104,7 @@ auto tuple_cast(any_tuple tup, pattern<T...> const& p)
template<typename... T> template<typename... T>
auto tuple_cast(any_tuple tup) auto tuple_cast(any_tuple tup)
-> option< -> option<
typename tuple_from_type_list< typename cow_tuple_from_type_list<
typename util::tl_filter_not<util::type_list<T...>, typename util::tl_filter_not<util::type_list<T...>,
is_anything>::type is_anything>::type
>::type> >::type>
...@@ -125,12 +125,12 @@ auto tuple_cast(any_tuple tup, util::type_list<T...> const&) ...@@ -125,12 +125,12 @@ auto tuple_cast(any_tuple tup, util::type_list<T...> const&)
template<typename... T> template<typename... T>
auto unsafe_tuple_cast(any_tuple& tup, pattern<T...> const& p) auto unsafe_tuple_cast(any_tuple& tup, pattern<T...> const& p)
-> option< -> option<
typename tuple_from_type_list< typename cow_tuple_from_type_list<
typename pattern<T...>::filtered_types typename pattern<T...>::filtered_types
>::type> >::type>
{ {
typedef typename pattern<T...>::filtered_types filtered_types; typedef typename pattern<T...>::filtered_types filtered_types;
typedef typename tuple_from_type_list<filtered_types>::type tuple_type; typedef typename cow_tuple_from_type_list<filtered_types>::type tuple_type;
static constexpr auto impl = static constexpr auto impl =
get_wildcard_position<util::type_list<T...>>(); get_wildcard_position<util::type_list<T...>>();
return detail::tuple_cast_impl<impl, tuple_type, T...>::unsafe(tup, p); return detail::tuple_cast_impl<impl, tuple_type, T...>::unsafe(tup, p);
...@@ -146,12 +146,12 @@ auto unsafe_tuple_cast(any_tuple& tup, util::type_list<T...> const&) ...@@ -146,12 +146,12 @@ auto unsafe_tuple_cast(any_tuple& tup, util::type_list<T...> const&)
// cast using a pattern; does neither perform type checking nor checks values // cast using a pattern; does neither perform type checking nor checks values
template<typename... T> template<typename... T>
auto forced_tuple_cast(any_tuple& tup, pattern<T...> const& p) auto forced_tuple_cast(any_tuple& tup, pattern<T...> const& p)
-> typename tuple_from_type_list< -> typename cow_tuple_from_type_list<
typename pattern<T...>::filtered_types typename pattern<T...>::filtered_types
>::type >::type
{ {
typedef typename pattern<T...>::filtered_types filtered_types; typedef typename pattern<T...>::filtered_types filtered_types;
typedef typename tuple_from_type_list<filtered_types>::type tuple_type; typedef typename cow_tuple_from_type_list<filtered_types>::type tuple_type;
static constexpr auto impl = static constexpr auto impl =
get_wildcard_position<util::type_list<T...>>(); get_wildcard_position<util::type_list<T...>>();
return detail::tuple_cast_impl<impl, tuple_type, T...>::force(tup, p); return detail::tuple_cast_impl<impl, tuple_type, T...>::force(tup, p);
......
...@@ -103,6 +103,12 @@ class type_value_pair_const_iterator ...@@ -103,6 +103,12 @@ class type_value_pair_const_iterator
return iter + offset; return iter + offset;
} }
inline type_value_pair_const_iterator& operator+=(size_t offset)
{
iter += offset;
return *this;
}
}; };
/** /**
......
...@@ -35,26 +35,48 @@ ...@@ -35,26 +35,48 @@
namespace cppa { namespace util { namespace cppa { namespace util {
/** template<size_t Begin, size_t End, bool BeginGreaterEnd>
* @ingroup MetaProgramming struct static_foreach_impl
* @brief A for loop that can be used with tuples.
*/
template<size_t Begin, size_t End>
struct static_foreach
{ {
template<typename Container, typename Fun> template<typename Container, typename Fun>
static inline void _(Container const& c, Fun& f) static inline void _(Container const& c, Fun& f)
{ {
f(get<Begin>(c)); f(get<Begin>(c));
static_foreach<Begin+1, End>::_(c, f); static_foreach_impl<Begin+1, End, (Begin+1 > End)>::_(c, f);
}
template<typename Container, typename Fun>
static inline bool eval(Container const& c, Fun& f)
{
return f(get<Begin>(c))
&& static_foreach_impl<Begin+1, End, (Begin+1 > End)>::eval(c, f);
} }
}; };
template<size_t X> template<size_t X>
struct static_foreach<X, X> struct static_foreach_impl<X, X, false>
{ {
template<typename Container, typename Fun> template<typename Container, typename Fun>
static inline void _(Container const&, Fun&) { } static inline void _(Container const&, Fun&) { }
template<typename Container, typename Fun>
static inline bool eval(Container const&, Fun&) { return true; }
};
template<size_t X, size_t Y>
struct static_foreach_impl<X, Y, true>
{
template<typename Container, typename Fun>
static inline void _(Container const&, Fun&) { }
template<typename Container, typename Fun>
static inline bool eval(Container const&, Fun&) { return true; }
};
/**
* @ingroup MetaProgramming
* @brief A for loop that can be used with tuples.
*/
template<size_t Begin, size_t End>
struct static_foreach : static_foreach_impl<Begin, End, (Begin > End)>
{
}; };
} } // namespace cppa::util } } // namespace cppa::util
......
...@@ -86,7 +86,7 @@ void actor_proxy::link_to(intrusive_ptr<actor>& other) ...@@ -86,7 +86,7 @@ void actor_proxy::link_to(intrusive_ptr<actor>& other)
// causes remote actor to link to (proxy of) other // causes remote actor to link to (proxy of) other
forward_message(parent_process_ptr(), forward_message(parent_process_ptr(),
other.get(), other.get(),
make_tuple(atom(":Link"), other)); make_cow_tuple(atom(":Link"), other));
} }
} }
...@@ -102,7 +102,7 @@ void actor_proxy::unlink_from(intrusive_ptr<actor>& other) ...@@ -102,7 +102,7 @@ void actor_proxy::unlink_from(intrusive_ptr<actor>& other)
// causes remote actor to unlink from (proxy of) other // causes remote actor to unlink from (proxy of) other
forward_message(parent_process_ptr(), forward_message(parent_process_ptr(),
other.get(), other.get(),
make_tuple(atom(":Unlink"), other)); make_cow_tuple(atom(":Unlink"), other));
} }
} }
...@@ -119,7 +119,7 @@ bool actor_proxy::establish_backlink(intrusive_ptr<actor>& other) ...@@ -119,7 +119,7 @@ bool actor_proxy::establish_backlink(intrusive_ptr<actor>& other)
// causes remote actor to unlink from (proxy of) other // causes remote actor to unlink from (proxy of) other
forward_message(parent_process_ptr(), forward_message(parent_process_ptr(),
other.get(), other.get(),
make_tuple(atom(":Link"), other)); make_cow_tuple(atom(":Link"), other));
} }
return result; return result;
} }
...@@ -131,7 +131,7 @@ bool actor_proxy::remove_backlink(intrusive_ptr<actor>& other) ...@@ -131,7 +131,7 @@ bool actor_proxy::remove_backlink(intrusive_ptr<actor>& other)
{ {
forward_message(parent_process_ptr(), forward_message(parent_process_ptr(),
nullptr, nullptr,
make_tuple(atom(":Unlink"), actor_ptr(this))); make_cow_tuple(atom(":Unlink"), actor_ptr(this)));
} }
return result; return result;
} }
......
...@@ -52,7 +52,7 @@ std::string to_string(atom_value const& what) ...@@ -52,7 +52,7 @@ std::string to_string(atom_value const& what)
read_chars = true; read_chars = true;
} }
} }
return std::move(result); return result;
} }
} // namespace cppa } // namespace cppa
...@@ -135,4 +135,11 @@ void demonitor(actor_ptr& whom) ...@@ -135,4 +135,11 @@ void demonitor(actor_ptr& whom)
if (whom) whom->detach(mtoken); if (whom) whom->detach(mtoken);
} }
value_matcher::~value_matcher() { }
bool dummy_matcher::operator()(any_tuple const&)
{
return true;
}
} // namespace cppa } // namespace cppa
...@@ -223,7 +223,7 @@ class po_peer ...@@ -223,7 +223,7 @@ class po_peer
{ {
if (!m_children.empty()) if (!m_children.empty())
{ {
auto msg = make_tuple(atom(":KillProxy"), auto msg = make_cow_tuple(atom(":KillProxy"),
exit_reason::remote_link_unreachable); exit_reason::remote_link_unreachable);
for (actor_proxy_ptr& pptr : m_children) for (actor_proxy_ptr& pptr : m_children)
{ {
...@@ -341,7 +341,7 @@ class po_peer ...@@ -341,7 +341,7 @@ class po_peer
// this message was send from a proxy // this message was send from a proxy
receiver->attach_functor([=](std::uint32_t reason) receiver->attach_functor([=](std::uint32_t reason)
{ {
any_tuple kmsg = make_tuple(atom(":KillProxy"), any_tuple kmsg = make_cow_tuple(atom(":KillProxy"),
reason); reason);
auto mjob = new detail::mailman_job(m_peer, auto mjob = new detail::mailman_job(m_peer,
receiver, receiver,
...@@ -540,7 +540,7 @@ void post_office_loop(int pipe_read_handle, int pipe_write_handle) ...@@ -540,7 +540,7 @@ void post_office_loop(int pipe_read_handle, int pipe_write_handle)
if (!pptr) DEBUG("pptr == nullptr"); if (!pptr) DEBUG("pptr == nullptr");
throw std::logic_error("selected_peer == nullptr"); throw std::logic_error("selected_peer == nullptr");
} }
pptr->enqueue(nullptr, make_tuple(atom(":Monitor"))); pptr->enqueue(nullptr, make_cow_tuple(atom(":Monitor")));
selected_peer->add_child(pptr); selected_peer->add_child(pptr);
auto aid = pptr->id(); auto aid = pptr->id();
auto pptr_copy = pptr; auto pptr_copy = pptr;
......
...@@ -84,7 +84,7 @@ struct scheduler_helper ...@@ -84,7 +84,7 @@ struct scheduler_helper
void stop() void stop()
{ {
m_worker->enqueue(nullptr, make_tuple(atom(":_DIE"))); m_worker->enqueue(nullptr, make_cow_tuple(atom(":_DIE")));
m_thread.join(); m_thread.join();
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include "test.hpp" #include "test.hpp"
#include "cppa/cppa.hpp" #include "cppa/cppa.hpp"
#include "cppa/tuple.hpp" #include "cppa/cow_tuple.hpp"
#include "cppa/match.hpp" #include "cppa/match.hpp"
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/anything.hpp" #include "cppa/anything.hpp"
......
...@@ -26,7 +26,7 @@ inline bool cppa_check_value_fun_eq(T1 value1, T2 value2, ...@@ -26,7 +26,7 @@ inline bool cppa_check_value_fun_eq(T1 value1, T2 value2,
} }
template<typename T1, typename T2> template<typename T1, typename T2>
inline void cppa_check_value_fun(T1 const& value1, T2 const& value2, inline bool cppa_check_value_fun(T1 const& value1, T2 const& value2,
char const* file_name, char const* file_name,
int line_number, int line_number,
size_t& error_count) size_t& error_count)
...@@ -38,6 +38,21 @@ inline void cppa_check_value_fun(T1 const& value1, T2 const& value2, ...@@ -38,6 +38,21 @@ inline void cppa_check_value_fun(T1 const& value1, T2 const& value2,
<< ", found: " << value2 << ", found: " << value2
<< std::endl; << std::endl;
++error_count; ++error_count;
return false;
}
return true;
}
template<typename T1, typename T2>
inline void cppa_check_value_verbose_fun(T1 const& value1, T2 const& value2,
char const* file_name,
int line_number,
size_t& error_count)
{
if (cppa_check_value_fun(value1, value2, file_name,
line_number, error_count))
{
std::cout << "line " << line_number << " passed" << std::endl;
} }
} }
...@@ -65,9 +80,13 @@ if (!(line_of_code)) \ ...@@ -65,9 +80,13 @@ if (!(line_of_code)) \
} \ } \
else \ else \
{ \ { \
std::cout << "line " << __LINE__ << " passed" << endl; \ std::cout << "line " << __LINE__ << " passed" << std::endl; \
} \ } \
((void) 0) ((void) 0)
#define CPPA_CHECK_EQUAL(lhs_loc, rhs_loc) \
cppa_check_value_verbose_fun((lhs_loc), (rhs_loc), __FILE__, __LINE__, \
cppa_ts.error_count)
#else #else
#define CPPA_IF_VERBOSE(line_of_code) ((void) 0) #define CPPA_IF_VERBOSE(line_of_code) ((void) 0)
#define CPPA_CHECK(line_of_code) \ #define CPPA_CHECK(line_of_code) \
...@@ -77,16 +96,16 @@ if (!(line_of_code)) \ ...@@ -77,16 +96,16 @@ if (!(line_of_code)) \
<< " => " << #line_of_code << std::endl; \ << " => " << #line_of_code << std::endl; \
++cppa_ts.error_count; \ ++cppa_ts.error_count; \
} ((void) 0) } ((void) 0)
#define CPPA_CHECK_EQUAL(lhs_loc, rhs_loc) \
cppa_check_value_fun((lhs_loc), (rhs_loc), __FILE__, __LINE__, \
cppa_ts.error_count)
#endif #endif
#define CPPA_ERROR(err_msg) \ #define CPPA_ERROR(err_msg) \
std::cerr << err_msg << std::endl; \ std::cerr << err_msg << std::endl; \
++cppa_ts.error_count ++cppa_ts.error_count
#define CPPA_CHECK_EQUAL(lhs_loc, rhs_loc) \
cppa_check_value_fun((lhs_loc), (rhs_loc), __FILE__, __LINE__, \
cppa_ts.error_count)
#define CPPA_CHECK_NOT_EQUAL(lhs_loc, rhs_loc) CPPA_CHECK(((lhs_loc) != (rhs_loc))) #define CPPA_CHECK_NOT_EQUAL(lhs_loc, rhs_loc) CPPA_CHECK(((lhs_loc) != (rhs_loc)))
typedef std::pair<std::string, std::string> string_pair; typedef std::pair<std::string, std::string> string_pair;
......
...@@ -45,12 +45,12 @@ size_t test__atom() ...@@ -45,12 +45,12 @@ size_t test__atom()
CPPA_CHECK_NOT_EQUAL(atom("abc"), atom(" abc")); CPPA_CHECK_NOT_EQUAL(atom("abc"), atom(" abc"));
// check to_string impl. // check to_string impl.
CPPA_CHECK_EQUAL(to_string(s_foo), "FooBar"); CPPA_CHECK_EQUAL(to_string(s_foo), "FooBar");
self << make_tuple(atom("foo"), static_cast<std::uint32_t>(42)) self << make_cow_tuple(atom("foo"), static_cast<std::uint32_t>(42))
<< make_tuple(atom(":Attach"), atom(":Baz"), "cstring") << make_cow_tuple(atom(":Attach"), atom(":Baz"), "cstring")
<< make_tuple(atom("b"), atom("a"), atom("c"), 23.f) << make_cow_tuple(atom("b"), atom("a"), atom("c"), 23.f)
<< make_tuple(atom("a"), atom("b"), atom("c"), 23.f); << make_cow_tuple(atom("a"), atom("b"), atom("c"), 23.f);
int i = 0; int i = 0;
receive_while([&i]() { return ++i <= 3; }) receive_for(i, 3)
( (
on<atom("foo"), std::uint32_t>() >> [&](std::uint32_t value) on<atom("foo"), std::uint32_t>() >> [&](std::uint32_t value)
{ {
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include "cppa/on.hpp" #include "cppa/on.hpp"
#include "cppa/atom.hpp" #include "cppa/atom.hpp"
#include "cppa/match.hpp" #include "cppa/match.hpp"
#include "cppa/tuple.hpp" #include "cppa/cow_tuple.hpp"
#include "cppa/option.hpp" #include "cppa/option.hpp"
#include "cppa/pattern.hpp" #include "cppa/pattern.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
...@@ -26,10 +26,11 @@ ...@@ -26,10 +26,11 @@
#include <boost/progress.hpp> #include <boost/progress.hpp>
using std::string;
using namespace cppa; using namespace cppa;
template<typename Arr> template<typename Arr>
std::string plot(Arr const& arr) string plot(Arr const& arr)
{ {
std::ostringstream oss; std::ostringstream oss;
oss << "{ "; oss << "{ ";
...@@ -56,7 +57,7 @@ void match_test(T const& value) ...@@ -56,7 +57,7 @@ void match_test(T const& value)
{ {
cout << "(" << a << ", " << b << ", " << c << ")" << endl; cout << "(" << a << ", " << b << ", " << c << ")" << endl;
}, },
on_arg_match >> [&](std::string const& str) on_arg_match >> [&](string const& str)
{ {
cout << str << endl; cout << str << endl;
} }
...@@ -96,12 +97,12 @@ size_t test__pattern() ...@@ -96,12 +97,12 @@ size_t test__pattern()
{ {
CPPA_TEST(test__pattern); CPPA_TEST(test__pattern);
//match_test(make_tuple(1,2,3)); //match_test(make_cow_tuple(1,2,3));
//match_test(std::list<int>{1, 2, 3}); //match_test(std::list<int>{1, 2, 3});
//match_test("abc"); //match_test("abc");
pattern<int, anything, int> i3; pattern<int, anything, int> i3;
any_tuple i3_any_tup = make_tuple(1, 2, 3); any_tuple i3_any_tup = make_cow_tuple(1, 2, 3);
/* /*
auto opt = tuple_cast(i3_any_tup, i3); auto opt = tuple_cast(i3_any_tup, i3);
CPPA_CHECK(opt.valid()); CPPA_CHECK(opt.valid());
...@@ -123,17 +124,72 @@ size_t test__pattern() ...@@ -123,17 +124,72 @@ size_t test__pattern()
CPPA_CHECK_EQUAL(plot(arr2), arr2_as_string); CPPA_CHECK_EQUAL(plot(arr2), arr2_as_string);
// some pattern objects to play with // some pattern objects to play with
pattern<atom_value, int, std::string> p0{util::wrapped<atom_value>()}; pattern<atom_value, int, string> p0{util::wrapped<atom_value>{}};
pattern<atom_value, int, std::string> p1(atom("FooBar")); pattern<atom_value, int, string> p1{atom("FooBar")};
pattern<atom_value, int, std::string> p2(atom("FooBar"), 42); pattern<atom_value, int, string> p2{atom("FooBar"), 42};
pattern<atom_value, int, std::string> p3(atom("FooBar"), 42, "hello world"); pattern<atom_value, int, string> p3{atom("FooBar"), 42, "hello world"};
pattern<atom_value, anything, std::string> p4(atom("FooBar"), anything(), "hello world"); pattern<atom_value, anything, string> p4{atom("FooBar"), anything(), "hello world"};
pattern<atom_value, anything> p5(atom("FooBar")); pattern<atom_value, anything> p5{atom("FooBar")};
pattern<anything> p6; pattern<anything> p6;
pattern<atom_value, anything> p7; pattern<atom_value, anything> p7;
pattern<atom_value, anything, std::string> p8; pattern<anything, string> p8;
// each one should accept x ... pattern<atom_value, int, string> p9{mk_tdata(atom("FooBar"), util::wrapped<int>(), "hello world")};
auto x = make_tuple(atom("FooBar"), 42, "hello world");
pattern<string, string, string> p10{"a", util::wrapped<string>{}, "c"};
// p0-p9 should accept t0
any_tuple t0 = make_cow_tuple(atom("FooBar"), 42, "hello world");
CPPA_CHECK((detail::matches(t0, p0)));
CPPA_CHECK((detail::matches(t0, p1)));
CPPA_CHECK((detail::matches(t0, p2)));
CPPA_CHECK((detail::matches(t0, p3)));
CPPA_CHECK((detail::matches(t0, p4)));
CPPA_CHECK((detail::matches(t0, p5)));
CPPA_CHECK((detail::matches(t0, p6)));
CPPA_CHECK((detail::matches(t0, p7)));
CPPA_CHECK((detail::matches(t0, p8)));
CPPA_CHECK((detail::matches(t0, p9)));
CPPA_CHECK(p0._matches_values(t0));
CPPA_CHECK(p1._matches_values(t0));
CPPA_CHECK(p2._matches_values(t0));
CPPA_CHECK(p3._matches_values(t0));
CPPA_CHECK(p4._matches_values(t0));
CPPA_CHECK(p5._matches_values(t0));
CPPA_CHECK(p6._matches_values(t0));
CPPA_CHECK(p7._matches_values(t0));
CPPA_CHECK(p8._matches_values(t0));
CPPA_CHECK(p9._matches_values(t0));
any_tuple t1 = make_cow_tuple("a", "b", "c");
CPPA_CHECK((detail::matches(t1, p8)));
CPPA_CHECK(p8._matches_values(t1));
CPPA_CHECK((detail::matches(t1, p10)));
CPPA_CHECK(p10._matches_values(t1));
std::vector<string> vec{"a", "b", "c"};
any_tuple t2 = any_tuple::view(vec);
CPPA_CHECK((detail::matches(t2, p8)));
CPPA_CHECK(p8._matches_values(t2));
CPPA_CHECK((detail::matches(t2, p10)));
CPPA_CHECK(p10._matches_values(t2));
pattern<atom_value, int> p11{atom("foo")};
any_tuple t3 = make_cow_tuple(atom("foo"), 42);
CPPA_CHECK((detail::matches(t3, p11)));
CPPA_CHECK(p11._matches_values(t3));
bool invoked = false;
match(t3)
(
on<atom("foo"), int>() >> [&](int i)
{
invoked = true;
CPPA_CHECK_EQUAL(42, i);
}
);
CPPA_CHECK_EQUAL(true, invoked);
/* /*
CPPA_CHECK(p0(x)); CPPA_CHECK(p0(x));
CPPA_CHECK(p1(x)); CPPA_CHECK(p1(x));
...@@ -145,7 +201,7 @@ size_t test__pattern() ...@@ -145,7 +201,7 @@ size_t test__pattern()
CPPA_CHECK(p7(x)); CPPA_CHECK(p7(x));
CPPA_CHECK(p8(x)); CPPA_CHECK(p8(x));
// ... but p2 and p3 should reject y // ... but p2 and p3 should reject y
auto y = make_tuple(atom("FooBar"), 24, "hello world"); auto y = make_cow_tuple(atom("FooBar"), 24, "hello world");
CPPA_CHECK_EQUAL(p0(y), true); CPPA_CHECK_EQUAL(p0(y), true);
CPPA_CHECK_EQUAL(p1(y), true); CPPA_CHECK_EQUAL(p1(y), true);
CPPA_CHECK_EQUAL(p2(y), false); CPPA_CHECK_EQUAL(p2(y), false);
...@@ -174,7 +230,7 @@ size_t test__pattern() ...@@ -174,7 +230,7 @@ size_t test__pattern()
CPPA_CHECK_EQUAL(v2, 3); CPPA_CHECK_EQUAL(v2, 3);
lambda_invoked[0] = true; lambda_invoked[0] = true;
}, },
on<std::string>() >> [&](const std::string& str) on<string>() >> [&](const string& str)
{ {
CPPA_CHECK_EQUAL(str, "hello foo"); CPPA_CHECK_EQUAL(str, "hello foo");
lambda_invoked[1] = true; lambda_invoked[1] = true;
...@@ -184,7 +240,7 @@ size_t test__pattern() ...@@ -184,7 +240,7 @@ size_t test__pattern()
CPPA_CHECK_EQUAL(value, 2); CPPA_CHECK_EQUAL(value, 2);
lambda_invoked[2] = true; lambda_invoked[2] = true;
}, },
on(1, val<std::string>(), any_vals) >> [&](const std::string& str) on(1, val<string>(), any_vals) >> [&](const string& str)
{ {
CPPA_CHECK_EQUAL(str, "2"); CPPA_CHECK_EQUAL(str, "2");
lambda_invoked[3] = true; lambda_invoked[3] = true;
...@@ -202,27 +258,27 @@ size_t test__pattern() ...@@ -202,27 +258,27 @@ size_t test__pattern()
} }
); );
// invokes lambda 0 // invokes lambda 0
patterns(make_tuple(1, "2", 3)); patterns(make_cow_tuple(1, "2", 3));
CPPA_CHECK(lambda_invoked[0]); CPPA_CHECK(lambda_invoked[0]);
reset_invoke_states(); reset_invoke_states();
// invokes lambda 1 // invokes lambda 1
patterns(make_tuple("hello foo")); patterns(make_cow_tuple("hello foo"));
CPPA_CHECK(lambda_invoked[1]); CPPA_CHECK(lambda_invoked[1]);
reset_invoke_states(); reset_invoke_states();
// invokes lambda 2 // invokes lambda 2
patterns(make_tuple("1", 2, 3)); patterns(make_cow_tuple("1", 2, 3));
CPPA_CHECK(lambda_invoked[2]); CPPA_CHECK(lambda_invoked[2]);
reset_invoke_states(); reset_invoke_states();
// invokes lambda 3 // invokes lambda 3
patterns(make_tuple(1, "2", "3")); patterns(make_cow_tuple(1, "2", "3"));
CPPA_CHECK(lambda_invoked[3]); CPPA_CHECK(lambda_invoked[3]);
reset_invoke_states(); reset_invoke_states();
// invokes lambda 4 // invokes lambda 4
patterns(make_tuple(atom("Foo"), 1)); patterns(make_cow_tuple(atom("Foo"), 1));
CPPA_CHECK(lambda_invoked[4]); CPPA_CHECK(lambda_invoked[4]);
reset_invoke_states(); reset_invoke_states();
// invokes lambda 5 // invokes lambda 5
patterns(make_tuple(1.0, 2.0f)); patterns(make_cow_tuple(1.0, 2.0f));
CPPA_CHECK(lambda_invoked[5]); CPPA_CHECK(lambda_invoked[5]);
reset_invoke_states(); reset_invoke_states();
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "test.hpp" #include "test.hpp"
#include "cppa/self.hpp" #include "cppa/self.hpp"
#include "cppa/tuple.hpp" #include "cppa/cow_tuple.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
#include "cppa/tuple_cast.hpp" #include "cppa/tuple_cast.hpp"
...@@ -140,7 +140,7 @@ size_t test__serialization() ...@@ -140,7 +140,7 @@ size_t test__serialization()
} }
{ {
any_tuple ttup = make_tuple(1, 2, actor_ptr(self)); any_tuple ttup = make_cow_tuple(1, 2, actor_ptr(self));
binary_serializer bs; binary_serializer bs;
bs << ttup; bs << ttup;
binary_deserializer bd(bs.data(), bs.size()); binary_deserializer bd(bs.data(), bs.size());
...@@ -176,7 +176,7 @@ size_t test__serialization() ...@@ -176,7 +176,7 @@ size_t test__serialization()
} }
{ {
any_tuple msg1 = cppa::make_tuple(42, std::string("Hello \"World\"!")); any_tuple msg1 = cppa::make_cow_tuple(42, std::string("Hello \"World\"!"));
auto msg1_tostring = to_string(msg1); auto msg1_tostring = to_string(msg1);
if (msg1str != msg1_tostring) if (msg1str != msg1_tostring)
{ {
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "test.hpp" #include "test.hpp"
#include "cppa/on.hpp" #include "cppa/on.hpp"
#include "cppa/tuple.hpp" #include "cppa/cow_tuple.hpp"
#include "cppa/pattern.hpp" #include "cppa/pattern.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
...@@ -28,9 +28,9 @@ using namespace cppa; ...@@ -28,9 +28,9 @@ using namespace cppa;
size_t test__tuple() size_t test__tuple()
{ {
CPPA_TEST(test__tuple); CPPA_TEST(test__tuple);
// check type correctness of make_tuple() // check type correctness of make_cow_tuple()
auto t0 = make_tuple("1", 2); auto t0 = make_cow_tuple("1", 2);
CPPA_CHECK((std::is_same<decltype(t0), cppa::tuple<std::string, int>>::value)); CPPA_CHECK((std::is_same<decltype(t0), cppa::cow_tuple<std::string, int>>::value));
auto t0_0 = get<0>(t0); auto t0_0 = get<0>(t0);
auto t0_1 = get<1>(t0); auto t0_1 = get<1>(t0);
// check implicit type conversion // check implicit type conversion
...@@ -41,7 +41,7 @@ size_t test__tuple() ...@@ -41,7 +41,7 @@ size_t test__tuple()
// use tuple cast to get a subtuple // use tuple cast to get a subtuple
any_tuple at0(t0); any_tuple at0(t0);
auto v0opt = tuple_cast<std::string, anything>(at0); auto v0opt = tuple_cast<std::string, anything>(at0);
CPPA_CHECK((std::is_same<decltype(v0opt), option<tuple<std::string>>>::value)); CPPA_CHECK((std::is_same<decltype(v0opt), option<cow_tuple<std::string>>>::value));
CPPA_CHECK((v0opt)); CPPA_CHECK((v0opt));
CPPA_CHECK( at0.size() == 2 CPPA_CHECK( at0.size() == 2
&& at0.at(0) == &get<0>(t0) && at0.at(0) == &get<0>(t0)
...@@ -49,7 +49,7 @@ size_t test__tuple() ...@@ -49,7 +49,7 @@ size_t test__tuple()
if (v0opt) if (v0opt)
{ {
auto& v0 = *v0opt; auto& v0 = *v0opt;
CPPA_CHECK((std::is_same<decltype(v0), tuple<std::string>&>::value)); CPPA_CHECK((std::is_same<decltype(v0), cow_tuple<std::string>&>::value));
CPPA_CHECK((std::is_same<decltype(get<0>(v0)), std::string const&>::value)); CPPA_CHECK((std::is_same<decltype(get<0>(v0)), std::string const&>::value));
CPPA_CHECK_EQUAL(v0.size(), 1); CPPA_CHECK_EQUAL(v0.size(), 1);
CPPA_CHECK_EQUAL(get<0>(v0), "1"); CPPA_CHECK_EQUAL(get<0>(v0), "1");
...@@ -61,19 +61,19 @@ size_t test__tuple() ...@@ -61,19 +61,19 @@ size_t test__tuple()
CPPA_CHECK_EQUAL(get<0>(v0), "1"); // v0 contains old value CPPA_CHECK_EQUAL(get<0>(v0), "1"); // v0 contains old value
CPPA_CHECK_NOT_EQUAL(&get<0>(t0), &get<0>(v0)); // no longer the same CPPA_CHECK_NOT_EQUAL(&get<0>(t0), &get<0>(v0)); // no longer the same
// check operator== // check operator==
auto lhs = make_tuple(1,2,3,4); auto lhs = make_cow_tuple(1,2,3,4);
auto rhs = make_tuple(static_cast<std::uint8_t>(1), 2.0, 3, 4); auto rhs = make_cow_tuple(static_cast<std::uint8_t>(1), 2.0, 3, 4);
CPPA_CHECK(lhs == rhs); CPPA_CHECK(lhs == rhs);
CPPA_CHECK(rhs == lhs); CPPA_CHECK(rhs == lhs);
} }
any_tuple at1 = make_tuple("one", 2, 3.f, 4.0); any_tuple at1 = make_cow_tuple("one", 2, 3.f, 4.0);
{ {
// perfect match // perfect match
auto opt0 = tuple_cast<std::string, int, float, double>(at1); auto opt0 = tuple_cast<std::string, int, float, double>(at1);
CPPA_CHECK(opt0); CPPA_CHECK(opt0);
if (opt0) if (opt0)
{ {
CPPA_CHECK((*opt0 == make_tuple("one", 2, 3.f, 4.0))); CPPA_CHECK((*opt0 == make_cow_tuple("one", 2, 3.f, 4.0)));
CPPA_CHECK_EQUAL(&get<0>(*opt0), at1.at(0)); CPPA_CHECK_EQUAL(&get<0>(*opt0), at1.at(0));
CPPA_CHECK_EQUAL(&get<1>(*opt0), at1.at(1)); CPPA_CHECK_EQUAL(&get<1>(*opt0), at1.at(1));
CPPA_CHECK_EQUAL(&get<2>(*opt0), at1.at(2)); CPPA_CHECK_EQUAL(&get<2>(*opt0), at1.at(2));
...@@ -100,7 +100,7 @@ size_t test__tuple() ...@@ -100,7 +100,7 @@ size_t test__tuple()
CPPA_CHECK(opt3); CPPA_CHECK(opt3);
if (opt3) if (opt3)
{ {
CPPA_CHECK((*opt3 == make_tuple("one", 4.0))); CPPA_CHECK((*opt3 == make_cow_tuple("one", 4.0)));
CPPA_CHECK_EQUAL(get<0>(*opt3), "one"); CPPA_CHECK_EQUAL(get<0>(*opt3), "one");
CPPA_CHECK_EQUAL(get<1>(*opt3), 4.0); CPPA_CHECK_EQUAL(get<1>(*opt3), 4.0);
CPPA_CHECK_EQUAL(&get<0>(*opt3), at1.at(0)); CPPA_CHECK_EQUAL(&get<0>(*opt3), at1.at(0));
......
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