Commit e60b3857 authored by neverlord's avatar neverlord

some performance tweaks and new pattern matching prototype

parent a61fb447
...@@ -44,3 +44,4 @@ Makefile ...@@ -44,3 +44,4 @@ Makefile
unit_testing/Makefile unit_testing/Makefile
libcppa.so* libcppa.so*
blob/cppatest blob/cppatest
callgrind.out.*
...@@ -31,6 +31,11 @@ struct tdata<> ...@@ -31,6 +31,11 @@ struct tdata<>
throw std::out_of_range(""); throw std::out_of_range("");
} }
inline const void* at(size_t) const
{
throw std::out_of_range("");
}
inline bool operator==(const tdata&) const inline bool operator==(const tdata&) const
{ {
return true; return true;
...@@ -48,7 +53,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> ...@@ -48,7 +53,10 @@ struct tdata<Head, Tail...> : tdata<Tail...>
inline tdata() : super(), head() { } inline tdata() : super(), head() { }
tdata(const Head& v0, const Tail&... vals) : super(vals...), head(v0) { } //tdata(const Head& v0, const Tail&... vals) : super(vals...), head(v0) { }
template<typename... Args>
tdata(const Head& v0, const Args&... vals) : super(vals...), head(v0) { }
inline tdata<Tail...>& tail() inline tdata<Tail...>& tail()
{ {
...@@ -67,6 +75,11 @@ struct tdata<Head, Tail...> : tdata<Tail...> ...@@ -67,6 +75,11 @@ struct tdata<Head, Tail...> : tdata<Tail...>
return head == other.head && tail() == other.tail(); return head == other.head && tail() == other.tail();
} }
inline const void* at(size_t pos) const
{
return (pos == 0) ? &head : super::at(pos - 1);
}
}; };
template<size_t N, typename... Tn> template<size_t N, typename... Tn>
......
...@@ -43,6 +43,9 @@ class yielding_message_queue_impl : public message_queue ...@@ -43,6 +43,9 @@ class yielding_message_queue_impl : public message_queue
std::uint32_t m_active_timeout_id; std::uint32_t m_active_timeout_id;
scheduled_actor* m_parent; scheduled_actor* m_parent;
std::atomic<int> m_state; std::atomic<int> m_state;
const uniform_type_info* m_atom_value_uti;
const uniform_type_info* m_ui32_uti;
const uniform_type_info* m_actor_ptr_uti;
util::single_reader_queue<queue_node> m_queue; util::single_reader_queue<queue_node> m_queue;
void yield_until_not_empty(); void yield_until_not_empty();
......
...@@ -20,6 +20,8 @@ class any_tuple_iterator ...@@ -20,6 +20,8 @@ class any_tuple_iterator
template<typename T> template<typename T>
inline const T& value() const; inline const T& value() const;
inline const void* value_ptr() const;
inline const cppa::uniform_type_info& type() const; inline const cppa::uniform_type_info& type() const;
inline size_t position() const; inline size_t position() const;
...@@ -44,6 +46,11 @@ inline const uniform_type_info& any_tuple_iterator::type() const ...@@ -44,6 +46,11 @@ inline const uniform_type_info& any_tuple_iterator::type() const
return m_data.utype_info_at(m_pos); return m_data.utype_info_at(m_pos);
} }
inline const void* any_tuple_iterator::value_ptr() const
{
return m_data.at(m_pos);
}
inline size_t any_tuple_iterator::position() const inline size_t any_tuple_iterator::position() const
{ {
return m_pos; return m_pos;
......
#CXX = /opt/local/bin/g++-mp-4.6 #CXX = /opt/local/bin/g++-mp-4.6
CXX = /usr/bin/g++-4.6 CXX = /usr/bin/g++-4.6
CXXFLAGS = -std=c++0x -pedantic -Wall -Wextra -I/opt/local/include/ -I../ -fpermissive -O2 CXXFLAGS = -std=c++0x -pedantic -Wall -Wextra -I/opt/local/include/ -I../ -fpermissive -O2 -g
LIBS = -L../.libs/ -lcppa -L/opt/local/lib -L/usr/lib -lboost_thread-mt LIBS = -L../.libs/ -lcppa -L/opt/local/lib -L/usr/lib -lboost_thread-mt
all: all:
$(CXX) $(CXXFLAGS) -o sequential_send sequential_send.cpp $(LIBS) $(CXX) $(CXXFLAGS) -o sequential_send sequential_send.cpp $(LIBS)
$(CXX) $(CXXFLAGS) -o parallel_send parallel_send.cpp $(LIBS) # $(CXX) $(CXXFLAGS) -o parallel_send parallel_send.cpp $(LIBS)
...@@ -700,7 +700,7 @@ class uniform_type_info_map_helper ...@@ -700,7 +700,7 @@ class uniform_type_info_map_helper
insert<double>(d); insert<double>(d);
insert<long double>(d); insert<long double>(d);
} }
insert<any_type>(d); //insert<any_type>(d);
// first: signed // first: signed
// second: unsigned // second: unsigned
push<char, push<char,
......
...@@ -42,6 +42,9 @@ yielding_message_queue_impl::queue_node::queue_node(const any_tuple& content) ...@@ -42,6 +42,9 @@ yielding_message_queue_impl::queue_node::queue_node(const any_tuple& content)
yielding_message_queue_impl::yielding_message_queue_impl(scheduled_actor* p) yielding_message_queue_impl::yielding_message_queue_impl(scheduled_actor* p)
: m_has_pending_timeout_request(false), m_active_timeout_id(0) : m_has_pending_timeout_request(false), m_active_timeout_id(0)
, m_parent(p), m_state(ready) , m_parent(p), m_state(ready)
, m_atom_value_uti(uniform_typeid<atom_value>())
, m_ui32_uti(uniform_typeid<std::uint32_t>())
, m_actor_ptr_uti(uniform_typeid<actor_ptr>())
{ {
} }
...@@ -60,6 +63,36 @@ enum filter_result ...@@ -60,6 +63,36 @@ enum filter_result
yielding_message_queue_impl::filter_result yielding_message_queue_impl::filter_result
yielding_message_queue_impl::filter_msg(const any_tuple& msg) yielding_message_queue_impl::filter_msg(const any_tuple& msg)
{ {
if ( m_trap_exit == false
&& msg.size() == 3
&& m_atom_value_uti == &(msg.utype_info_at(0)))
{
if (*reinterpret_cast<const atom_value*>(msg.at(0)) == atom(":Exit"))
{
if ( m_actor_ptr_uti == &(msg.utype_info_at(1))
&& m_ui32_uti == &(msg.utype_info_at(2)))
{
auto why = *reinterpret_cast<const std::uint32_t*>(msg.at(1));
if (why != exit_reason::normal)
{
self()->quit(why);
}
return normal_exit_signal;
}
}
}
if ( msg.size() == 2
&& m_atom_value_uti == &(msg.utype_info_at(0))
&& atom(":Timeout") == *reinterpret_cast<const atom_value*>(msg.at(0)))
{
if (m_ui32_uti == &(msg.utype_info_at(1)))
{
auto id = *reinterpret_cast<const std::uint32_t*>(msg.at(1));
return (id == m_active_timeout_id) ? timeout_message
: expired_timeout_message;
}
}
/*
if ( m_trap_exit == false if ( m_trap_exit == false
&& match<atom_value, actor_ptr, std::uint32_t>(msg, && match<atom_value, actor_ptr, std::uint32_t>(msg,
nullptr, nullptr,
...@@ -81,6 +114,7 @@ yielding_message_queue_impl::filter_msg(const any_tuple& msg) ...@@ -81,6 +114,7 @@ yielding_message_queue_impl::filter_msg(const any_tuple& msg)
return (id == m_active_timeout_id) ? timeout_message return (id == m_active_timeout_id) ? timeout_message
: expired_timeout_message; : expired_timeout_message;
} }
*/
return ordinary_message; return ordinary_message;
} }
......
...@@ -24,6 +24,12 @@ ...@@ -24,6 +24,12 @@
#include "cppa/detail/task_scheduler.hpp" #include "cppa/detail/task_scheduler.hpp"
#include "cppa/detail/thread_pool_scheduler.hpp" #include "cppa/detail/thread_pool_scheduler.hpp"
// header for experimental stuff
#include "cppa/util/filter_type_list.hpp"
#include "cppa/util/any_tuple_iterator.hpp"
#include "cppa/detail/matcher_arguments.hpp"
#define CPPA_TEST_CATCH_BLOCK() \ #define CPPA_TEST_CATCH_BLOCK() \
catch (std::exception& e) \ catch (std::exception& e) \
{ \ { \
...@@ -115,8 +121,337 @@ inline bool found_key(Iterator& i, Container& cont, Key&& key) ...@@ -115,8 +121,337 @@ inline bool found_key(Iterator& i, Container& cont, Key&& key)
return (i = cont.find(std::forward<Key>(key))) != cont.end(); return (i = cont.find(std::forward<Key>(key))) != cont.end();
} }
namespace {
using namespace cppa;
struct wildcard { };
typedef std::vector<const uniform_type_info*> uti_vec;
template<typename T>
struct is_wildcard { static constexpr bool value = false; };
template<>
struct is_wildcard<wildcard> { static constexpr bool value = true; };
template<typename OutputIterator, typename T0>
void fill_vec(OutputIterator& ii)
{
*ii = is_wildcard<T0>::value ? nullptr : cppa::uniform_typeid<T0>();
}
template<typename OutputIterator, typename T0, typename T1, typename... Tn>
void fill_vec(OutputIterator& ii);
template<typename OutputIterator, typename T0>
struct fill_vec_util
{
template<typename T1, typename... Tn>
static void _(OutputIterator& ii)
{
*ii = cppa::uniform_typeid<T0>();
++ii;
fill_vec<OutputIterator,T1,Tn...>(ii);
}
};
template<typename OutputIterator>
struct fill_vec_util<OutputIterator, wildcard>
{
template<typename T1, typename... Tn>
static void _(OutputIterator& ii)
{
*ii = nullptr;
++ii;
fill_vec<OutputIterator,T1,Tn...>(ii);
}
};
template<typename OutputIterator, typename T0, typename T1, typename... Tn>
void fill_vec(OutputIterator& ii)
{
fill_vec_util<OutputIterator,T0>::template _<T1,Tn...>(ii);
}
bool match_fun(const cppa::uniform_type_info** utis, size_t utis_size,
const cppa::any_tuple& msg)
{
if (msg.size() == utis_size)
{
for (size_t i = 0; i < utis_size; ++i)
{
if (utis[i] != &(msg.utype_info_at(i))) return false;
}
return true;
}
return false;
}
bool compare_at(size_t pos,
const cppa::any_tuple& msg,
const cppa::uniform_type_info* uti,
const void* value)
{
if (uti == &(msg.utype_info_at(pos)))
{
return (value) ? uti->equal(msg.at(pos), value) : true;
}
return false;
}
template<typename T>
struct tdata_from_type_list;
template<typename... T>
struct tdata_from_type_list<cppa::util::type_list<T...>>
{
typedef cppa::detail::tdata<T...> type;
};
struct matcher_types_args
{
size_t m_pos;
size_t m_size;
void const* const* m_data;
cppa::uniform_type_info const* const* m_types;
public:
matcher_types_args(size_t msize,
void const* const* mdata,
cppa::uniform_type_info const* const* mtypes)
: m_pos(0)
, m_size(msize)
, m_data(mdata)
, m_types(mtypes)
{
}
matcher_types_args(const matcher_types_args&) = default;
matcher_types_args& operator=(const matcher_types_args&) = default;
inline bool at_end() const { return m_pos == m_size; }
inline matcher_types_args& next()
{
++m_pos;
return *this;
}
inline const uniform_type_info* type() const
{
return m_types[m_pos];
}
inline bool has_value() const { return value() != nullptr; }
inline const void* value() const
{
return m_data[m_pos];
}
};
struct matcher_tuple_args
{
util::any_tuple_iterator iter;
std::vector<size_t>* mapping;
matcher_tuple_args(const any_tuple& tup,
std::vector<size_t>* mv = 0)
: iter(tup), mapping(mv)
{
}
matcher_tuple_args(const util::any_tuple_iterator& from_iter,
std::vector<size_t>* mv = nullptr)
: iter(from_iter), mapping(mv)
{
}
inline bool at_end() const { return iter.at_end(); }
inline matcher_tuple_args& next()
{
iter.next();
return *this;
}
inline matcher_tuple_args& push_mapping()
{
if (mapping) mapping->push_back(iter.position());
return *this;
}
inline const uniform_type_info* type() const
{
return &(iter.type());
}
inline const void* value() const
{
return iter.value_ptr();
}
};
bool do_match(matcher_types_args& ty_args, matcher_tuple_args& tu_args)
{
// nullptr == wildcard
if (ty_args.at_end() && tu_args.at_end())
{
return true;
}
if (ty_args.type() == nullptr)
{
// perform submatching
ty_args.next();
if (ty_args.at_end())
{
// always true at the end of the pattern
return true;
}
auto ty_cpy = ty_args;
std::vector<size_t> mv;
auto mv_ptr = (tu_args.mapping) ? &mv : nullptr;
// iterate over tu_iter until we found a match
while (tu_args.at_end() == false)
{
matcher_tuple_args tu_cpy(tu_args.iter, mv_ptr);
if (do_match(ty_cpy, tu_cpy))
{
if (mv_ptr)
{
tu_args.mapping->insert(tu_args.mapping->end(),
mv.begin(),
mv.end());
}
return true;
}
// next iteration
mv.clear();
tu_args.next();
}
}
else
{
if (tu_args.at_end() == false && ty_args.type() == tu_args.type())
{
if ( ty_args.has_value() == false
|| ty_args.type()->equal(ty_args.value(), tu_args.value()))
{
tu_args.push_mapping();
return do_match(ty_args.next(), tu_args.next());
}
}
}
return false;
}
template<typename... Types>
struct foobar_test
{
typedef typename cppa::util::filter_type_list<wildcard, cppa::util::type_list<Types...> >::type filtered_types;
typename tdata_from_type_list<filtered_types>::type m_data;
const void* m_data_ptr[sizeof...(Types)];
const cppa::uniform_type_info* m_utis[sizeof...(Types)];
foobar_test()
{
const cppa::uniform_type_info** iter = m_utis;
fill_vec<decltype(iter), Types...>(iter);
for (size_t i = 0; i < sizeof...(Types); ++i)
{
m_data_ptr[i] = nullptr;
}
}
template<typename Arg0, typename... Args>
foobar_test(const Arg0& arg0, const Args&... args) : m_data(arg0, args...)
{
const cppa::uniform_type_info** iter = m_utis;
fill_vec<decltype(iter), Types...>(iter);
size_t j = 0;
for (size_t i = 0; i < sizeof...(Types); ++i)
{
if (m_utis[i] == nullptr)
{
m_data_ptr[i] = nullptr;
}
else
{
if (j < (sizeof...(Args) + 1))
{
m_data_ptr[i] = m_data.at(j++);
}
else
{
m_data_ptr[i] = nullptr;
}
}
}
}
const cppa::uniform_type_info& operator[](size_t pos) const
{
return *(m_utis[pos]);
}
bool operator()(const cppa::any_tuple& msg) const
{
matcher_types_args ty(sizeof...(Types), m_data_ptr, m_utis);
matcher_tuple_args tu(msg);
return do_match(ty, tu);
}
};
} // namespace <anonmyous> w/ using cppa
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
cout << std::boolalpha;
auto x = cppa::make_tuple(0, 0.0f, 0.0);
foobar_test<wildcard> ft0;
foobar_test<int,float,double> ft1;
/*
cout << "ft1[0] = " << ft1[0].name() << ", "
<< "ft1[1] = " << ft1[1].name() << ", "
<< "ft1[2] = " << ft1[2].name()
<< endl;
*/
cout << "ft0(x) [expected: true] = " << ft0(x) << endl;
cout << "ft1(x) [expected: true] = " << ft1(x) << endl;
foobar_test<int,float,double> ft2(0);
cout << "ft2(x) [expected: true] = " << std::boolalpha << ft2(x) << endl;
foobar_test<int,float,double> ft3(0, 0.f);
cout << "ft3(x) [expected: true] = " << std::boolalpha << ft3(x) << endl;
foobar_test<int,float,double> ft4(0, 0.f, 0.0);
cout << "ft4(x) [expected: true] = " << std::boolalpha << ft4(x) << endl;
foobar_test<int,float,double> ft5(0, 0.1f, 0.0);
cout << "ft5(x) [expected: false] = " << std::boolalpha << ft5(x) << endl;
return 0;
auto args = get_kv_pairs(argc, argv); auto args = get_kv_pairs(argc, argv);
if (!args.empty()) if (!args.empty())
{ {
......
...@@ -84,7 +84,7 @@ size_t test__uniform_type() ...@@ -84,7 +84,7 @@ size_t test__uniform_type()
"@0", // cppa::util::void_type "@0", // cppa::util::void_type
// default announced cppa types // default announced cppa types
"@atom", // cppa::atom_value "@atom", // cppa::atom_value
"@*", // cppa::any_type //"@*", // cppa::any_type
"@<>", // cppa::any_tuple "@<>", // cppa::any_tuple
"@msg", // cppa::message "@msg", // cppa::message
"@actor", // cppa::actor_ptr "@actor", // cppa::actor_ptr
......
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