Commit 3f194ef3 authored by neverlord's avatar neverlord

maintenance

parent f0cd281c
......@@ -136,6 +136,7 @@ nobase_library_include_HEADERS = \
cppa/detail/tdata.hpp \
cppa/detail/thread_pool_scheduler.hpp \
cppa/detail/to_uniform_name.hpp \
cppa/detail/tuple_cast_impl.hpp \
cppa/detail/tuple_vals.hpp \
cppa/detail/type_to_ptype.hpp \
cppa/detail/types_array.hpp \
......
......@@ -244,12 +244,10 @@ cppa/util/type_pair.hpp
cppa/util/tbind.hpp
cppa/option.hpp
cppa/tuple_cast.hpp
cppa/detail/matches.hpp
cppa/util/is_mutable_ref.hpp
cppa/util/is_manipulator.hpp
cppa/util/apply_tuple.hpp
cppa/any_tuple_view.hpp
cppa/match.hpp
benchmarks/Matching.scala
benchmarks/matching.cpp
benchmarks/matching.erl
......@@ -262,3 +260,5 @@ cppa/type_value_pair.hpp
examples/dining_philosophers.cpp
cppa/detail/disablable_delete.hpp
unit_testing/test__fixed_vector.cpp
cppa/detail/tuple_cast_impl.hpp
cppa/match.hpp
......@@ -101,13 +101,34 @@ struct abstract_tuple : ref_counted
return {m_tuple, m_pos + offset};
}
inline const_iterator& operator+=(size_t offset)
{
m_pos += offset;
return *this;
}
inline const_iterator operator-(size_t offset)
{
CPPA_REQUIRE(m_pos >= offset);
return {m_tuple, m_pos - offset};
}
inline const_iterator& operator-=(size_t offset)
{
CPPA_REQUIRE(m_pos >= offset);
m_pos -= offset;
return *this;
}
inline size_t position() const { return m_pos; }
void const* value() const { return m_tuple.at(m_pos); }
uniform_type_info const* type() const { return m_tuple.type_at(m_pos); }
type_value_pair operator*() { return {type(), value()}; }
const_iterator& operator*() { return *this; }
operator type_value_pair() const { return {type(), value()}; }
};
......@@ -117,6 +138,27 @@ struct abstract_tuple : 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 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 types_only_eq(abstract_tuple::const_iterator const& lhs,
type_value_pair const& rhs)
{
return lhs.type() == rhs.first;
}
} } // namespace cppa::detail
#endif // ABSTRACT_TUPLE_HPP
......@@ -40,8 +40,10 @@
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/apply_tuple.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/serialize_tuple.hpp"
......@@ -71,11 +73,16 @@ class decorated_tuple : public abstract_tuple
return {(new decorated_tuple(std::move(d)))->init()};
}
// creates a subtuple form @p d with an offset
static cow_pointer_type create(cow_pointer_type d, size_t offset)
{
return {(new decorated_tuple(std::move(d)))->init(offset)};
}
virtual void* mutable_at(size_t pos)
{
CPPA_REQUIRE(pos < size());
// const_cast is safe because decorated_tuple is used in cow_ptrs only
return const_cast<void*>(m_data[pos].second);
return m_decorated->mutable_at(m_mapping[pos]);
}
virtual size_t size() const
......@@ -91,13 +98,13 @@ class decorated_tuple : public abstract_tuple
virtual void const* at(size_t pos) const
{
CPPA_REQUIRE(pos < size());
return m_data[pos].second;
return m_decorated->at(m_mapping[pos]);
}
virtual uniform_type_info const* type_at(size_t pos) const
{
CPPA_REQUIRE(pos < size());
return m_data[pos].first;
return m_decorated->type_at(m_mapping[pos]);
}
virtual std::type_info const& impl_type() const
......@@ -108,7 +115,7 @@ class decorated_tuple : public abstract_tuple
private:
cow_pointer_type m_decorated;
type_value_pair m_data[sizeof...(ElementTypes)];
vector_type m_mapping;
decorated_tuple(cow_pointer_type const& d) : m_decorated(d) { }
......@@ -117,9 +124,8 @@ class decorated_tuple : public abstract_tuple
decorated_tuple(decorated_tuple const& other)
: abstract_tuple()
, m_decorated(other.m_decorated)
, m_mapping(other.m_mapping)
{
// both instances point to the same data
std::copy(other.begin(), other.end(), m_data);
}
decorated_tuple* init(vector_type const& v)
......@@ -127,24 +133,26 @@ class decorated_tuple : public abstract_tuple
CPPA_REQUIRE(m_decorated->size() >= sizeof...(ElementTypes));
CPPA_REQUIRE(v.size() == sizeof...(ElementTypes));
CPPA_REQUIRE(*(std::max_element(v.begin(), v.end())) < m_decorated->size());
for (size_t i = 0; i < sizeof...(ElementTypes); ++i)
{
auto x = v[i];
m_data[i].first = m_decorated->type_at(x);
m_data[i].second = m_decorated->at(x);
}
m_mapping.resize(v.size());
std::copy(v.begin(), v.end(), m_mapping.begin());
return this;
}
decorated_tuple* init()
{
CPPA_REQUIRE(m_decorated->size() >= sizeof...(ElementTypes));
// copy first n elements
for (size_t i = 0; i < sizeof...(ElementTypes); ++i)
{
m_data[i].first = m_decorated->type_at(i);
m_data[i].second = m_decorated->at(i);
}
size_t i = 0;
m_mapping.resize(sizeof...(ElementTypes));
std::generate(m_mapping.begin(), m_mapping.end(), [&](){return i++;});
return this;
}
decorated_tuple* init(size_t offset)
{
CPPA_REQUIRE((m_decorated->size() - offset) == sizeof...(ElementTypes));
size_t i = offset;
m_mapping.resize(sizeof...(ElementTypes));
std::generate(m_mapping.begin(), m_mapping.end(), [&](){return i++;});
return this;
}
......
......@@ -35,6 +35,7 @@
#include <cstddef>
#include <cstdint>
#include "cppa/match.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_cast.hpp"
#include "cppa/util/duration.hpp"
......@@ -42,7 +43,6 @@
#include "cppa/util/fixed_vector.hpp"
#include "cppa/util/callable_trait.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/intermediate.hpp"
// forward declaration
......@@ -183,7 +183,7 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
template<typename T>
bool invoke_impl(T const& data) const
{
if (matches(data, *m_pattern))
if (match(data, *m_pattern))
{
m_iimpl.m_fun();
return true;
......@@ -206,7 +206,7 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
intermediate* get_intermediate(any_tuple const& data)
{
return matches(data, *m_pattern) ? &m_iimpl : nullptr;
return match(data, *m_pattern) ? &m_iimpl : nullptr;
}
};
......
This diff is collapsed.
This diff is collapsed.
......@@ -74,11 +74,6 @@ class tuple_vals : public abstract_tuple
return m_data;
}
inline data_type& data_ref()
{
return m_data;
}
size_t size() const
{
return sizeof...(ElementTypes);
......
This diff is collapsed.
......@@ -119,26 +119,34 @@ class tuple
tuple& operator=(tuple&&) = default;
tuple& operator=(tuple const&) = default;
static tuple from(cow_ptr_type ptr)
inline static tuple from(cow_ptr_type ptr)
{
if (ptr->size() == sizeof...(ElementTypes))
{
// *this == *ptr
return {priv_ctor(), std::move(ptr)};
}
else
{
// *this is a subtuple of *ptr
return {priv_ctor(), decorated_type::create(std::move(ptr))};
}
return {priv_ctor(), std::move(ptr)};
}
static tuple from(cow_ptr_type ptr,
util::fixed_vector<size_t, num_elements> const& mv)
inline static tuple from(cow_ptr_type ptr,
util::fixed_vector<size_t, num_elements> const& mv)
{
return {priv_ctor(), decorated_type::create(std::move(ptr), mv)};
}
// *this is a [0, N) subtuple
inline static tuple subtuple(cow_ptr_type ptr)
{
// N == ptr->size() ?
if (ptr->size() == num_elements) return from(std::move(ptr));
// no, create subtuple
return {priv_ctor(), decorated_type::create(std::move(ptr))};
}
inline static tuple offset_subtuple(cow_ptr_type ptr, size_t offset)
{
// N == ptr->size() ?
if (ptr->size() == num_elements) return from(std::move(ptr));
// no, create subtuple
return {priv_ctor(), decorated_type::create(std::move(ptr), offset)};
}
/**
* @brief Gets the size of this tuple.
*/
......
......@@ -35,93 +35,23 @@
#include "cppa/option.hpp"
#include "cppa/pattern.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/decorated_tuple.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace cppa {
#include "cppa/detail/tuple_cast_impl.hpp"
// cast using a pattern
template<class ResultTuple, class Tuple, typename... P>
option<ResultTuple> tuple_cast_impl(Tuple const& tup, pattern<P...> const& p)
{
typedef util::type_list<P...> types;
static constexpr int apos = util::tl_find<types, anything>::value;
// no anything in given template parameter pack
// or anything at end of template parameter pack
if (apos == -1 || apos == (sizeof...(P) - 1))
{
if (detail::matches(tup, p))
{
return {ResultTuple::from(tup.vals())};
}
}
else
{
typename pattern<P...>::mapping_vector mv;
if (detail::matches(tup, p, &mv))
{
if (mv.size() == tup.size()) // perfect match
{
return {ResultTuple::from(tup.vals())};
}
else
{
return {ResultTuple::from(tup.vals(), mv)};
}
}
}
return { };
}
// cast using types
template<class ResultTuple, class Tuple, typename... T>
option<ResultTuple> tuple_cast_impl(Tuple const& tup)
{
typedef util::type_list<T...> types;
static constexpr int apos = util::tl_find<types, anything>::value;
// no anything in given template parameter pack
// or anything at end of template parameter pack
if (apos == -1 || apos == (sizeof...(T) - 1))
{
if (tup.size() >= sizeof...(T))
{
auto& tarr = detail::static_types_array<T...>::arr;
static constexpr int end = (apos == -1) ? sizeof...(T) : apos;
for (int i = 0; i < end; ++i)
{
if (tarr[i] != tup.type_at(i)) return { };
}
// always a perfect match or subtuple
return {ResultTuple::from(tup.vals())};
}
}
else
{
util::fixed_vector<size_t, ResultTuple::num_elements> mv;
if (detail::matches(tup, detail::static_types_array<T...>::arr, &mv))
{
// never a perfect match
return {ResultTuple::from(tup.vals(), mv)};
}
}
return { };
}
namespace cppa {
// cast using a pattern
template<typename... P>
auto tuple_cast(any_tuple const& tup, pattern<P...> const& p)
template<typename... T>
auto tuple_cast(any_tuple const& tup, pattern<T...> const& p)
-> option<
typename tuple_from_type_list<
typename pattern<P...>::filtered_types
typename pattern<T...>::filtered_types
>::type>
{
typedef typename pattern<P...>::filtered_types filtered_types;
typedef typename pattern<T...>::filtered_types filtered_types;
typedef typename tuple_from_type_list<filtered_types>::type tuple_type;
return tuple_cast_impl<tuple_type, any_tuple, P...>(tup, p);
static constexpr auto impl = detail::select_tuple_cast_impl<T...>::value;
return detail::tuple_cast_impl<impl, tuple_type, T...>::_(tup, p);
}
// cast using types
......@@ -137,38 +67,9 @@ auto tuple_cast(any_tuple const& tup)
{
typedef decltype(tuple_cast<T...>(tup)) result_type;
typedef typename result_type::value_type tuple_type;
return tuple_cast_impl<tuple_type, any_tuple, T...>(tup);
}
/*
template<typename... P>
auto tuple_cast(any_tuple_view const& tup, pattern<P...> const& p)
-> option<
typename tuple_view_from_type_list<
typename pattern<P...>::filtered_types
>::type>
{
typedef typename pattern<P...>::filtered_types filtered_types;
typedef typename tuple_view_from_type_list<filtered_types>::type tuple_type;
return tuple_cast_impl<tuple_type, any_tuple_view, P...>(tup, p);
}
// cast using types
template<typename... T>
auto tuple_cast(any_tuple_view const& tup)
-> option<
typename tuple_view_from_type_list<
typename util::tl_filter_not<
util::type_list<T...>,
util::tbind<std::is_same, anything>::type
>::type
>::type>
{
typedef decltype(tuple_cast<T...>(tup)) result_type;
typedef typename result_type::value_type tuple_type;
return tuple_cast_impl<tuple_type, any_tuple_view, T...>(tup);
static constexpr auto impl = detail::select_tuple_cast_impl<T...>::value;
return detail::tuple_cast_impl<impl, tuple_type, T...>::_(tup);
}
*/
} // namespace cppa
......
......@@ -84,17 +84,8 @@ class fixed_vector
void resize(size_type s)
{
CPPA_REQUIRE(s < MaxSize);
if (s > m_size)
{
auto x = T();
auto old_size = m_size;
for (auto i = old_size; i < s; ++i) push_back(x);
}
else
{
m_size = s;
}
CPPA_REQUIRE(s <= MaxSize);
m_size = s;
}
fixed_vector(std::initializer_list<T> init) : m_size(init.size())
......
......@@ -135,14 +135,21 @@ template<typename What, int Pos>
struct tl_find<type_list<>, What, Pos>
{
static constexpr int value = -1;
typedef type_list<> rest_list;
};
template<typename What, int Pos, typename... Tail>
struct tl_find<type_list<What, Tail...>, What, Pos>
{
static constexpr int value = Pos;
typedef type_list<Tail...> rest_list;
};
template<typename What, int Pos, typename Head, typename... Tail>
struct tl_find<type_list<Head, Tail...>, What, Pos>
{
static constexpr int value = std::is_same<Head, What>::value
? Pos
: tl_find<type_list<Tail...>, What, Pos+1>::value;
static constexpr int value = tl_find<type_list<Tail...>, What, Pos+1>::value;
typedef typename tl_find<type_list<Tail...>, What, Pos+1>::rest_list rest_list;
};
// list list::first_n(size_t)
......@@ -209,6 +216,45 @@ struct tl_exists<type_list<>, Predicate>
static constexpr bool value = false;
};
// size_t list::count(predicate)
/**
* @brief Counts the number of elements in the list which satisfy a predicate.
*/
template<class List, template <typename> class Predicate>
struct tl_count
{
static constexpr size_t value =
(Predicate<typename List::head>::value ? 1 : 0)
+ tl_count<typename List::tail, Predicate>::value;
};
template<template <typename> class Predicate>
struct tl_count<type_list<>, Predicate>
{
static constexpr size_t value = 0;
};
// size_t list::count_not(predicate)
/**
* @brief Counts the number of elements in the list which satisfy a predicate.
*/
template<class List, template <typename> class Predicate>
struct tl_count_not
{
static constexpr size_t value =
(Predicate<typename List::head>::value ? 0 : 1)
+ tl_count_not<typename List::tail, Predicate>::value;
};
template<template <typename> class Predicate>
struct tl_count_not<type_list<>, Predicate>
{
static constexpr size_t value = 0;
};
// bool list::zipped_forall(predicate)
/**
......
......@@ -32,8 +32,8 @@
#include <algorithm>
#include "cppa/self.hpp"
#include "cppa/match.hpp"
#include "cppa/exception.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/invokable.hpp"
#include "cppa/detail/intermediate.hpp"
#include "cppa/detail/converted_thread_context.hpp"
......@@ -100,10 +100,11 @@ void converted_thread_context::dequeue(timed_invoke_rules& rules) /*override*/
}
while (dq(node, rules, buffer) == false);
}
converted_thread_context::throw_on_exit_result
converted_thread_context::throw_on_exit(any_tuple const& msg)
{
if (matches(msg, m_exit_msg_pattern))
if (match(msg, m_exit_msg_pattern))
{
auto reason = msg.get_as<std::uint32_t>(1);
if (reason != exit_reason::normal)
......
......@@ -5,8 +5,8 @@
#include "cppa/on.hpp"
#include "cppa/atom.hpp"
#include "cppa/tuple.hpp"
#include "cppa/match.hpp"
#include "cppa/tuple.hpp"
#include "cppa/option.hpp"
#include "cppa/pattern.hpp"
#include "cppa/announce.hpp"
......
......@@ -39,30 +39,14 @@ size_t test__tuple()
CPPA_CHECK((std::is_same<decltype(t0_1), int>::value));
CPPA_CHECK_EQUAL(t0_0, "1");
CPPA_CHECK_EQUAL(t0_1, 2);
// get a view of t0
any_tuple atup0(t0);
CPPA_CHECK(atup0.size() == 2 && atup0.at(0) == &get<0>(t0));
/*
auto v1opt = tuple_cast<std::string, anything>(any_tuple_view(atup0));
// the tuple_view forces atup0 to detach from t0
CPPA_CHECK(atup0.size() == 2 && atup0.at(0) != &get<0>(t0));
CPPA_CHECK((v1opt));
if (v1opt)
{
auto& v1 = *v1opt;
CPPA_CHECK((std::is_same<decltype(v1), tuple_view<std::string>&>::value));
CPPA_CHECK_EQUAL(v1.size(), 1);
auto& v1_0 = get<0>(v1);
CPPA_CHECK_EQUAL(v1_0, "1");
CPPA_CHECK_EQUAL(atup0.at(0), &(get<0>(v1))); // point to the same
}
*/
// use tuple cast to get a subtuple
any_tuple at0(t0);
auto v0opt = tuple_cast<std::string, anything>(at0);
CPPA_CHECK((std::is_same<decltype(v0opt), option<tuple<std::string>>>::value));
CPPA_CHECK((v0opt));
CPPA_CHECK(at0.size() == 2 && at0.at(0) == &get<0>(t0));
CPPA_CHECK( at0.size() == 2
&& at0.at(0) == &get<0>(t0)
&& at0.at(1) == &get<1>(t0));
if (v0opt)
{
auto& v0 = *v0opt;
......@@ -84,5 +68,24 @@ size_t test__tuple()
CPPA_CHECK_EQUAL(lhs, rhs);
CPPA_CHECK_EQUAL(rhs, lhs);
}
any_tuple at1 = make_tuple("one", 2, 3.f, 4.0);
{
// perfect match
auto opt0 = tuple_cast<std::string, int, float, double>(at1);
CPPA_CHECK(opt0);
if (opt0) { CPPA_CHECK_EQUAL(*opt0, make_tuple("one", 2, 3.f, 4.0)); }
// leading wildcard
auto opt1 = tuple_cast<anything, double>(at1);
CPPA_CHECK(opt1);
if (opt1) { CPPA_CHECK_EQUAL(get<0>(*opt1), 4.0); }
// trailing wildcard
auto opt2 = tuple_cast<std::string, anything>(at1);
CPPA_CHECK(opt2);
if (opt2) { CPPA_CHECK_EQUAL(get<0>(*opt2), "one"); }
// wildcard in between
auto opt3 = tuple_cast<std::string, anything, double>(at1);
CPPA_CHECK(opt3);
if (opt3) { CPPA_CHECK_EQUAL(*opt3, make_tuple("one", 4.0)); }
}
return CPPA_TEST_RESULT;
}
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