Commit 8021cd02 authored by neverlord's avatar neverlord

fixed on()

parent 19af9398
......@@ -93,3 +93,6 @@ cppa/detail/channel.hpp
cppa/message_receiver.hpp
src/message_receiver.cpp
src/actor.cpp
src/actor_private.cpp
cppa/util/eval_first_n.hpp
cppa/util/first_n.hpp
......@@ -15,11 +15,13 @@ class actor : public message_receiver
public:
typedef cppa::intrusive_ptr<detail::actor_public> ptr_type;
typedef cppa::intrusive_ptr<detail::actor_private> ptr_type;
actor() = default;
inline actor(detail::actor_public* ptr) : super(ptr) { }
~actor();
inline actor(detail::actor_private* ptr) : super(ptr) { }
inline actor(const ptr_type& ptr) : super(ptr) { }
......
#ifndef ACTOR_PRIVATE_HPP
#define ACTOR_PRIVATE_HPP
#include <boost/thread/thread.hpp>
#include "cppa/invoke_rules.hpp"
#include "cppa/untyped_tuple.hpp"
......@@ -14,6 +16,9 @@ namespace cppa { namespace detail {
// private part of the actor interface (callable only from this_actor())
struct actor_private : public actor_public
{
boost::thread* m_thread;
inline actor_private() : m_thread(0) { }
virtual ~actor_private();
virtual const message& receive() = 0;
virtual const message& last_dequeued() const = 0;
virtual void receive(invoke_rules&) = 0;
......
......@@ -26,24 +26,32 @@ class intrusive_ptr : detail::comparable<intrusive_ptr<T>, T*>,
intrusive_ptr() : m_ptr(0) { }
template<typename Y>
intrusive_ptr(Y* raw_ptr) { set_ptr(raw_ptr); }
intrusive_ptr(T* raw_ptr) { set_ptr(raw_ptr); }
intrusive_ptr(intrusive_ptr&& other) : m_ptr(other.m_ptr)
intrusive_ptr(const intrusive_ptr& other)
{
other.m_ptr = 0;
set_ptr(other.m_ptr);
}
intrusive_ptr(const intrusive_ptr& other) { set_ptr(other.m_ptr); }
intrusive_ptr(intrusive_ptr&& other) : m_ptr(0)
{
swap(other);
}
template<typename Y>
intrusive_ptr(const intrusive_ptr<Y>& other)
{
static_assert(std::is_convertible<Y*, T*>::value,
"Y* is not assignable to T*");
set_ptr(const_cast<Y*>(other.get()));
}
template<typename Y>
intrusive_ptr(intrusive_ptr<Y>&& other) : m_ptr(0)
{
swap(other);
}
~intrusive_ptr()
{
if (m_ptr && !m_ptr->deref())
......@@ -77,11 +85,8 @@ class intrusive_ptr : detail::comparable<intrusive_ptr<T>, T*>,
intrusive_ptr& operator=(const intrusive_ptr& other)
{
if (get() != other.get())
{
intrusive_ptr tmp(other);
swap(tmp);
}
intrusive_ptr tmp(other);
swap(tmp);
return *this;
}
......@@ -100,6 +105,16 @@ class intrusive_ptr : detail::comparable<intrusive_ptr<T>, T*>,
return *this;
}
template<typename Y>
intrusive_ptr& operator=(intrusive_ptr<Y>&& other)
{
static_assert(std::is_convertible<Y*, T*>::value,
"Y* is not assignable to T*");
m_ptr = other.m_ptr;
other.m_ptr = 0;
return *this;
}
T* operator->() { return m_ptr; }
T& operator*() { return *m_ptr; }
......
......@@ -8,6 +8,7 @@
#include "cppa/tuple_view.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/util/compare_tuples.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/is_comparable.hpp"
#include "cppa/util/utype_iterator.hpp"
......@@ -51,7 +52,8 @@ bool match(const untyped_tuple& what, const ValuesTuple& vals,
{
std::vector<std::size_t> tmp(mappings);
view_type view(what.vals(), std::move(tmp));
return view == vals;
return compare_first_elements(view, vals);
// return view == vals;
}
return false;
}
......
......@@ -33,6 +33,8 @@ class message_receiver :
{
}
virtual ~message_receiver();
message_receiver() = default;
message_receiver(message_receiver&&) = default;
......
......@@ -5,6 +5,7 @@
#include "cppa/invoke_rules.hpp"
#include "cppa/untyped_tuple.hpp"
#include "cppa/util/eval_first_n.hpp"
#include "cppa/util/filter_type_list.hpp"
#include "cppa/detail/ref_counted_impl.hpp"
......@@ -36,6 +37,12 @@ struct invoke_rule_builder
template<typename Arg0, typename... Args>
invoke_rule_builder(const Arg0& arg0, const Args&... args)
{
typedef util::type_list<Arg0, Args...> arg_types;
static_assert(arg_types::type_list_size
<= filtered_types::type_list_size,
"too much arguments");
class helper_impl : public irb_helper
{
......@@ -44,7 +51,9 @@ struct invoke_rule_builder
public:
helper_impl(const Arg0& arg0, const Args&... args)
: m_values(arg0, args...) { }
: m_values(arg0, args...)
{
}
virtual bool value_cmp(const untyped_tuple& t,
std::vector<std::size_t>& v) const
......@@ -56,10 +65,11 @@ struct invoke_rule_builder
m_helper = new helper_impl(arg0, args...);
static_assert(util::eval_type_lists<filtered_types,
util::type_list<Arg0, Args...>,
util::is_comparable>::value,
"Wrong argument types");
static_assert(util::eval_first_n<arg_types::type_list_size,
filtered_types,
arg_types,
util::is_comparable>::value,
"wrong argument types (not comparable)");
}
typedef typename tuple_view_type_from_type_list<filtered_types>::type
......
......@@ -9,9 +9,11 @@
#include "cppa/util/detach.hpp"
#include "cppa/util/disjunction.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/eval_first_n.hpp"
#include "cppa/util/eval_type_list.hpp"
#include "cppa/util/eval_type_lists.hpp"
#include "cppa/util/filter_type_list.hpp"
#include "cppa/util/first_n.hpp"
#include "cppa/util/has_copy_member_fun.hpp"
#include "cppa/util/is_comparable.hpp"
#include "cppa/util/is_copyable.hpp"
......
......@@ -3,6 +3,7 @@
#include "cppa/get.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/eval_first_n.hpp"
#include "cppa/util/is_comparable.hpp"
#include "cppa/util/eval_type_lists.hpp"
......@@ -34,6 +35,25 @@ struct cmp_helper<0, LhsTuple, RhsTuple>
}
};
template<bool ALessB, std::size_t A, std::size_t B>
struct min_impl
{
static const std::size_t value = A;
};
template<std::size_t A, std::size_t B>
struct min_impl<false, A, B>
{
static const std::size_t value = B;
};
template<std::size_t A, std::size_t B>
struct min_
{
static const std::size_t value = min_impl<(A < B), A, B>::value;
};
} } // namespace cppa::detail
namespace cppa { namespace util {
......@@ -55,6 +75,29 @@ bool compare_tuples(const LhsTuple<LhsTypes...>& lhs,
RhsTuple<RhsTypes...>>::cmp(lhs, rhs);
}
template<template<typename...> class LhsTuple, typename... LhsTypes,
template<typename...> class RhsTuple, typename... RhsTypes>
bool compare_first_elements(const LhsTuple<LhsTypes...>& lhs,
const RhsTuple<RhsTypes...>& rhs)
{
typedef util::type_list<LhsTypes...> lhs_types;
typedef util::type_list<RhsTypes...> rhs_types;
static_assert(util::eval_first_n<detail::min_<lhs_types::type_list_size,
rhs_types::type_list_size>
::value,
lhs_types,
rhs_types,
util::is_comparable>::value,
"types of lhs are not comparable to the types of rhs");
return detail::cmp_helper<(detail::min_<lhs_types::type_list_size,
rhs_types::type_list_size>
::value - 1),
LhsTuple<LhsTypes...>,
RhsTuple<RhsTypes...>>::cmp(lhs, rhs);
}
} } // namespace cppa::util
#endif // COMPARE_TUPLES_HPP
......@@ -4,7 +4,6 @@
#include <type_traits>
#include "cppa/util/type_list.hpp"
#include "cppa/util/concat_type_lists.hpp"
namespace cppa { namespace util {
......@@ -18,6 +17,7 @@ struct eval_type_lists
typedef typename ListA::head_type head_type_a;
typedef typename ListA::tail_type tail_type_a;
typedef typename ListB::head_type head_type_b;
typedef typename ListB::tail_type tail_type_b;
......
......@@ -55,6 +55,7 @@ HEADERS = cppa/actor.hpp \
cppa/util/void_type.hpp
SOURCES = src/actor.cpp \
src/actor_private.cpp \
src/decorated_tuple.cpp \
src/deserializer.cpp \
src/message_receiver.cpp \
......
#include "cppa/actor.hpp"
#include <boost/thread.hpp>
namespace cppa {
actor& actor::operator=(const actor& other)
......@@ -14,4 +16,23 @@ actor& actor::operator=(actor&& other)
return *this;
}
actor::~actor()
{
/*
if (m_channel && m_channel->unique())
{
detail::actor_private* ap = dynamic_cast<detail::actor_private*>(m_channel.get());
if (ap && ap->m_thread)
{
if (boost::this_thread::get_id() != ap->m_thread->get_id())
{
ap->m_thread->join();
delete ap->m_thread;
ap->m_thread = 0;
}
}
}
*/
}
} // namespace cppa
......@@ -22,4 +22,8 @@ message_receiver::operator=(intrusive_ptr<detail::channel>&& ch_ptr)
return *this;
}
message_receiver::~message_receiver()
{
}
} // namespace cppa
......@@ -134,7 +134,8 @@ namespace cppa { namespace detail {
actor spawn_impl(behavior* actor_behavior)
{
actor_ptr aptr(new actor_impl(actor_behavior));
boost::thread(aptr).detach();
aptr.m_impl->m_thread = new boost::thread(aptr);
// boost::thread(aptr).detach();
return actor(aptr.m_impl);
// return actor(std::move(aptr.m_impl));
}
......
......@@ -16,6 +16,8 @@ std::size_t test__a_matches_b()
typedef type_list<int, int, std::string> int_int_string;
typedef type_list<int, int, const std::string&> int_int_const_string_ref;
typedef typename first_n<2, int_float_int>::type int_float;
typedef type_list_apply<int_int_const_string_ref,
remove_const_reference>::type
int_int_string2;
......@@ -29,8 +31,10 @@ std::size_t test__a_matches_b()
CPPA_CHECK((a_matches_b<int_int_string, int_int_string2>::value));
CPPA_CHECK(!(a_matches_b<int_int_string, int_int_const_string_ref>::value));
CPPA_CHECK_EQUAL((a_matches_b<type_list<float>,
type_list<int, float, int>>::value), false);
CPPA_CHECK(!(a_matches_b<type_list<float>,
type_list<int, float, int>>::value));
CPPA_CHECK((std::is_same<util::type_list<int, float>, int_float>::value));
CPPA_CHECK((a_matches_b<type_list<any_type*, float>,
type_list<int, float, int>>::value) == false);
......
......@@ -20,127 +20,104 @@ using std::endl;
using namespace cppa;
class group : public detail::channel
{
boost::mutex m_mtx;
std::list<actor> m_subscribers;
namespace {
public:
struct group : detail::channel
{
struct subscription
// NOT thread safe
class subscription : public detail::ref_counted_impl<std::size_t>
{
actor m_self;
intrusive_ptr<group> m_group;
public:
subscription() = delete;
subscription(const subscription&) = delete;
subscription& operator=(const subscription&) = delete;
subscription(const actor& s, const intrusive_ptr<group>& g)
: m_self(s), m_group(g)
{
}
~subscription()
{
m_group->unsubscribe(m_self);
}
};
subscription subscribe(const actor& who)
{
boost::mutex::scoped_lock guard(m_mtx);
m_subscribers.push_back(who);
return { who, this };
}
virtual intrusive_ptr<subscription> subscribe(const actor& who) = 0;
void unsubscribe(const actor& who)
{
boost::mutex::scoped_lock guard(m_mtx);
auto i = std::find(m_subscribers.begin(), m_subscribers.end(), who);
if (i != m_subscribers.end())
{
m_subscribers.erase(i);
}
}
void enqueue_msg(const message& msg)
{
boost::mutex::scoped_lock guard(m_mtx);
for (auto i = m_subscribers.begin(); i != m_subscribers.end(); ++i)
{
i->enqueue_msg(msg);
}
}
virtual void unsubscribe(const actor& who) = 0;
template<typename... Args>
void send(const Args&... args)
{
message msg(this_actor(), this, args...);
enqueue_msg(msg);
enqueue_msg(message(this_actor(), this, args...));
}
};
namespace {
class group_bucket
class local_group : public group
{
boost::mutex m_mtx;
std::map<std::string, intrusive_ptr<group>> m_groups;
std::list<actor> m_subscribers;
inline std::list<actor>::iterator find(const actor& what)
{
return std::find(m_subscribers.begin(), m_subscribers.end(), what);
}
public:
intrusive_ptr<group> get(const std::string& group_name)
virtual void enqueue_msg(const message& msg)
{
boost::mutex::scoped_lock guard(m_mtx);
intrusive_ptr<group>& result = m_groups[group_name];
if (!result)
for (auto i = m_subscribers.begin(); i != m_subscribers.end(); ++i)
{
result.reset(new group);
i->enqueue_msg(msg);
}
return result;
}
};
template<std::size_t NumBuckets>
class group_table
{
group_bucket m_buckets[NumBuckets];
group_bucket& bucket(const std::string& group_name)
virtual intrusive_ptr<group::subscription> subscribe(const actor& who)
{
unsigned int gn_hash = hash_of(group_name);
return m_buckets[gn_hash % NumBuckets];
boost::mutex::scoped_lock guard(m_mtx);
auto i = find(who);
if (i == m_subscribers.end())
{
m_subscribers.push_back(who);
return new group::subscription(who, this);
}
return new group::subscription(0, 0);
}
public:
intrusive_ptr<group> operator[](const std::string& group_name)
virtual void unsubscribe(const actor& who)
{
return bucket(group_name).get(group_name);
boost::mutex::scoped_lock guard(m_mtx);
auto i = find(who);
if (i != m_subscribers.end())
{
m_subscribers.erase(i);
}
}
};
group_table<100> m_groups;
} // namespace <anonymous>
namespace {
//local_group* m_local_group = new local_group;
intrusive_ptr<group> local_group = new group;
local_group m_local_group;
}
struct
group& local(const char*)
{
intrusive_ptr<group> operator/(const std::string& /*group_name*/)
{
return local_group;
// return m_groups[group_name];
}
return m_local_group;
}
local;
} // namespace <anonymous>
struct storage
{
......@@ -168,6 +145,7 @@ struct storage
};
/*
template<typename... Args>
void send(std::list<actor>& actors, const Args&... args)
{
......@@ -176,21 +154,13 @@ void send(std::list<actor>& actors, const Args&... args)
i->send(args...);
}
}
*/
void foo_actor()
{
// auto x = (local/"foobar")->subscribe(this_actor());
auto rules = (
on<int, int, int>() >> []() {
reply(23.f);
},
on<int>() >> [](int i) {
reply(i);
}
);
receive(rules);
receive(rules);
// reply(1);
receive(on<int>() >> [](int i) {
reply(i);
});
}
std::size_t test__local_group()
......@@ -198,37 +168,15 @@ std::size_t test__local_group()
CPPA_TEST(test__local_group);
/*
storage st;
st.get<int>("foobaz") = 42;
CPPA_CHECK_EQUAL(st.get<int>("foobaz"), 42);
st.get<std::string>("_s") = "Hello World!";
CPPA_CHECK_EQUAL(st.get<std::string>("_s"), "Hello World!");
*/
// auto g = local/"foobar";
std::list<actor> m_slaves;
for (int i = 0; i < 5; ++i)
{
m_slaves.push_back(spawn(foo_actor));
}
send(m_slaves, 1, 2, 3);
send(m_slaves, 1);
std::list<intrusive_ptr<group::subscription>> m_subscriptions;
group& lg = local("foobar");
for (int i = 0; i < 5; ++i)
{
receive(on<float>() >> []() { });
m_subscriptions.push_back(lg.subscribe(spawn(foo_actor)));
}
// g->send(1);
lg.send(1);
int result = 0;
......
......@@ -73,6 +73,18 @@ std::size_t test__tuple()
CPPA_CHECK(tv2.get<1>() == "Hello World");
{
tuple<int> t1_sub1(42);
tuple<int, float> t1_sub2(42, .2f);
tuple<int, float, int> t1_sub3(42, .2f, 2);
CPPA_CHECK((util::compare_first_elements(t1, t1_sub1)));
CPPA_CHECK((match<int, any_type*>(t1, t1_sub1)));
CPPA_CHECK((util::compare_first_elements(t1, t1_sub2)));
CPPA_CHECK((match<int, any_type*, float, any_type*>(t1, t1_sub2)));
CPPA_CHECK((util::compare_first_elements(t1, t1_sub3)));
CPPA_CHECK((match<int, float, int, any_type>(t1, t1_sub3)));
}
{
std::vector<std::size_t> tv3_mappings;
match<any_type*, int, std::string>(t1, tv3_mappings);
......
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