Commit eb1fb939 authored by Dominik Charousset's avatar Dominik Charousset

fixed partial_function args in match_expr_concat

parent c25d2453
...@@ -112,9 +112,6 @@ class behavior { ...@@ -112,9 +112,6 @@ class behavior {
*/ */
behavior add_continuation(continuation_fun fun); behavior add_continuation(continuation_fun fun);
//template<typename F>
//inline behavior add_continuation(F fun);
private: private:
impl_ptr m_impl; impl_ptr m_impl;
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
namespace cppa { namespace cppa {
class partial_function;
typedef optional<any_tuple> bhvr_invoke_result; typedef optional<any_tuple> bhvr_invoke_result;
} // namespace cppa } // namespace cppa
...@@ -224,6 +225,11 @@ default_behavior_impl<dummy_match_expr, F>* new_default_behavior(util::duration ...@@ -224,6 +225,11 @@ default_behavior_impl<dummy_match_expr, F>* new_default_behavior(util::duration
typedef intrusive_ptr<behavior_impl> behavior_impl_ptr; typedef intrusive_ptr<behavior_impl> behavior_impl_ptr;
// implemented in partial_function.cpp
behavior_impl_ptr combine(behavior_impl_ptr, const partial_function&);
behavior_impl_ptr combine(const partial_function&, behavior_impl_ptr);
behavior_impl_ptr extract(const partial_function&);
} } // namespace cppa::detail } } // namespace cppa::detail
#endif // BEHAVIOR_IMPL_HPP #endif // BEHAVIOR_IMPL_HPP
...@@ -108,7 +108,7 @@ inline void assert_types() { ...@@ -108,7 +108,7 @@ inline void assert_types() {
template<typename T> template<typename T>
struct lifted_result_type { struct lifted_result_type {
typedef util::type_list<T> type; typedef util::type_list<typename detail::implicit_conversions<T>::type> type;
}; };
template<typename... Ts> template<typename... Ts>
......
...@@ -520,8 +520,8 @@ Result unroll_expr(PPFPs& fs, ...@@ -520,8 +520,8 @@ Result unroll_expr(PPFPs& fs,
} }
// PPFP = projection_partial_function_pair // PPFP = projection_partial_function_pair
template<class PPFPs, class Tuple> template<class PPFPs, class T>
inline bool can_unroll_expr(PPFPs&, minus1l, const std::type_info&, const Tuple&) { inline bool can_unroll_expr(PPFPs&, minus1l, const std::type_info&, const T&) {
return false; return false;
} }
...@@ -906,21 +906,40 @@ match_expr_collect(const T& arg, const Ts&... args) { ...@@ -906,21 +906,40 @@ match_expr_collect(const T& arg, const Ts&... args) {
namespace detail { namespace detail {
typedef std::true_type with_timeout; //typedef std::true_type with_timeout;
typedef std::false_type without_timeout; //typedef std::false_type without_timeout;
// with timeout
// end of recursion // end of recursion
template<class Data, class Token>
behavior_impl_ptr concat_rec(const Data& data, Token) {
typedef typename match_expr_from_type_list<Token>::type combined_type;
auto lvoid = [] { };
typedef default_behavior_impl<combined_type, decltype(lvoid)> impl_type;
return new impl_type(data, util::duration{}, lvoid);
}
// end of recursion with nothing but a partial function
inline behavior_impl_ptr concat_rec(const tdata<>&,
util::empty_type_list,
const partial_function& pfun) {
return extract(pfun);
}
// end of recursion with timeout
template<class Data, class Token, typename F> template<class Data, class Token, typename F>
behavior_impl* concat_rec(const Data& data, Token, const timeout_definition<F>& arg) { behavior_impl_ptr concat_rec(const Data& data,
Token,
const timeout_definition<F>& arg) {
typedef typename match_expr_from_type_list<Token>::type combined_type; typedef typename match_expr_from_type_list<Token>::type combined_type;
return new default_behavior_impl<combined_type, F>{data, arg}; return new default_behavior_impl<combined_type, F>{data, arg};
} }
// recursive concatenation function // recursive concatenation function
template<class Data, class Token, typename T, typename... Ts> template<class Data, class Token, typename T, typename... Ts>
behavior_impl* concat_rec(const Data& data, Token, const T& arg, const Ts&... args) { behavior_impl_ptr concat_rec(const Data& data,
Token,
const T& arg,
const Ts&... args) {
typedef typename util::tl_concat< typedef typename util::tl_concat<
Token, Token,
typename T::cases_list typename T::cases_list
...@@ -938,57 +957,41 @@ behavior_impl* concat_rec(const Data& data, Token, const T& arg, const Ts&... ar ...@@ -938,57 +957,41 @@ behavior_impl* concat_rec(const Data& data, Token, const T& arg, const Ts&... ar
return concat_rec(next_data, next_token, args...); return concat_rec(next_data, next_token, args...);
} }
template<typename F> // handle partial functions at end of recursion
behavior_impl* concat_expr(with_timeout, const timeout_definition<F>& arg) { template<class Data, class Token>
typedef default_behavior_impl<dummy_match_expr, F> impl_type; behavior_impl_ptr concat_rec(const Data& data,
return new impl_type(dummy_match_expr{}, arg); Token token,
const partial_function& pfun) {
return combine(concat_rec(data, token), pfun);
} }
template<typename T, typename... Ts> // handle partial functions in between
behavior_impl* concat_expr(with_timeout, const T& arg, const Ts&... args) { template<class Data, class Token, typename T, typename... Ts>
typename tdata_from_type_list< behavior_impl_ptr concat_rec(const Data& data,
typename util::tl_map< Token token,
typename T::cases_list, const partial_function& pfun,
gref_wrapped const T& arg,
>::type const Ts&... args) {
>::type auto lhs = concat_rec(data, token);
wrapper; detail::tdata<> dummy;
detail::rebind_tdata(wrapper, arg.cases()); auto rhs = concat_rec(dummy, util::empty_type_list{}, arg, args...);
return concat_rec(wrapper, typename T::cases_list{}, args...); return combine(lhs, pfun)->or_else(rhs);
} }
// without timeout // handle partial functions at recursion start
template<typename T, typename... Ts> template<typename T, typename... Ts>
behavior_impl* concat_expr(without_timeout, const T& arg, const Ts&... args) { behavior_impl_ptr concat_rec(const tdata<>& data,
typename tdata_from_type_list< util::empty_type_list token,
typename util::tl_map< const partial_function& pfun,
typename util::tl_concat< const T& arg,
typename T::cases_list, const Ts&... args) {
typename Ts::cases_list... return combine(pfun, concat_rec(data, token, arg, args...));
>::type,
gref_wrapped
>::type
>::type
all_cases;
typedef typename match_expr_from_type_list<
typename util::tl_concat<
typename T::cases_list,
typename Ts::cases_list...
>::type
>::type
combined_type;
auto lvoid = [] { };
typedef default_behavior_impl<combined_type, decltype(lvoid)> impl_type;
rebind_tdata(all_cases, arg.cases(), args.cases()...);
return new impl_type(all_cases, util::duration{}, lvoid);
} }
template<typename T, typename... Ts> template<typename T, typename... Ts>
behavior_impl_ptr match_expr_concat(const T& arg, const Ts&... args) { behavior_impl_ptr match_expr_concat(const T& arg, const Ts&... args) {
std::integral_constant<bool, util::disjunction<T::may_have_timeout, Ts::may_have_timeout...>::value> token; detail::tdata<> dummy;
// use static call dispatch to select correct function return concat_rec(dummy, util::empty_type_list{}, arg, args...);
return concat_expr(token, arg, args...);
} }
} // namespace detail } // namespace detail
......
...@@ -62,13 +62,13 @@ class continue_helper { ...@@ -62,13 +62,13 @@ class continue_helper {
inline continue_helper(message_id mid) : m_mid(mid) { } inline continue_helper(message_id mid) : m_mid(mid) { }
template<typename F> template<typename F>
void continue_with(F fun) { continue_helper& continue_with(F fun) {
continue_with(behavior::continuation_fun{partial_function{ return continue_with(behavior::continuation_fun{partial_function{
on(any_vals, arg_match) >> fun on(any_vals, arg_match) >> fun
}}); }});
} }
inline void continue_with(behavior::continuation_fun fun) { inline continue_helper& continue_with(behavior::continuation_fun fun) {
auto ref_opt = self->bhvr_stack().sync_handler(m_mid); auto ref_opt = self->bhvr_stack().sync_handler(m_mid);
if (ref_opt) { if (ref_opt) {
auto& ref = *ref_opt; auto& ref = *ref_opt;
...@@ -77,6 +77,7 @@ class continue_helper { ...@@ -77,6 +77,7 @@ class continue_helper {
ref = cpy.add_continuation(std::move(fun)); ref = cpy.add_continuation(std::move(fun));
} }
else CPPA_LOG_ERROR(".continue_with: failed to add continuation"); else CPPA_LOG_ERROR(".continue_with: failed to add continuation");
return *this;
} }
inline message_id get_message_id() const { inline message_id get_message_id() const {
...@@ -196,9 +197,41 @@ class typed_continue_helper { ...@@ -196,9 +197,41 @@ class typed_continue_helper {
typed_continue_helper(continue_helper ch) : m_ch(std::move(ch)) { } typed_continue_helper(continue_helper ch) : m_ch(std::move(ch)) { }
template<typename F> template<typename F>
void continue_with(F fun) { typed_continue_helper<typename util::get_callable_trait<F>::result_type>
continue_with(F fun) {
detail::assert_types<result_types, F>(); detail::assert_types<result_types, F>();
m_ch.continue_with(std::move(fun)); m_ch.continue_with(std::move(fun));
return {m_ch};
}
inline message_id get_message_id() const {
return m_ch.get_message_id();
}
private:
continue_helper m_ch;
};
/*
template<>
class typed_continue_helper<void> {
public:
typedef int message_id_wrapper_tag;
typedef util::type_list<void> result_types;
typed_continue_helper(continue_helper ch) : m_ch(std::move(ch)) { }
template<typename F>
void continue_with(F fun) {
using arg_types = typename util::get_callable_trait<F>::arg_types;
static_assert(std::is_same<util::empty_type_list, arg_types>::value,
"functor takes too much arguments");
m_ch.continue_with(std::move(fun));
} }
inline message_id get_message_id() const { inline message_id get_message_id() const {
...@@ -210,6 +243,7 @@ class typed_continue_helper { ...@@ -210,6 +243,7 @@ class typed_continue_helper {
continue_helper m_ch; continue_helper m_ch;
}; };
*/
template<typename OutputList> template<typename OutputList>
class typed_message_future { class typed_message_future {
......
...@@ -65,7 +65,7 @@ class partial_function { ...@@ -65,7 +65,7 @@ class partial_function {
typedef intrusive_ptr<detail::behavior_impl> impl_ptr; typedef intrusive_ptr<detail::behavior_impl> impl_ptr;
inline auto as_behavior_impl() const -> const impl_ptr&; inline auto as_behavior_impl() const -> impl_ptr;
partial_function(impl_ptr ptr); partial_function(impl_ptr ptr);
...@@ -142,7 +142,7 @@ match_expr_convert(const T0& arg0, const T1& arg1, const Ts&... args) { ...@@ -142,7 +142,7 @@ match_expr_convert(const T0& arg0, const T1& arg1, const Ts&... args) {
template<typename... Cases> template<typename... Cases>
partial_function operator,(const match_expr<Cases...>& mexpr, partial_function operator,(const match_expr<Cases...>& mexpr,
const partial_function& pfun) { const partial_function& pfun) {
return mexpr.as_behavior_impl()->or_else(pfun.as_behavior_impl); return mexpr.as_behavior_impl()->or_else(pfun.as_behavior_impl());
} }
/****************************************************************************** /******************************************************************************
...@@ -177,7 +177,7 @@ partial_function::or_else(Ts&&... args) const { ...@@ -177,7 +177,7 @@ partial_function::or_else(Ts&&... args) const {
return m_impl->or_else(tmp.as_behavior_impl()); return m_impl->or_else(tmp.as_behavior_impl());
} }
inline auto partial_function::as_behavior_impl() const -> const impl_ptr& { inline auto partial_function::as_behavior_impl() const -> impl_ptr {
return m_impl; return m_impl;
} }
......
...@@ -40,3 +40,19 @@ partial_function::partial_function(impl_ptr ptr) : m_impl(std::move(ptr)) { } ...@@ -40,3 +40,19 @@ partial_function::partial_function(impl_ptr ptr) : m_impl(std::move(ptr)) { }
void detail::behavior_impl::handle_timeout() { } void detail::behavior_impl::handle_timeout() { }
} // namespace cppa } // namespace cppa
namespace cppa { namespace detail {
behavior_impl_ptr combine(behavior_impl_ptr lhs, const partial_function& rhs) {
return lhs->or_else(rhs.as_behavior_impl());
}
behavior_impl_ptr combine(const partial_function& lhs, behavior_impl_ptr rhs) {
return lhs.as_behavior_impl()->or_else(rhs);
}
behavior_impl_ptr extract(const partial_function& arg) {
return arg.as_behavior_impl();
}
} } // namespace cppa::detail
...@@ -390,10 +390,86 @@ void test_serial_reply() { ...@@ -390,10 +390,86 @@ void test_serial_reply() {
} }
void test_or_else() {
partial_function handle_a {
on("a") >> [] { return 1; }
};
partial_function handle_b {
on("b") >> [] { return 2; }
};
partial_function handle_c {
on("c") >> [] { return 3; }
};
auto run_testee([](actor_ptr testee) {
sync_send(testee, "a").await([](int i) {
CPPA_CHECK_EQUAL(i, 1);
});
sync_send(testee, "b").await([](int i) {
CPPA_CHECK_EQUAL(i, 2);
});
sync_send(testee, "c").await([](int i) {
CPPA_CHECK_EQUAL(i, 3);
});
send_exit(testee, exit_reason::user_shutdown);
await_all_others_done();
});
run_testee(
spawn([=] {
become(handle_a.or_else(handle_b).or_else(handle_c));
})
);
run_testee(
spawn([=] {
become(handle_a, handle_b, handle_c);
})
);
run_testee(
spawn([=] {
become(
handle_a.or_else(handle_b),
on("c") >> [] { return 3; }
);
})
);
run_testee(
spawn([=] {
become(
on("a") >> [] { return 1; },
handle_b.or_else(handle_c)
);
})
);
}
void test_continuation() {
auto mirror = spawn<simple_mirror>();
spawn([=] {
sync_send(mirror, 42).then(
on(42) >> [] {
return "fourty-two";
}
).continue_with(
[=](const string& ref) {
CPPA_CHECK_EQUAL(ref, "fourty-two");
return 4.2f;
}
).continue_with(
[=](float f) {
CPPA_CHECK_EQUAL(f, 4.2f);
send_exit(mirror, exit_reason::user_shutdown);
self->quit();
}
);
});
await_all_others_done();
}
int main() { int main() {
CPPA_TEST(test_spawn); CPPA_TEST(test_spawn);
test_serial_reply(); test_serial_reply();
test_or_else();
test_continuation();
// check whether detached actors and scheduled actors interact w/o errors // check whether detached actors and scheduled actors interact w/o errors
auto m = spawn<master, detached>(); auto m = spawn<master, detached>();
......
...@@ -153,8 +153,26 @@ int main() { ...@@ -153,8 +153,26 @@ int main() {
sync_send(ptr, 1.2f).await( sync_send(ptr, 1.2f).await(
[] { CPPA_CHECKPOINT(); } [] { CPPA_CHECKPOINT(); }
); );
send_exit(ptr0, exit_reason::user_shutdown); spawn([=] {
send_exit(ptr, exit_reason::user_shutdown); sync_send(ptr, 2.3f).then(
[] (int c) {
CPPA_CHECK_EQUAL(c, 3);
return "hello continuation";
}
).continue_with(
[] (const string& str) {
CPPA_CHECK_EQUAL(str, "hello continuation");
return 4.2;
}
).continue_with(
[=] (double d) {
CPPA_CHECK_EQUAL(d, 4.2);
send_exit(ptr0, exit_reason::user_shutdown);
send_exit(ptr, exit_reason::user_shutdown);
self->quit();
}
);
});
await_all_others_done(); await_all_others_done();
CPPA_CHECKPOINT(); CPPA_CHECKPOINT();
shutdown(); shutdown();
......
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