Commit 6660002d authored by neverlord's avatar neverlord

maintenance

parent 00f15911
......@@ -68,7 +68,8 @@ struct fsm_receiver : fsm_actor<fsm_receiver>
void receiver(int64_t max)
{
int64_t value;
receive_while([&]() { return value < max; })
receive_while(gref(value) < max)
//receive_while([&]() { return value < max; })
(
on(atom("msg")) >> [&]()
{
......
......@@ -362,16 +362,23 @@ template<class Pattern, typename Fun>
std::unique_ptr<invokable> get_invokable_impl(Fun&& fun,
std::unique_ptr<value_matcher>&& vm)
{
typedef typename select_invokable_impl<Fun, Pattern>::type result;
return std::unique_ptr<invokable>{
new result(std::forward<Fun>(fun), std::move(vm))};
typedef std::unique_ptr<invokable> result;
if (vm)
{
typedef typename select_invokable_impl<Fun, Pattern>::type impl1;
return result{new impl1{std::forward<Fun>(fun), std::move(vm)}};
}
typedef typename Pattern::types pattern_types;
typedef typename select_invokable_impl<Fun, pattern_types>::type impl2;
return result{new impl2{std::forward<Fun>(fun)}};
}
template<class Pattern, typename Fun>
std::unique_ptr<invokable> get_invokable_impl(Fun&& fun)
{
typedef typename select_invokable_impl<Fun, typename Pattern::types>::type result;
return std::unique_ptr<invokable>{new result(std::forward<Fun>(fun))};
typedef typename Pattern::types pattern_types;
typedef typename select_invokable_impl<Fun, pattern_types>::type impl;
return std::unique_ptr<invokable>{new impl(std::forward<Fun>(fun))};
}
} } // namespace cppa::detail
......
......@@ -104,6 +104,8 @@ struct tdata<>
throw std::out_of_range("");
}
inline void set() { }
inline bool operator==(tdata const&) const { return true; }
};
......@@ -160,6 +162,13 @@ struct tdata<Head, Tail...> : tdata<Tail...>
return *this;
}
template<typename Arg0, typename... Args>
inline void set(Arg0&& arg0, Args&&... args)
{
head = std::forward<Arg0>(arg0);
super::set(std::forward<Args>(args)...);
}
// upcast
inline tdata<Tail...>& tail() { return *this; }
inline tdata<Tail...> const& tail() const { return *this; }
......@@ -215,6 +224,13 @@ struct tdata<option<Head>, Tail...> : tdata<Tail...>
{
}
template<typename Arg0, typename... Args>
inline void set(Arg0&& arg0, Args&&... args)
{
head = std::forward<Arg0>(arg0);
super::set(std::forward<Args>(args)...);
}
template<typename... Y>
tdata& operator=(tdata<Y...> const& other)
{
......
......@@ -38,6 +38,8 @@
#include <type_traits>
#include "cppa/util/at.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/detail/tdata.hpp"
namespace cppa {
......@@ -91,6 +93,10 @@ struct guard_expr
guard_expr(guard_expr const&) = default;
guard_expr(guard_expr&& other) : m_args(std::move(other.m_args)) { }
template<typename... Args>
bool operator()(Args const&... args) const;
};
#define CPPA_FORALL_OPS(SubMacro) \
......@@ -295,6 +301,39 @@ struct guard_placeholder
};
template<typename T>
struct ge_reference_wrapper
{
T const* value;
ge_reference_wrapper(T&&) = delete;
ge_reference_wrapper(T const& val_ref) : value(&val_ref) { }
ge_reference_wrapper(ge_reference_wrapper const&) = default;
ge_reference_wrapper& operator=(ge_reference_wrapper const&) = default;
T const& get() const { return *value; }
operator T const& () const { return *value; }
};
// support use of gref(BooleanVariable) as receive loop 'guard'
template<>
struct ge_reference_wrapper<bool>
{
bool const* value;
ge_reference_wrapper(bool&&) = delete;
ge_reference_wrapper(bool const& val_ref) : value(&val_ref) { }
ge_reference_wrapper(ge_reference_wrapper const&) = default;
ge_reference_wrapper& operator=(ge_reference_wrapper const&) = default;
bool get() const { return *value; }
operator bool () const { return *value; }
bool operator()() const { return *value; }
};
/**
* @brief Create a reference wrapper similar to std::reference_wrapper<const T>
* that could be used in guard expressions or to enforce lazy evaluation.
*/
template<typename T>
ge_reference_wrapper<T> gref(T const& value) { return {value}; }
// result type computation
......@@ -304,6 +343,12 @@ struct ge_unbound
typedef T type;
};
template<typename T, class Tuple>
struct ge_unbound<ge_reference_wrapper<T>, Tuple>
{
typedef T type;
};
// unbound type of placeholder
template<int X, typename... Ts>
struct ge_unbound<guard_placeholder<X>, detail::tdata<Ts...> >
......@@ -315,51 +360,49 @@ struct ge_unbound<guard_placeholder<X>, detail::tdata<Ts...> >
// operators, operators, operators
#define CPPA_GUARD_PLACEHOLDER_OPERATOR(EnumValue, Operator) \
template<int Pos1, int Pos2> \
guard_expr< EnumValue , guard_placeholder<Pos1>, guard_placeholder<Pos2>> \
operator Operator (guard_placeholder<Pos1> p1, guard_placeholder<Pos2> p2) \
{ return {p1, p2}; } \
template<int Pos, typename T> \
guard_expr< EnumValue , guard_placeholder<Pos>, \
typename detail::strip_and_convert<T>::type > \
operator Operator (guard_placeholder<Pos> gp, T value) \
{ return {std::move(gp), std::move(value)}; } \
template<typename T, int Pos> \
guard_expr< EnumValue , \
typename detail::strip_and_convert<T>::type, \
guard_placeholder<Pos> > \
operator Operator (T value, guard_placeholder<Pos> gp) \
{ return {std::move(value), std::move(gp)}; }
CPPA_FORALL_OPS(CPPA_GUARD_PLACEHOLDER_OPERATOR)
#define CPPA_GUARD_EXPR_OPERATOR(EnumValue, Operator) \
template<operator_id OP, typename F, typename S, typename T> \
guard_expr< EnumValue , guard_expr<OP, F, S>, \
typename detail::strip_and_convert<T>::type> \
operator Operator (guard_expr<OP, F, S> lhs, T rhs) \
{ return {lhs, rhs}; } \
template<typename T, operator_id OP, typename F, typename S> \
guard_expr< EnumValue , typename detail::strip_and_convert<T>::type, \
guard_expr<OP, F, S>> \
operator Operator (T lhs, guard_expr<OP, F, S> rhs) \
{ return {lhs, rhs}; } \
template<operator_id OP, typename F, typename S, int X> \
guard_expr< EnumValue , guard_expr<OP, F, S>, guard_placeholder<X> > \
operator Operator (guard_expr<OP, F, S> lhs, guard_placeholder<X> rhs) \
{ return {lhs, rhs}; } \
template<int X, operator_id OP, typename F, typename S> \
guard_expr< EnumValue , guard_placeholder<X>, guard_expr<OP, F, S>> \
operator Operator (guard_placeholder<X> lhs, guard_expr<OP, F, S> rhs) \
{ return {lhs, rhs}; } \
template<operator_id OP1, typename F1, typename S1, \
operator_id OP2, typename F2, typename S2> \
guard_expr< EnumValue , guard_expr<OP1, F1, S1>, guard_expr<OP2, F2, S2>> \
operator Operator (guard_expr<OP1,F1,S1> lhs, guard_expr<OP2,F2,S2> rhs) \
{ return {lhs, rhs}; }
CPPA_FORALL_OPS(CPPA_GUARD_EXPR_OPERATOR)
template<typename T>
struct is_ge_type
{
static constexpr bool value = false;
};
template<int X>
struct is_ge_type<guard_placeholder<X> >
{
static constexpr bool value = true;
};
template<typename T>
struct is_ge_type<ge_reference_wrapper<T> >
{
static constexpr bool value = true;
};
template<operator_id OP, typename First, typename Second>
struct is_ge_type<guard_expr<OP, First, Second> >
{
static constexpr bool value = true;
};
template<operator_id OP, typename T1, typename T2>
guard_expr<OP, typename detail::strip_and_convert<T1>::type,
typename detail::strip_and_convert<T2>::type>
ge_concatenate(T1 first, T2 second,
typename util::enable_if_c<
is_ge_type<T1>::value || is_ge_type<T2>::value
>::type* = 0)
{
return {first, second};
}
#define CPPA_GE_OPERATOR(EnumValue, Operator) \
template<typename T1, typename T2> \
auto operator Operator (T1 v1, T2 v2) \
-> decltype(ge_concatenate< EnumValue >(v1, v2)) { \
return ge_concatenate< EnumValue >(v1, v2); \
}
CPPA_FORALL_OPS(CPPA_GE_OPERATOR)
template<operator_id OP>
struct ge_eval_op;
......@@ -430,25 +473,6 @@ struct ge_result_<guard_expr<exec_fun3_op, First, Second>, Tuple>
)) type;
};
/*
#define CPPA_G_RESULT_TYPE_SPECIALIZATION(EnumValue, Operator) \
template<typename First, typename Second, class Tuple> \
struct ge_result_< guard_expr< EnumValue , First, Second>, Tuple> \
{ \
typedef typename ge_result_<First, Tuple>::type lhs_type; \
typedef typename ge_result_<Second, Tuple>::type rhs_type; \
typedef decltype(*static_cast<lhs_type const*>(nullptr) \
Operator \
*static_cast<rhs_type const*>(nullptr)) type; \
};
CPPA_G_RESULT_TYPE_SPECIALIZATION(addition_op, +)
CPPA_G_RESULT_TYPE_SPECIALIZATION(subtraction_op, -)
CPPA_G_RESULT_TYPE_SPECIALIZATION(multiplication_op, *)
CPPA_G_RESULT_TYPE_SPECIALIZATION(division_op, /)
CPPA_G_RESULT_TYPE_SPECIALIZATION(modulo_op, %)
*/
template<operator_id OP, typename First, typename Second, class Tuple>
struct ge_result
{
......@@ -483,6 +507,12 @@ inline T const& ge_resolve(Tuple const&, T const& value)
return value;
}
template<class Tuple, typename T>
inline T const& ge_resolve(Tuple const&, ge_reference_wrapper<T> const& value)
{
return value.get();
}
template<class Tuple, int X>
inline auto ge_resolve(Tuple const& tup, guard_placeholder<X>)
-> decltype(*get<X>(tup))
......@@ -635,6 +665,15 @@ ge_invoke_any(guard_expr<OP, First, Second> const& ge,
return util::unchecked_apply_tuple<result_type>(f, *x);
}
template<operator_id OP, typename First, typename Second>
template<typename... Args>
bool guard_expr<OP, First, Second>::operator()(Args const&... args) const
{
static_assert(std::is_same<decltype(ge_invoke(*this, args...)), bool>::value,
"guard expression does not return a boolean");
return ge_invoke(*this, args...);
}
// finally ...
namespace placeholders { namespace {
......
......@@ -126,27 +126,59 @@ class rvalue_builder
public:
template<operator_id OP, typename F, typename S>
rvalue_builder& when(guard_expr<OP, F, S> ge)
//template<operator_id OP, typename F, typename S>
//rvalue_builder& when(guard_expr<OP, F, S> ge)
template<typename Fun>
rvalue_builder& when(Fun&& fun)
{
typedef guard_expr<OP, F, S> gtype;
struct vm_impl : value_matcher
//TODO: static_assert
typedef typename util::rm_ref<Fun>::type fun_type;
if (m_vm)
{
struct impl1 : value_matcher
{
vm_ptr m_ptr;
gtype m_ge;
vm_impl(vm_ptr&& ptr, gtype&& g) : m_ptr(std::move(ptr)), m_ge(std::move(g)) { }
fun_type m_fun;
impl1(vm_ptr&& ptr, Fun&& f)
: m_ptr(std::move(ptr)), m_fun(std::forward<Fun>(f))
{
}
bool operator()(any_tuple const& tup) const
{
static_assert(std::is_same<decltype(ge_invoke_any<types>(m_ge, tup)), bool>::value,
"guard expression does not return a boolean");
if ((*m_ptr)(tup))
{
return ge_invoke_any<types>(m_ge, tup);
auto ttup = tuple_cast(tup, types{});
if (ttup)
{
return util::unchecked_apply_tuple<bool>(m_fun,
*ttup);
}
}
return false;
}
};
m_vm.reset(new impl1{std::move(m_vm), std::forward<Fun>(fun)});
}
else
{
struct impl2 : value_matcher
{
fun_type m_fun;
impl2(Fun&& f) : m_fun(std::forward<Fun>(f))
{
}
bool operator()(any_tuple const& tup) const
{
auto ttup = tuple_cast(tup, types{});
if (ttup)
{
return util::unchecked_apply_tuple<bool>(m_fun, *ttup);
}
return false;
}
};
m_vm.reset(new vm_impl(std::move(m_vm), std::move(ge)));
m_vm.reset(new impl2{std::forward<Fun>(fun)});
}
return *this;
}
......
......@@ -313,11 +313,14 @@ class pattern
m_vm.reset(new value_matcher_impl<wildcard_pos, types, util::type_list<Args...> >{data});
}
pattern(std::unique_ptr<value_matcher>&& vm) : m_vm(std::move(vm)) { }
pattern(std::unique_ptr<value_matcher>&& vm) : m_vm(std::move(vm))
{
if (!m_vm) m_vm.reset(new dummy_matcher);
}
static inline value_matcher* get_value_matcher()
{
return new dummy_matcher;
return nullptr;
}
template<typename Arg0, typename... Args>
......
......@@ -97,6 +97,8 @@ struct get_callable_trait
std::is_member_function_pointer<fun_type>::value,
fun_type>::type
type;
typedef typename type::result_type result_type;
typedef typename type::arg_types arg_types;
};
template<typename C>
......
......@@ -58,7 +58,7 @@ int main(int, char**)
// receive two messages
int i = 0;
receive_while([&]() { return ++i <= 2; })
receive_for(i, 2)
(
// note: we sent a foo_pair2, but match on foo_pair
// that's safe because both are aliases for std::pair<int,int>
......
......@@ -116,7 +116,7 @@ int main(int, char**)
// receive two messages
int i = 0;
receive_while([&]() { return ++i <= 2; })
receive_for(i, 2)
(
on<bar>() >> [](bar const& val)
{
......
......@@ -200,7 +200,7 @@ int main()
// receive both messages
int i = 0;
receive_while([&]() { return ++i <= 2; })
receive_for(i, 2)
(
// ... and receive it
on<tree>() >> [](const tree& tmsg)
......
......@@ -33,7 +33,8 @@ void math_fun()
done = true;
}
)
.until([&]() { return done; });
.until(gref(done));
//.until([&]() { return done; });
}
struct math_actor : event_based_actor
......
......@@ -41,7 +41,6 @@ size_t test__local_group()
}
send(foo_group, 2);
int result = 0;
//receive_until([&result]() { return result == 10; })
do_receive
(
on<int>() >> [&](int value)
......@@ -55,7 +54,7 @@ size_t test__local_group()
result = 10;
}
)
.until([&result]() { return result == 10; });
.until(gref(result) == 10);
await_all_others_done();
return CPPA_TEST_RESULT;
}
......@@ -48,9 +48,10 @@ size_t test__match()
auto expr2 = _x1 + _x2 < _x3;
auto expr3 = _x1 % _x2 == 0;
CPPA_CHECK_EQUAL(5, (ge_invoke(expr1, 2, 3)));
CPPA_CHECK(ge_invoke(expr2, 1, 2, 4));
//CPPA_CHECK(ge_invoke(expr2, 1, 2, 4));
CPPA_CHECK(expr2(1, 2, 4));
CPPA_CHECK_EQUAL("12", (ge_invoke(expr1, std::string{"1"}, std::string{"2"})));
CPPA_CHECK((ge_invoke(expr3, 100, 2)));
CPPA_CHECK(expr3(100, 2));
auto expr4 = _x1 == "-h" || _x1 == "--help";
CPPA_CHECK(ge_invoke(expr4, string("-h")));
......
......@@ -212,7 +212,7 @@ class testee_actor : public scheduled_actor
reply("wait4string");
}
)
.until([&]() { return string_received; });
.until(gref(string_received));
}
void wait4float()
......@@ -230,7 +230,7 @@ class testee_actor : public scheduled_actor
reply("wait4float");
}
)
.until([&]() { return float_received; });
.until(gref(float_received));
}
public:
......@@ -281,11 +281,11 @@ void testee3(actor_ptr parent)
// test a future_send / delayed_reply based loop
future_send(self, std::chrono::milliseconds(50), atom("Poll"));
int polls = 0;
receive_while([&polls]() { return ++polls <= 5; })
receive_for(polls, 5)
(
on(atom("Poll")) >> [&]()
{
if (polls < 5)
if (polls < 4)
{
delayed_reply(std::chrono::milliseconds(50), atom("Poll"));
}
......@@ -386,7 +386,7 @@ size_t test__spawn()
int flags = 0;
future_send(self, std::chrono::seconds(1), atom("FooBar"));
// wait for :Down and :Exit messages of pong
receive_while([&i]() { return ++i <= 3; })
receive_for(i, 3)
(
on<atom(":Exit"), std::uint32_t>() >> [&](std::uint32_t reason)
{
......@@ -424,26 +424,6 @@ size_t test__spawn()
// verify pong messages
CPPA_CHECK_EQUAL(pongs(), 5);
/*
spawn(testee3, self);
i = 0;
// testee3 sends 5 { "Push", int } messages in a 50 milliseconds interval;
// allow for a maximum error of 5ms
receive_while([&i]() { return ++i <= 5; })
(
on<atom("Push"), int>() >> [&](int val)
{
CPPA_CHECK_EQUAL(i, val);
//cout << "{ Push, " << val << " } ..." << endl;
},
after(std::chrono::milliseconds(55)) >> [&]()
{
cout << "Push " << i
<< " was delayed more than 55 milliseconds" << endl;
CPPA_CHECK(false);
}
);
*/
await_all_others_done();
return CPPA_TEST_RESULT;
}
......@@ -25,9 +25,65 @@ using std::endl;
using namespace cppa;
template<class Expr, class Guard, typename Result, typename... Args>
class tpartial_function
{
public:
tpartial_function(Guard&& g, Expr&& e)
: m_guard(std::move(g)), m_expr(std::move(e))
{
}
tpartial_function(tpartial_function&&) = default;
tpartial_function(tpartial_function const&) = default;
bool defined_at(Args const&... args)
{
return m_guard(args...);
}
Result operator()(Args const&... args)
{
return m_expr(args...);
}
private:
detail::tdata<Args...> m_args;
Guard m_guard;
Expr m_expr;
};
template<class Expr, class Guard, typename Result, class ArgTypes>
struct tpf_;
template<class Expr, class Guard, typename Result, typename... Ts>
struct tpf_<Expr, Guard, Result, util::type_list<Ts...> >
{
typedef tpartial_function<Expr, Guard, Result, Ts...> type;
};
template<class Expr, class Guard>
typename tpf_<Expr, Guard,
typename util::get_callable_trait<Expr>::result_type,
typename util::get_callable_trait<Expr>::arg_types
>::type
tfun(Expr e, Guard g)
{
return {std::move(g), std::move(e)};
}
size_t test__tuple()
{
CPPA_TEST(test__tuple);
using namespace cppa::placeholders;
// check type correctness of make_cow_tuple()
auto t0 = make_cow_tuple("1", 2);
CPPA_CHECK((std::is_same<decltype(t0), cppa::cow_tuple<std::string, int>>::value));
......
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