Commit 715e1999 authored by Dominik Charousset's avatar Dominik Charousset

properly implemented skipping for typed actors

parent 81f824fb
......@@ -186,7 +186,6 @@ set(LIBCPPA_SRC
src/node_id.cpp
src/object.cpp
src/object_array.cpp
src/on.cpp
src/opt.cpp
src/partial_function.cpp
src/primitive_variant.cpp
......
......@@ -113,7 +113,7 @@ cppa/mailbox_based.hpp
cppa/mailbox_element.hpp
cppa/match.hpp
cppa/match_expr.hpp
cppa/match_hint.hpp
cppa/skip_message.hpp
cppa/memory_cached.hpp
cppa/memory_managed.hpp
cppa/message_header.hpp
......@@ -293,7 +293,6 @@ src/middleman_event_handler_poll.cpp
src/node_id.cpp
src/object.cpp
src/object_array.cpp
src/on.cpp
src/opencl/actor_facade.cpp
src/opencl/global.cpp
src/opencl/opencl_metainfo.cpp
......@@ -349,3 +348,4 @@ unit_testing/test_typed_remote_actor.cpp
unit_testing/test_typed_spawn.cpp
unit_testing/test_uniform_type.cpp
unit_testing/test_yield_interface.cpp
cppa/may_have_timeout.hpp
......@@ -64,8 +64,6 @@ class behavior {
inline behavior(impl_ptr ptr);
static constexpr bool may_have_timeout = true;
/** @endcond */
behavior() = default;
......@@ -88,6 +86,14 @@ class behavior {
template<typename... Cs, typename T, typename... Ts>
behavior(const match_expr<Cs...>& arg0, const T& arg1, const Ts&... args);
template<typename F,
typename Enable = typename std::enable_if<
util::is_callable<F>::value
&& !std::is_same<F, behavior>::value
&& !std::is_same<F, partial_function>::value
>::type>
behavior(F fun);
/**
* @brief Invokes the timeout callback.
*/
......@@ -137,6 +143,10 @@ inline behavior operator,(const match_expr<Cs...>& lhs,
* inline and template member function implementations *
******************************************************************************/
template<typename F, typename Enable>
behavior::behavior(F fun)
: m_impl(detail::match_expr_from_functor(std::move(fun)).as_behavior_impl()) { }
template<typename F>
behavior::behavior(const timeout_definition<F>& arg)
: m_impl(detail::new_default_behavior(arg.timeout, arg.handler)) { }
......@@ -173,11 +183,6 @@ inline auto behavior::as_behavior_impl() const -> const impl_ptr& {
return m_impl;
}
//template<typename F>
//inline behavior behavior::add_continuation(F fun) {
// return {new detail::continuation_decorator<F>(std::move(fun), m_impl)};
//}
} // namespace cppa
#endif // CPPA_BEHAVIOR_HPP
......@@ -70,7 +70,7 @@ class blocking_actor
void operator()(Ts&&... args) {
static_assert(sizeof...(Ts) > 0,
"operator() requires at least one argument");
behavior bhvr = match_expr_convert(std::forward<Ts>(args)...);
behavior bhvr = lift_and_convert(std::forward<Ts>(args)...);
while (m_stmt()) m_dq(bhvr);
}
......@@ -85,7 +85,7 @@ class blocking_actor
template<typename... Ts>
void operator()(Ts&&... args) {
behavior bhvr = match_expr_convert(std::forward<Ts>(args)...);
behavior bhvr = lift_and_convert(std::forward<Ts>(args)...);
for ( ; begin != end; ++begin) m_dq(bhvr);
}
......@@ -111,7 +111,7 @@ class blocking_actor
template<typename... Ts>
void receive(Ts&&... args) {
static_assert(sizeof...(Ts), "at least one argument required");
dequeue(match_expr_convert(std::forward<Ts>(args)...));
dequeue(lift_and_convert(std::forward<Ts>(args)...));
}
/**
......@@ -120,7 +120,7 @@ class blocking_actor
*/
template<typename... Ts>
void receive_loop(Ts&&... args) {
behavior bhvr = match_expr_convert(std::forward<Ts>(args)...);
behavior bhvr = lift_and_convert(std::forward<Ts>(args)...);
for (;;) dequeue(bhvr);
}
......@@ -192,7 +192,7 @@ class blocking_actor
template<typename... Ts>
do_receive_helper do_receive(Ts&&... args) {
return { make_dequeue_callback()
, match_expr_convert(std::forward<Ts>(args)...)};
, lift_and_convert(std::forward<Ts>(args)...)};
}
optional<behavior&> sync_handler(message_id msg_id) override {
......
......@@ -36,6 +36,7 @@
#include "cppa/on.hpp"
#include "cppa/behavior.hpp"
#include "cppa/message_id.hpp"
#include "cppa/partial_function.hpp"
namespace cppa {
......
......@@ -78,9 +78,9 @@ struct optional_any_tuple_visitor {
};
template<typename... Ts>
struct has_match_hint {
struct has_skip_message {
static constexpr bool value = util::disjunction<
std::is_same<Ts, match_hint>::value...
std::is_same<Ts, skip_message_t>::value...
>::value;
};
......@@ -188,13 +188,10 @@ class default_behavior_impl : public behavior_impl {
private:
template<typename... Ts>
typename std::enable_if<has_match_hint<Ts...>::value, bhvr_invoke_result>::type
typename std::enable_if<has_skip_message<Ts...>::value, bhvr_invoke_result>::type
eval_res(optional_variant<Ts...>&& res) {
if (res) {
if (res.template is<match_hint>()) {
if (get<match_hint>(res) == match_hint::handle) {
return any_tuple{};
}
if (res.template is<skip_message_t>()) {
return none;
}
return apply_visitor(optional_any_tuple_visitor{}, res);
......@@ -203,7 +200,7 @@ class default_behavior_impl : public behavior_impl {
}
template<typename... Ts>
typename std::enable_if<!has_match_hint<Ts...>::value, bhvr_invoke_result>::type
typename std::enable_if<!has_skip_message<Ts...>::value, bhvr_invoke_result>::type
eval_res(optional_variant<Ts...>&& res) {
return apply_visitor(optional_any_tuple_visitor{}, res);
}
......
......@@ -93,25 +93,6 @@ class projection {
projection(const projection&) = default;
/**
* @brief Invokes @p fun with a projection of <tt>args...</tt> and stores
* the result of @p fun in @p result.
*/
/*
template<class PartFun>
bool invoke(PartFun& fun, typename PartFun::result_type& result, Ts... args) const {
typename collected_args_tuple<ProjectionFuns, Ts...>::type pargs;
if (collect(pargs, m_funs, std::forward<Ts>(args)...)) {
auto indices = util::get_indices(pargs);
if (is_defined_at(fun, pargs, indices)) {
result = util::apply_args(fun, pargs, indices);
return true;
}
}
return false;
}
*/
/**
* @brief Invokes @p fun with a projection of <tt>args...</tt>.
*/
......
......@@ -32,7 +32,7 @@
#define CPPA_DETAIL_RESPONSE_FUTURE_UTIL_HPP
#include "cppa/on.hpp"
#include "cppa/match_hint.hpp"
#include "cppa/skip_message.hpp"
#include "cppa/system_messages.hpp"
#include "cppa/util/type_traits.hpp"
......@@ -42,9 +42,9 @@ namespace detail {
template<typename Actor, typename... Fs>
behavior fs2bhvr(Actor* self, Fs... fs) {
auto handle_sync_timeout = [self]() -> match_hint {
auto handle_sync_timeout = [self]() -> skip_message_t {
self->handle_sync_timeout();
return match_hint::skip;
return {};
};
return behavior{
on<sync_timeout_msg>() >> handle_sync_timeout,
......
......@@ -37,8 +37,8 @@
#include <type_traits>
#include "cppa/any_tuple.hpp"
#include "cppa/match_hint.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/skip_message.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/util/tbind.hpp"
......@@ -170,14 +170,8 @@ static inline bool eval_res(const optional<T>& res, bool&) {
return static_cast<bool>(res);
}
static inline bool eval_res(const optional<match_hint>& res, bool& skipped) {
if (res) {
if (*res == match_hint::skip) {
skipped = true;
return false;
}
return true;
}
static inline bool eval_res(const optional<skip_message_t>& res, bool& skipped) {
if (res) skipped = true;
return false;
}
......@@ -240,13 +234,22 @@ size_t run_case(std::vector<T>& vec,
InputIterator& pos,
const InputIterator& end,
Case& target) {
// check that there's no empty match expression
// (would cause indefinite recursion)
static constexpr size_t num_args = util::tl_size<typename Case::pattern_type>::value;
typedef typename Case::second_type partial_fun_type;
typedef typename partial_fun_type::arg_types arg_types;
typedef typename util::tl_map<arg_types, util::rm_const_and_ref>::type plain_args;
static_assert(num_args > 0,
"empty match expressions are not allowed in stream matching");
static_assert(util::tl_forall<plain_args, util::tbind<std::is_same, T>::template type>::value,
typedef typename Case::first_type projection_type;
typedef typename projection_type::arg_types arg_types;
typedef typename util::tl_map<
arg_types,
util::rm_const_and_ref
>::type
plain_args;
static_assert(util::tl_forall<
plain_args,
util::tbind<std::is_same, T>::template type
>::value,
"match_stream<T>: at least one callback argument "
"is not of type T");
while (vec.size() < num_args) {
......
......@@ -359,7 +359,6 @@ struct invoke_util
typename util::tl_filter_not_type<Pattern, anything>::type> {
};
template<class Pattern, class Projection, class PartialFun>
struct projection_partial_function_pair : std::pair<Projection, PartialFun> {
template<typename... Ts>
......@@ -629,7 +628,8 @@ struct get_case_result {
namespace cppa {
/**
* @brief A match expression encapsulating cases <tt>Cs...</tt>.
* @brief A match expression encapsulating cases <tt>Cs...</tt>, whereas
* each case is a @p detail::projection_partial_function_pair.
*/
template<class... Cs>
class match_expr {
......@@ -638,8 +638,6 @@ class match_expr {
public:
static constexpr bool may_have_timeout = false;
typedef util::type_list<Cs...> cases_list;
typedef typename optional_variant_from_type_list<
......@@ -995,6 +993,30 @@ behavior_impl_ptr match_expr_concat(const T& arg, const Ts&... args) {
return concat_rec(dummy, util::empty_type_list{}, arg, args...);
}
template<typename F>
match_expr<
typename get_case<
false,
F,
empty_value_guard,
util::empty_type_list,
util::empty_type_list
>::type>
match_expr_from_functor(F fun) {
typedef typename get_case<
false,
F,
empty_value_guard,
util::empty_type_list,
util::empty_type_list
>::type
result_type;
return result_type{typename result_type::first_type{},
typename result_type::second_type{
std::move(fun),
empty_value_guard{}}};
}
} // namespace detail
} // namespace cppa
......
......@@ -27,12 +27,32 @@
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#include "cppa/on.hpp"
#ifndef MAY_HAVE_TIMEOUT_HPP
#define MAY_HAVE_TIMEOUT_HPP
namespace cppa {
match_hint skip_message() {
return match_hint::skip;
}
template<typename F>
struct timeout_definition;
class behavior;
template<typename T>
struct may_have_timeout {
static constexpr bool value = false;
};
template<>
struct may_have_timeout<behavior> {
static constexpr bool value = true;
};
template<typename F>
struct may_have_timeout<timeout_definition<F>> {
static constexpr bool value = true;
};
} // namespace cppa
#endif // MAY_HAVE_TIMEOUT_HPP
......@@ -38,12 +38,12 @@
#include "cppa/unit.hpp"
#include "cppa/atom.hpp"
#include "cppa/anything.hpp"
#include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/guard_expr.hpp"
#include "cppa/match_hint.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/skip_message.hpp"
#include "cppa/may_have_timeout.hpp"
#include "cppa/timeout_definition.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/util/type_list.hpp"
......@@ -227,11 +227,6 @@ namespace cppa {
*/
constexpr anything any_vals = anything{};
/**
* @brief Returns {@link match_hint skipped}.
*/
match_hint skip_message();
#ifdef CPPA_DOCUMENTATION
/**
......@@ -418,14 +413,16 @@ constexpr detail::on_the_fly_rvalue_builder on_arg_match;
// and even more convenience
template<typename F, class E = typename std::enable_if<util::is_callable<F>::value>::type>
template<typename F,
class E = typename std::enable_if<util::is_callable<F>::value>::type>
inline auto lift_to_match_expr(F fun) -> decltype(on_arg_match >> fun) {
return (on_arg_match >> fun);
}
template<typename... Cs>
inline match_expr<Cs...> lift_to_match_expr(match_expr<Cs...> expr) {
return std::move(expr);
template<typename T,
class E = typename std::enable_if<!util::is_callable<T>::value>::type>
inline T lift_to_match_expr(T arg) {
return arg;
}
#endif // CPPA_DOCUMENTATION
......
......@@ -38,7 +38,7 @@
#include "cppa/none.hpp"
#include "cppa/unit.hpp"
#include "cppa/optional.hpp"
#include "cppa/match_hint.hpp"
#include "cppa/skip_message.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/type_traits.hpp"
......@@ -116,8 +116,6 @@ class optional_variant {
static constexpr int void_pos = util::tl_find<types, void>::value;
static constexpr bool has_match_hint = util::tl_find<types, match_hint>::value != -1;
/**
* @brief Checks whether this objects holds a value of type @p T.
*/
......
......@@ -37,10 +37,12 @@
#include <utility>
#include <type_traits>
#include "cppa/on.hpp"
#include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/may_have_timeout.hpp"
#include "cppa/timeout_definition.hpp"
#include "cppa/util/duration.hpp"
......@@ -69,8 +71,6 @@ class partial_function {
partial_function(impl_ptr ptr);
static constexpr bool may_have_timeout = false;
/** @endcond */
partial_function() = default;
......@@ -107,7 +107,9 @@ class partial_function {
*/
template<typename... Ts>
typename std::conditional<
util::disjunction<util::rm_const_and_ref<Ts>::type::may_have_timeout...>::value,
util::disjunction<
may_have_timeout<typename util::rm_const_and_ref<Ts>::type>::value...
>::value,
behavior,
partial_function
>::type
......@@ -120,7 +122,11 @@ class partial_function {
};
template<typename T>
typename std::conditional<T::may_have_timeout, behavior, partial_function>::type
typename std::conditional<
may_have_timeout<T>::value,
behavior,
partial_function
>::type
match_expr_convert(const T& arg) {
return {arg};
}
......@@ -128,9 +134,9 @@ match_expr_convert(const T& arg) {
template<typename T0, typename T1, typename... Ts>
typename std::conditional<
util::disjunction<
T0::may_have_timeout,
T1::may_have_timeout,
Ts::may_have_timeout...
may_have_timeout<T0>::value,
may_have_timeout<T1>::value,
may_have_timeout<Ts>::value...
>::value,
behavior,
partial_function
......@@ -139,6 +145,20 @@ match_expr_convert(const T0& arg0, const T1& arg1, const Ts&... args) {
return detail::match_expr_concat(arg0, arg1, args...);
}
// calls match_expr_convert(lift_to_match_expr(args)...)
template<typename... Ts>
typename std::conditional<
util::disjunction<
may_have_timeout<Ts>::value...
>::value,
behavior,
partial_function
>::type
lift_and_convert(Ts&&... args) {
static_assert(sizeof...(Ts) > 0, "at least one argument required");
return match_expr_convert(lift_to_match_expr(std::forward<Ts>(args))...);
}
template<typename... Cases>
partial_function operator,(const match_expr<Cases...>& mexpr,
const partial_function& pfun) {
......@@ -174,7 +194,9 @@ inline optional<any_tuple> partial_function::operator()(T&& arg) {
template<typename... Ts>
typename std::conditional<
util::disjunction<util::rm_const_and_ref<Ts>::type::may_have_timeout...>::value,
util::disjunction<
may_have_timeout<typename util::rm_const_and_ref<Ts>::type>::value...
>::value,
behavior,
partial_function
>::type
......
......@@ -31,8 +31,6 @@
#ifndef CPPA_MATCH_HINT_HPP
#define CPPA_MATCH_HINT_HPP
#include <iosfwd>
namespace cppa {
/**
......@@ -40,13 +38,19 @@ namespace cppa {
* expressions. This type is evaluated by the runtime system of libcppa
* and can be used to intentionally skip messages.
*/
enum class match_hint {
skip,
handle
};
struct skip_message_t { constexpr skip_message_t() { } };
/**
* @brief Tells the runtime system to skip a message when used as message
* handler, i.e., causes the runtime to leave the message in
* the mailbox of an actor.
*/
constexpr skip_message_t skip_message() {
return {};
}
// implemented in string_serialization.cpp
std::ostream& operator<<(std::ostream&, match_hint);
std::ostream& operator<<(std::ostream&, skip_message_t);
} // namespace cppa
......
......@@ -33,6 +33,7 @@
#include "cppa/behavior.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/typed_continue_helper.hpp"
#include "cppa/detail/typed_actor_util.hpp"
......@@ -43,51 +44,69 @@ namespace detail {
template<typename... Rs>
class functor_based_typed_actor;
template<typename T>
struct match_hint_to_void {
typedef T type;
};
// converts a list of replies_to<...>::with<...> elements to a list of
// lists containing the replies_to<...> half only
template<typename List>
struct input_only;
template<>
struct match_hint_to_void<match_hint> {
typedef void type;
};
template<typename T>
struct infer_result_from_continue_helper {
typedef T type;
template<typename... Ts>
struct input_only<util::type_list<Ts...>> {
typedef util::type_list<typename Ts::input_types...> type;
};
template<typename R>
struct infer_result_from_continue_helper<typed_continue_helper<R>> {
typedef R type;
};
typedef util::type_list<skip_message_t> skip_list;
template<class List>
struct collapse_infered_list {
struct unbox_typed_continue_helper {
// do nothing if List is actually a list, i.e., not a typed_continue_helper
typedef List type;
};
template<typename... Ts>
struct collapse_infered_list<util::type_list<util::type_list<Ts...>>> {
typedef util::type_list<Ts...> type;
template<class List>
struct unbox_typed_continue_helper<util::type_list<typed_continue_helper<List>>> {
typedef List type;
};
template<typename T>
struct infer_response_types {
typedef typename T::input_types input_types;
typedef typename util::tl_map<
typename T::output_types,
match_hint_to_void,
infer_result_from_continue_helper
template<typename SList>
struct valid_input_predicate {
typedef typename input_only<SList>::type s_inputs;
template<typename Expr>
struct inner {
typedef typename Expr::input_types input_types;
typedef typename unbox_typed_continue_helper<
typename Expr::output_types
>::type
output_types;
typedef typename replies_to_from_type_list<
input_types,
// continue_helper stores a type list,
// so we need to collapse the list here
typename collapse_infered_list<output_types>::type
>::type
type;
static constexpr int pos = util::tl_find<s_inputs, input_types>::value;
static_assert(pos != -1, "cannot assign given match expression to "
"typed behavior, because the expression "
"contains at least one pattern that is "
"not defined in the actor's type");
typedef typename util::tl_at<SList, pos>::type s_element;
typedef typename s_element::output_types s_out;
static constexpr bool value =
std::is_same<output_types, s_out>::value
|| std::is_same<output_types, skip_list>::value;
static_assert(value, "wtf");
};
};
// Tests whether the input list (IList) matches the
// signature list (SList) for a typed actor behavior
template<class SList, class IList>
struct valid_input {
// check for each element in IList that there's an element in SList that
// (1) has an identical input type list
// (2) has an identical output type list
// OR the output of the element in IList is skip_message_t
static_assert(util::tl_is_distinct<IList>::value,
"given pattern is not distinct");
static constexpr bool value =
util::tl_size<SList>::value == util::tl_size<IList>::value
&& util::tl_forall<
IList,
valid_input_predicate<SList>::template inner
>::value;
};
// this function is called from typed_behavior<...>::set and its whole
......@@ -95,12 +114,12 @@ struct infer_response_types {
// (this function only has the type informations needed to understand the error)
template<class SignatureList, class InputList>
void static_check_typed_behavior_input() {
constexpr bool is_equal = util::tl_equal<SignatureList, InputList>::value;
constexpr bool is_valid = valid_input<SignatureList, InputList>::value;
// note: it might be worth considering to allow a wildcard in the
// InputList if its return type is identical to all "missing"
// input types ... however, it might lead to unexpected results
// and would cause a lot of not-so-straightforward code here
static_assert(is_equal, "given pattern cannot be used to initialize "
static_assert(is_valid, "given pattern cannot be used to initialize "
"typed behavior (exact match needed)");
}
......@@ -181,11 +200,7 @@ class typed_behavior {
typedef typename util::tl_map<
util::type_list<
typename detail::deduce_signature<Cs>::type...
>,
// returning a match_hint from a message handler does
// not send anything back, so we can consider
// match_hint to be void
detail::infer_response_types
>
>::type
input;
// check types
......
......@@ -35,6 +35,8 @@
#include "cppa/util/type_traits.hpp"
#include "cppa/detail/typed_actor_util.hpp"
namespace cppa {
template<typename OutputList>
......
......@@ -40,7 +40,8 @@
#include "cppa/util/type_list.hpp"
#include "cppa/util/type_traits.hpp"
namespace cppa { namespace util {
namespace cppa {
namespace util {
/**
* @addtogroup MetaProgramming
......@@ -59,7 +60,7 @@ template<typename T> struct rm_const_and_ref<const T> { typedef T type; };
template<typename T> struct rm_const_and_ref<T&> { typedef T type; };
template<> struct rm_const_and_ref<void> { };
//template<> struct rm_const_and_ref<void> { };
/**
* @brief Joins all bool constants using operator &&.
......@@ -94,7 +95,6 @@ struct disjunction<V0, Vs...> {
template<>
struct disjunction<> { static constexpr bool value = false; };
/**
* @brief Equal to std::is_same<T, anything>.
*/
......@@ -496,6 +496,8 @@ struct type_at<0, T0, Ts...> {
/**
* @}
*/
} } // namespace cppa::util
} // namespace util
} // namespace cppa
#endif // CPPA_UTIL_TYPE_TRAITS_HPP
......@@ -86,5 +86,4 @@ behavior behavior::add_continuation(continuation_fun fun) {
return {new continuation_decorator(std::move(fun), m_impl)};
}
} // namespace cppa
......@@ -38,11 +38,11 @@
#include "cppa/atom.hpp"
#include "cppa/object.hpp"
#include "cppa/to_string.hpp"
#include "cppa/match_hint.hpp"
#include "cppa/serializer.hpp"
#include "cppa/singletons.hpp"
#include "cppa/from_string.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/skip_message.hpp"
#include "cppa/actor_namespace.hpp"
#include "cppa/primitive_variant.hpp"
#include "cppa/uniform_type_info.hpp"
......@@ -526,9 +526,8 @@ string to_verbose_string(const exception& e) {
return oss.str();
}
std::ostream& operator<<(std::ostream& out, match_hint mh) {
return out << (mh == match_hint::handle ? "match_hint::handle"
: "match_hint::skip");
std::ostream& operator<<(std::ostream& out, skip_message_t) {
return out << "skip_message";
}
} // namespace cppa
......@@ -268,17 +268,12 @@ void test_match_stream() {
CPPA_CHECK(name == "foo" || name == "bar");
return name == "foo" || name == "bar";
},
on("-p", arg_match) >> [&](const string& port) -> match_hint {
auto i = toint(port);
if (i) {
CPPA_CHECK_EQUAL(*i, 2);
return match_hint::handle;
}
else return match_hint::skip;
on("-p", toint) >> [&](int port) {
CPPA_CHECK_EQUAL(port, 2);
},
on_arg_match >> [](const string& arg) -> match_hint {
on_arg_match >> [](const string& arg) -> skip_message_t {
CPPA_FAILURE("unexpected string: " << arg);
return match_hint::skip;
return {};
}
);
CPPA_CHECK_EQUAL(success, true);
......@@ -291,10 +286,13 @@ void test_behavior() {
CPPA_CHECK_EQUAL(static_cast<bool>(pf(tup)), expected_result); \
CPPA_CHECK_EQUAL(last_invoked_fun, str); \
}
auto not_42 = [](int i) -> optional<int> {
if (i != 42) return i;
return none;
};
behavior bhvr1 {
on<int>() >> [&](int i) -> match_hint {
on(not_42) >> [&](int) {
last_invoked_fun = "<int>@1";
return (i == 42) ? match_hint::skip : match_hint::handle;
},
on<float>() >> [&] {
last_invoked_fun = "<float>@2";
......@@ -306,7 +304,7 @@ void test_behavior() {
last_invoked_fun = "<*>@4";
}
};
bhvr_check(bhvr1, make_any_tuple(42), false, "<int>@1");
bhvr_check(bhvr1, make_any_tuple(42), true, "<int>@3");
bhvr_check(bhvr1, make_any_tuple(24), true, "<int>@1");
bhvr_check(bhvr1, make_any_tuple(2.f), true, "<float>@2");
bhvr_check(bhvr1, make_any_tuple(""), true, "<*>@4");
......
......@@ -217,16 +217,16 @@ void test_sync_send() {
self->send_exit(mirror, exit_reason::user_shutdown);
self->await_all_other_actors_done();
CPPA_CHECKPOINT();
auto non_normal_down_msg = [](down_msg dm) -> optional<down_msg> {
if (dm.reason != exit_reason::normal) return dm;
return none;
};
auto await_success_message = [&] {
self->receive (
on(atom("success")) >> CPPA_CHECKPOINT_CB(),
on(atom("failure")) >> CPPA_FAILURE_CB("A didn't receive sync response"),
on_arg_match >> [&](const down_msg& dm) -> match_hint {
if (dm.reason != exit_reason::normal) {
on(non_normal_down_msg) >> [&](const down_msg& dm) {
CPPA_FAILURE("A exited for reason " << dm.reason);
return match_hint::handle;
}
return match_hint::skip;
}
);
};
......
......@@ -137,7 +137,7 @@ typedef typed_actor<
replies_to<get_state_msg>::with<string>,
replies_to<string>::with<void>,
replies_to<float>::with<void>,
replies_to<int>::with<void>
replies_to<int>::with<int>
>
event_testee_type;
......@@ -162,12 +162,11 @@ class event_testee : public event_testee_type::base {
on<get_state_msg>() >> [] {
return "wait4int";
},
on<int>() >> [=] {
on<int>() >> [=]() -> int {
become(wait4float());
return 42;
},
(on<float>() || on<string>()) >> [] {
return match_hint::skip;
}
(on<float>() || on<string>()) >> skip_message
};
}
......@@ -179,9 +178,7 @@ class event_testee : public event_testee_type::base {
on<float>() >> [=] {
become(wait4string());
},
(on<string>() || on<int>()) >> [] {
return match_hint::skip;
}
(on<string>() || on<int>()) >> skip_message
};
}
......@@ -208,11 +205,18 @@ void test_event_testee() {
set<string> iface{"cppa::replies_to<get_state_msg>::with<@str>",
"cppa::replies_to<@str>::with<void>",
"cppa::replies_to<float>::with<void>",
"cppa::replies_to<@i32>::with<void>"};
"cppa::replies_to<@i32>::with<@i32>"};
CPPA_CHECK(sub_et->interface() == iface);
self->send(sub_et, get_state_msg{});
// we expect three 42s
int i = 0;
self->receive_for(i, 3) (
[](int value) {
CPPA_CHECK_EQUAL(value, 42);
}
);
self->receive (
on_arg_match >> [&](const string& str) {
[&](const string& str) {
result = str;
},
after(chrono::minutes(1)) >> [&]() {
......
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