Commit dd826000 authored by Dominik Charousset's avatar Dominik Charousset

fixed continuation handling

continuation is called only if given functor is invoked
parent 7f9d99c4
...@@ -119,6 +119,20 @@ class projection { ...@@ -119,6 +119,20 @@ class projection {
return false; return false;
} }
/**
* @brief Invokes @p fun with a projection of <tt>args...</tt> and stores
* the result of @p fun in @p result.
*/
template<class PartialFun>
inline bool operator()(PartialFun& fun, typename PartialFun::result_type& result, Args... args) const {
return invoke(fun, result, args...);
}
template<class PartialFun>
inline bool operator()(PartialFun& fun, const util::void_type&, Args... args) const {
return (*this)(fun, args...);
}
private: private:
template<typename Storage, typename T> template<typename Storage, typename T>
...@@ -181,6 +195,24 @@ class projection<util::empty_type_list> { ...@@ -181,6 +195,24 @@ class projection<util::empty_type_list> {
return false; return false;
} }
template<class PartialFun>
bool operator()(PartialFun& fun, const util::void_type&) const {
if (fun.defined_at()) {
fun();
return true;
}
return false;
}
template<class PartialFun>
bool operator()(PartialFun& fun, typename PartialFun::result_type& res) const {
if (fun.defined_at()) {
res = fun();
return true;
}
return false;
}
}; };
template<class ProjectionFuns, class List> template<class ProjectionFuns, class List>
......
...@@ -49,7 +49,7 @@ struct pseudo_tuple { ...@@ -49,7 +49,7 @@ struct pseudo_tuple {
} }
inline pointer mutable_at(size_t p) { inline pointer mutable_at(size_t p) {
return const_cast<pointer>(data[p]); return data[p];
} }
inline pointer& operator[](size_t p) { inline pointer& operator[](size_t p) {
......
...@@ -359,14 +359,7 @@ class receive_policy { ...@@ -359,14 +359,7 @@ class receive_policy {
case sync_response: { case sync_response: {
if (awaited_response.valid() && node->mid == awaited_response) { if (awaited_response.valid() && node->mid == awaited_response) {
auto previous_node = hm_begin(client, node, policy); auto previous_node = hm_begin(client, node, policy);
# ifdef CPPA_DEBUG
if (!fun(node->msg)) {
std::cerr << "WARNING: actor didn't handle a "
"synchronous message\n";
}
# else
fun(node->msg); fun(node->msg);
# endif
client->mark_arrived(awaited_response); client->mark_arrived(awaited_response);
client->remove_handler(awaited_response); client->remove_handler(awaited_response);
hm_cleanup(client, previous_node, policy); hm_cleanup(client, previous_node, policy);
......
...@@ -52,66 +52,76 @@ ...@@ -52,66 +52,76 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<long N>
struct long_constant { static constexpr long value = N; };
typedef long_constant<-1l> minus1l;
template<typename T1, typename T2>
inline T2& deduce_const(T1&, T2& rhs) { return rhs; }
template<typename T1, typename T2>
inline const T2& deduce_const(const T1&, T2& rhs) { return rhs; }
template<class FilteredPattern>
struct invoke_policy_base {
typedef FilteredPattern filtered_pattern;
typedef typename pseudo_tuple_from_type_list<filtered_pattern>::type
tuple_type;
};
// covers wildcard_position::multiple and wildcard_position::in_between // covers wildcard_position::multiple and wildcard_position::in_between
template<wildcard_position, class Pattern, class FilteredPattern> template<wildcard_position, class Pattern, class FilteredPattern>
struct invoke_policy_impl { struct invoke_policy_impl : invoke_policy_base<FilteredPattern> {
typedef FilteredPattern filtered_pattern;
typedef invoke_policy_base<FilteredPattern> super;
template<class Tuple> template<class Tuple>
static bool can_invoke(const std::type_info& type_token, static bool can_invoke(const std::type_info& type_token,
const Tuple& tup) { const Tuple& tup) {
typedef typename match_impl_from_type_list<Tuple, Pattern>::type mimpl; typedef typename match_impl_from_type_list<Tuple,Pattern>::type mimpl;
return type_token == typeid(filtered_pattern) || mimpl::_(tup); return type_token == typeid(FilteredPattern) || mimpl::_(tup);
} }
template<class Target, typename PtrType, class Tuple> template<typename PtrType, class Tuple>
static bool invoke(Target& target, static bool prepare_invoke(typename super::tuple_type& result,
const std::type_info& type_token, const std::type_info& type_token,
detail::tuple_impl_info, detail::tuple_impl_info,
PtrType*, PtrType*,
Tuple& tup) { Tuple& tup) {
typedef typename match_impl_from_type_list< typedef typename match_impl_from_type_list<
typename std::remove_const<Tuple>::type, typename std::remove_const<Tuple>::type,
Pattern Pattern
>::type >::type
mimpl; mimpl;
util::fixed_vector<size_t, util::tl_size<filtered_pattern>::value> mv; util::fixed_vector<size_t,util::tl_size<FilteredPattern>::value> mv;
if (type_token == typeid(filtered_pattern) || mimpl::_(tup, mv)) { if (type_token == typeid(FilteredPattern) || mimpl::_(tup, mv)) {
typedef typename pseudo_tuple_from_type_list<filtered_pattern>::type for (size_t i = 0; i < util::tl_size<FilteredPattern>::value; ++i) {
ttup_type; result[i] = const_cast<void*>(tup.at(mv[i]));
ttup_type ttup;
// if we strip const here ...
for (size_t i = 0; i < util::tl_size<filtered_pattern>::value; ++i) {
ttup[i] = const_cast<void*>(tup.at(mv[i]));
} }
// ... we restore it here again return true;
typedef typename util::if_else<
std::is_const<Tuple>,
const ttup_type&,
util::wrapped<ttup_type&>
>::type
ttup_ref;
ttup_ref ttup_fwd = ttup;
auto indices = util::get_indices(ttup_fwd);
return util::apply_args_prefixed(target.first, ttup_fwd, indices, target.second);
} }
return false; return false;
} }
}; };
template<> template<>
struct invoke_policy_impl<wildcard_position::nil, struct invoke_policy_impl<wildcard_position::nil,
util::empty_type_list, util::empty_type_list,
util::empty_type_list > { util::empty_type_list >
: invoke_policy_base<util::empty_type_list> {
template<class Target, typename PtrType, typename Tuple> typedef invoke_policy_base<util::empty_type_list> super;
static bool invoke(Target& target,
const std::type_info&, template<typename PtrType, class Tuple>
detail::tuple_impl_info, static bool prepare_invoke(typename super::tuple_type&,
PtrType*, const std::type_info& type_token,
Tuple&) { detail::tuple_impl_info,
return target.first(target.second); PtrType*,
Tuple& tup) {
return can_invoke(type_token, tup);
} }
template<class Tuple> template<class Tuple>
...@@ -124,63 +134,67 @@ struct invoke_policy_impl<wildcard_position::nil, ...@@ -124,63 +134,67 @@ struct invoke_policy_impl<wildcard_position::nil,
template<class Pattern, typename... Ts> template<class Pattern, typename... Ts>
struct invoke_policy_impl<wildcard_position::nil, struct invoke_policy_impl<wildcard_position::nil,
Pattern, Pattern,
util::type_list<Ts...> > { util::type_list<Ts...>>
: invoke_policy_base<util::type_list<Ts...>> {
typedef invoke_policy_base<util::type_list<Ts...>> super;
typedef util::type_list<Ts...> filtered_pattern; typedef typename super::tuple_type tuple_type;
typedef detail::tdata<Ts...> native_data_type; typedef detail::tdata<Ts...> native_data_type;
typedef typename detail::static_types_array<Ts...> arr_type; typedef typename detail::static_types_array<Ts...> arr_type;
template<class Target, class Tup> template<class Tup>
static bool invoke(std::integral_constant<bool, false>, Target&, Tup&) { static bool prepare_invoke(std::false_type, tuple_type&, Tup&) {
return false; return false;
} }
template<class Target, class Tup> template<class Tup>
static bool invoke(std::integral_constant<bool, true>, static bool prepare_invoke(std::true_type, tuple_type& result, Tup& tup) {
Target& target, Tup& tup) { for (size_t i = 0; i < sizeof...(Ts); ++i) {
auto indices = util::get_indices(tup); result[i] = const_cast<void*>(tup.at(i));
return util::apply_args_prefixed(target.first, tup, indices, target.second); }
} return true;
}
template<class Target, typename PtrType, class Tuple>
static bool invoke(Target& target, template<typename PtrType, class Tuple>
const std::type_info&, static bool prepare_invoke(tuple_type& result,
detail::tuple_impl_info, const std::type_info&,
PtrType*, detail::tuple_impl_info,
Tuple& tup, PtrType*,
typename std::enable_if< Tuple& tup,
std::is_same< typename std::enable_if<
typename std::remove_const<Tuple>::type, std::is_same<
detail::abstract_tuple typename std::remove_const<Tuple>::type,
>::value == false detail::abstract_tuple
>::type* = 0) { >::value == false
static constexpr bool can_apply = >::type* = 0) {
util::tl_binary_forall< std::integral_constant<bool,
typename util::tl_map< util::tl_binary_forall<
typename Tuple::types, typename util::tl_map<
util::purge_refs typename Tuple::types,
>::type, util::purge_refs
filtered_pattern, >::type,
std::is_same util::type_list<Ts...>,
>::value; std::is_same
return invoke(std::integral_constant<bool, can_apply>{}, target, tup); >::value > token;
} return prepare_invoke(token, result, tup);
}
template<class Target, typename PtrType, typename Tuple>
static bool invoke(Target& target, template<typename PtrType, class Tuple>
const std::type_info& arg_types, static bool prepare_invoke(typename super::tuple_type& result,
detail::tuple_impl_info timpl, const std::type_info& arg_types,
PtrType* native_arg, detail::tuple_impl_info timpl,
Tuple& tup, PtrType* native_arg,
typename std::enable_if< Tuple& tup,
std::is_same< typename std::enable_if<
typename std::remove_const<Tuple>::type, std::is_same<
detail::abstract_tuple typename std::remove_const<Tuple>::type,
>::value detail::abstract_tuple
>::type* = 0) { >::value == true
if (arg_types == typeid(filtered_pattern)) { >::type* = 0) {
if (arg_types == typeid(util::type_list<Ts...>)) {
if (native_arg) { if (native_arg) {
typedef typename util::if_else_c< typedef typename util::if_else_c<
std::is_const<PtrType>::value, std::is_const<PtrType>::value,
...@@ -189,46 +203,35 @@ struct invoke_policy_impl<wildcard_position::nil, ...@@ -189,46 +203,35 @@ struct invoke_policy_impl<wildcard_position::nil,
>::type >::type
cast_type; cast_type;
auto arg = reinterpret_cast<cast_type>(native_arg); auto arg = reinterpret_cast<cast_type>(native_arg);
auto indices = util::get_indices(*arg); for (size_t i = 0; i < sizeof...(Ts); ++i) {
return util::apply_args_prefixed(target.first, *arg, indices, target.second); result[i] = const_cast<void*>(arg->at(i));
}
return true;
} }
// 'fall through' // 'fall through'
} }
else if (timpl == detail::dynamically_typed) { else if (timpl == detail::dynamically_typed) {
auto& arr = arr_type::arr; auto& arr = arr_type::arr;
if (tup.size() != util::tl_size<filtered_pattern>::value) { if (tup.size() != sizeof...(Ts)) {
return false; return false;
} }
for (size_t i = 0; i < util::tl_size<filtered_pattern>::value; ++i) { for (size_t i = 0; i < sizeof...(Ts); ++i) {
if (arr[i] != tup.type_at(i)) { if (arr[i] != tup.type_at(i)) {
return false; return false;
} }
} }
// 'fall through' // 'fall through'
} }
else { else return false;
return false; for (size_t i = 0; i < sizeof...(Ts); ++i) {
result[i] = const_cast<void*>(tup.at(i));
} }
typedef pseudo_tuple<Ts...> ttup_type; return true;
ttup_type ttup;
// if we strip const here ...
for (size_t i = 0; i < sizeof...(Ts); ++i)
ttup[i] = const_cast<void*>(tup.at(i));
// ... we restore it here again
typedef typename util::if_else<
std::is_const<PtrType>,
const ttup_type&,
util::wrapped<ttup_type&>
>::type
ttup_ref;
ttup_ref ttup_fwd = ttup;
auto indices = util::get_indices(ttup_fwd);
return util::apply_args_prefixed(target.first, ttup_fwd, indices, target.second);
} }
template<class Tuple> template<class Tuple>
static bool can_invoke(const std::type_info& arg_types, const Tuple&) { static bool can_invoke(const std::type_info& arg_types, const Tuple&) {
return arg_types == typeid(filtered_pattern); return arg_types == typeid(util::type_list<Ts...>);
} }
}; };
...@@ -236,41 +239,47 @@ struct invoke_policy_impl<wildcard_position::nil, ...@@ -236,41 +239,47 @@ struct invoke_policy_impl<wildcard_position::nil,
template<> template<>
struct invoke_policy_impl<wildcard_position::leading, struct invoke_policy_impl<wildcard_position::leading,
util::type_list<anything>, util::type_list<anything>,
util::empty_type_list> { util::empty_type_list>
: invoke_policy_base<util::empty_type_list> {
typedef invoke_policy_base<util::empty_type_list> super;
template<class Tuple> template<class Tuple>
static inline bool can_invoke(const std::type_info&, static inline bool can_invoke(const std::type_info&, const Tuple&) {
const Tuple&) {
return true; return true;
} }
template<class Target, typename PtrType, typename Tuple> template<typename PtrType, typename Tuple>
static bool invoke(Target& target, static inline bool prepare_invoke(typename super::tuple_type&,
const std::type_info&, const std::type_info&,
detail::tuple_impl_info, detail::tuple_impl_info,
PtrType*, PtrType*,
Tuple&) { Tuple&) {
return target.first(target.second); return true;
} }
}; };
template<class Pattern, typename... Ts> template<class Pattern, typename... Ts>
struct invoke_policy_impl<wildcard_position::trailing, struct invoke_policy_impl<wildcard_position::trailing,
Pattern, util::type_list<Ts...> > { Pattern,
typedef util::type_list<Ts...> filtered_pattern; util::type_list<Ts...>>
: invoke_policy_base<util::type_list<Ts...>> {
typedef invoke_policy_base<util::type_list<Ts...>> super;
template<class Tuple> template<class Tuple>
static bool can_invoke(const std::type_info& arg_types, static bool can_invoke(const std::type_info& arg_types,
const Tuple& tup) { const Tuple& tup) {
if (arg_types == typeid(filtered_pattern)) { if (arg_types == typeid(util::type_list<Ts...>)) {
return true; return true;
} }
typedef detail::static_types_array<Ts...> arr_type; typedef detail::static_types_array<Ts...> arr_type;
auto& arr = arr_type::arr; auto& arr = arr_type::arr;
if (tup.size() < util::tl_size<filtered_pattern>::value) { if (tup.size() < sizeof...(Ts)) {
return false; return false;
} }
for (size_t i = 0; i < util::tl_size<filtered_pattern>::value; ++i) { for (size_t i = 0; i < sizeof...(Ts); ++i) {
if (arr[i] != tup.type_at(i)) { if (arr[i] != tup.type_at(i)) {
return false; return false;
} }
...@@ -278,81 +287,59 @@ struct invoke_policy_impl<wildcard_position::trailing, ...@@ -278,81 +287,59 @@ struct invoke_policy_impl<wildcard_position::trailing,
return true; return true;
} }
template<class Target, typename PtrType, class Tuple> template<typename PtrType, class Tuple>
static bool invoke(Target& target, static bool prepare_invoke(typename super::tuple_type& result,
const std::type_info& arg_types, const std::type_info& arg_types,
detail::tuple_impl_info, detail::tuple_impl_info,
PtrType*, PtrType*,
Tuple& tup) { Tuple& tup) {
if (!can_invoke(arg_types, tup)) return false; if (!can_invoke(arg_types, tup)) return false;
typedef pseudo_tuple<Ts...> ttup_type; for (size_t i = 0; i < sizeof...(Ts); ++i) {
ttup_type ttup; result[i] = const_cast<void*>(tup.at(i));
for (size_t i = 0; i < sizeof...(Ts); ++i) }
ttup[i] = const_cast<void*>(tup.at(i)); return true;
// ensure const-correctness
typedef typename util::if_else<
std::is_const<Tuple>,
const ttup_type&,
util::wrapped<ttup_type&>
>::type
ttup_ref;
ttup_ref ttup_fwd = ttup;
auto indices = util::get_indices(ttup_fwd);
return util::apply_args_prefixed(target.first, ttup_fwd, indices, target.second);
} }
}; };
template<class Pattern, typename... Ts> template<class Pattern, typename... Ts>
struct invoke_policy_impl<wildcard_position::leading, struct invoke_policy_impl<wildcard_position::leading,
Pattern, util::type_list<Ts...> > { Pattern,
typedef util::type_list<Ts...> filtered_pattern; util::type_list<Ts...>>
: invoke_policy_base<util::type_list<Ts...>> {
typedef invoke_policy_base<util::type_list<Ts...>> super;
template<class Tuple> template<class Tuple>
static bool can_invoke(const std::type_info& arg_types, static bool can_invoke(const std::type_info& arg_types,
const Tuple& tup) { const Tuple& tup) {
if (arg_types == typeid(filtered_pattern)) { if (arg_types == typeid(util::type_list<Ts...>)) {
return true; return true;
} }
typedef detail::static_types_array<Ts...> arr_type; typedef detail::static_types_array<Ts...> arr_type;
auto& arr = arr_type::arr; auto& arr = arr_type::arr;
if (tup.size() < util::tl_size<filtered_pattern>::value) { if (tup.size() < sizeof...(Ts)) return false;
return false; size_t i = tup.size() - sizeof...(Ts);
}
size_t i = tup.size() - util::tl_size<filtered_pattern>::value;
size_t j = 0; size_t j = 0;
while (j < util::tl_size<filtered_pattern>::value) { while (j < sizeof...(Ts)) {
if (arr[i++] != tup.type_at(j++)) { if (arr[i++] != tup.type_at(j++)) return false;
return false;
}
} }
return true; return true;
} }
template<class Target, typename PtrType, class Tuple> template<typename PtrType, class Tuple>
static bool invoke(Target& target, static bool prepare_invoke(typename super::tuple_type& result,
const std::type_info& arg_types, const std::type_info& arg_types,
detail::tuple_impl_info, detail::tuple_impl_info,
PtrType*, PtrType*,
Tuple& tup) { Tuple& tup) {
if (!can_invoke(arg_types, tup)) return false; if (!can_invoke(arg_types, tup)) return false;
typedef pseudo_tuple<Ts...> ttup_type; size_t i = tup.size() - sizeof...(Ts);
ttup_type ttup;
size_t i = tup.size() - util::tl_size<filtered_pattern>::value;
size_t j = 0; size_t j = 0;
while (j < util::tl_size<filtered_pattern>::value) { while (j < sizeof...(Ts)) {
ttup[j++] = const_cast<void*>(tup.at(i++)); result[j++] = const_cast<void*>(tup.at(i++));
} }
// ensure const-correctness return true;
typedef typename util::if_else<
std::is_const<Tuple>,
const ttup_type&,
util::wrapped<ttup_type&>
>::type
ttup_ref;
ttup_ref ttup_fwd = ttup;
auto indices = util::get_indices(ttup_fwd);
return util::apply_args_prefixed(target.first, ttup_fwd, indices, target.second);
} }
}; };
...@@ -362,16 +349,15 @@ struct invoke_policy ...@@ -362,16 +349,15 @@ struct invoke_policy
: invoke_policy_impl< : invoke_policy_impl<
get_wildcard_position<Pattern>(), get_wildcard_position<Pattern>(),
Pattern, Pattern,
typename util::tl_filter_not_type<Pattern, anything>::type> { typename util::tl_filter_not_type<Pattern,anything>::type> {
}; };
template<class Pattern, class Projection, class PartialFunction> template<class Pattern, class Projection, class PartialFun>
struct projection_partial_function_pair : std::pair<Projection, PartialFunction> { struct projection_partial_function_pair : std::pair<Projection,PartialFun> {
template<typename... Args> template<typename... Args>
projection_partial_function_pair(Args&&... args) projection_partial_function_pair(Args&&... args)
: std::pair<Projection, PartialFunction>(std::forward<Args>(args)...) { : std::pair<Projection,PartialFun>(std::forward<Args>(args)...) { }
}
typedef Pattern pattern_type; typedef Pattern pattern_type;
}; };
...@@ -455,17 +441,17 @@ struct get_case_ { ...@@ -455,17 +441,17 @@ struct get_case_ {
>::type >::type
type2; type2;
typedef projection_partial_function_pair<Pattern, type1, type2> type; typedef projection_partial_function_pair<Pattern,type1,type2> type;
}; };
template<bool IsComplete, class Expr, class Guard, class Transformers, class Pattern> template<bool Complete, class Expr, class Guard, class Trans, class Pattern>
struct get_case { struct get_case {
typedef typename get_case_<Expr, Guard, Transformers, Pattern>::type type; typedef typename get_case_<Expr,Guard,Trans,Pattern>::type type;
}; };
template<class Expr, class Guard, class Transformers, class Pattern> template<class Expr, class Guard, class Trans, class Pattern>
struct get_case<false, Expr, Guard, Transformers, Pattern> { struct get_case<false,Expr,Guard,Trans,Pattern> {
typedef typename util::tl_pop_back<Pattern>::type lhs_pattern; typedef typename util::tl_pop_back<Pattern>::type lhs_pattern;
typedef typename util::tl_map< typedef typename util::tl_map<
typename util::get_arg_types<Expr>::types, typename util::get_arg_types<Expr>::types,
...@@ -475,26 +461,48 @@ struct get_case<false, Expr, Guard, Transformers, Pattern> { ...@@ -475,26 +461,48 @@ struct get_case<false, Expr, Guard, Transformers, Pattern> {
typedef typename get_case_< typedef typename get_case_<
Expr, Expr,
Guard, Guard,
Transformers, Trans,
typename util::tl_concat<lhs_pattern, rhs_pattern>::type typename util::tl_concat<lhs_pattern,rhs_pattern>::type
>::type >::type
type; type;
}; };
// PPFP = projection_partial_function_pair template<typename Fun>
template<class PPFPs, typename... Args> struct has_bool_result {
inline bool unroll_expr(PPFPs& fs, std::uint64_t bitmask, std::integral_constant<size_t,0>, const std::type_info& arg_types, Args&... as) { typedef typename Fun::result_type result_type;
if ((bitmask & 0x01) == 0) return false; static constexpr bool value = std::is_same<bool,result_type>::value;
auto& f = get<0>(fs); typedef std::integral_constant<bool,value> token_type;
typedef typename util::rm_ref<decltype(f)>::type Fun; };
typedef typename Fun::pattern_type pattern_type;
typedef detail::invoke_policy<pattern_type> policy; template<typename T1, typename T2>
return policy::invoke(f, arg_types, as...); T1& select_if(std::true_type, T1& lhs, T2&) { return lhs; }
template<typename T1, typename T2>
T2& select_if(std::false_type, T1&, T2& rhs) { return rhs; }
template<class PPFPs, typename PtrType, class Tuple>
inline bool unroll_expr(PPFPs&,
bool&,
std::uint64_t,
minus1l,
const std::type_info&,
detail::tuple_impl_info,
PtrType*,
Tuple&) {
return false;
} }
template<class PPFPs, size_t N, typename... Args> template<class PPFPs, long N, typename PtrType, class Tuple>
inline bool unroll_expr(PPFPs& fs, std::uint64_t bitmask, std::integral_constant<size_t,N>, const std::type_info& arg_types, Args&... as) { bool unroll_expr(PPFPs& fs,
if (unroll_expr(fs, bitmask, std::integral_constant<size_t,N-1>(), arg_types, as...)) { bool& invoke_res,
std::uint64_t bitmask,
long_constant<N>,
const std::type_info& type_token,
detail::tuple_impl_info iinfo,
PtrType* ptr,
Tuple& tup) {
if (unroll_expr(fs, invoke_res, bitmask, long_constant<N-1>{},
type_token, iinfo, ptr, tup)) {
return true; return true;
} }
if ((bitmask & (0x01 << N)) == 0) return false; if ((bitmask & (0x01 << N)) == 0) return false;
...@@ -502,22 +510,29 @@ inline bool unroll_expr(PPFPs& fs, std::uint64_t bitmask, std::integral_constant ...@@ -502,22 +510,29 @@ inline bool unroll_expr(PPFPs& fs, std::uint64_t bitmask, std::integral_constant
typedef typename util::rm_ref<decltype(f)>::type Fun; typedef typename util::rm_ref<decltype(f)>::type Fun;
typedef typename Fun::pattern_type pattern_type; typedef typename Fun::pattern_type pattern_type;
typedef detail::invoke_policy<pattern_type> policy; typedef detail::invoke_policy<pattern_type> policy;
return policy::invoke(f, arg_types, as...); typename policy::tuple_type targs;
if (policy::prepare_invoke(targs, type_token, iinfo, ptr, tup)) {
auto is = util::get_indices(targs);
util::void_type dummy;
typename has_bool_result<typename Fun::second_type>::token_type stoken;
return util::apply_args_prefixed(f.first,
deduce_const(tup, targs),
is,
f.second,
select_if(stoken, invoke_res, dummy));
}
return false;
} }
// PPFP = projection_partial_function_pair // PPFP = projection_partial_function_pair
template<class PPFPs, class Tuple> template<class PPFPs, class Tuple>
inline bool can_unroll_expr(PPFPs& fs, std::integral_constant<size_t,0>, const std::type_info& arg_types, const Tuple& tup) { inline bool can_unroll_expr(PPFPs&, minus1l, const std::type_info&, const Tuple&) {
auto& f = get<0>(fs); return false;
typedef typename util::rm_ref<decltype(f)>::type Fun;
typedef typename Fun::pattern_type pattern_type;
typedef detail::invoke_policy<pattern_type> policy;
return policy::can_invoke(arg_types, tup);
} }
template<class PPFPs, size_t N, class Tuple> template<class PPFPs, long N, class Tuple>
inline bool can_unroll_expr(PPFPs& fs, std::integral_constant<size_t,N>, const std::type_info& arg_types, const Tuple& tup) { inline bool can_unroll_expr(PPFPs& fs, long_constant<N>, const std::type_info& arg_types, const Tuple& tup) {
if (can_unroll_expr(fs, std::integral_constant<size_t,N-1>(), arg_types, tup)) { if (can_unroll_expr(fs, long_constant<N-1l>(), arg_types, tup)) {
return true; return true;
} }
auto& f = get<N>(fs); auto& f = get<N>(fs);
...@@ -528,22 +543,18 @@ inline bool can_unroll_expr(PPFPs& fs, std::integral_constant<size_t,N>, const s ...@@ -528,22 +543,18 @@ inline bool can_unroll_expr(PPFPs& fs, std::integral_constant<size_t,N>, const s
} }
template<class PPFPs, class Tuple> template<class PPFPs, class Tuple>
inline std::uint64_t calc_bitmask(PPFPs& fs, std::integral_constant<size_t,0>, const std::type_info& tinf, const Tuple& tup) { inline std::uint64_t calc_bitmask(PPFPs&, minus1l, const std::type_info&, const Tuple&) {
auto& f = get<0>(fs); return 0x00;
typedef typename util::rm_ref<decltype(f)>::type Fun;
typedef typename Fun::pattern_type pattern_type;
typedef detail::invoke_policy<pattern_type> policy;
return policy::can_invoke(tinf, tup) ? 0x01 : 0x00;
} }
template<class PPFPs, size_t N, class Tuple> template<class PPFPs, long N, class Tuple>
inline std::uint64_t calc_bitmask(PPFPs& fs, std::integral_constant<size_t,N>, const std::type_info& tinf, const Tuple& tup) { inline std::uint64_t calc_bitmask(PPFPs& fs, long_constant<N>, const std::type_info& tinf, const Tuple& tup) {
auto& f = get<N>(fs); auto& f = get<N>(fs);
typedef typename util::rm_ref<decltype(f)>::type Fun; typedef typename util::rm_ref<decltype(f)>::type Fun;
typedef typename Fun::pattern_type pattern_type; typedef typename Fun::pattern_type pattern_type;
typedef detail::invoke_policy<pattern_type> policy; typedef detail::invoke_policy<pattern_type> policy;
std::uint64_t result = policy::can_invoke(tinf, tup) ? (0x01 << N) : 0x00; std::uint64_t result = policy::can_invoke(tinf, tup) ? (0x01 << N) : 0x00;
return result | calc_bitmask(fs, std::integral_constant<size_t,N-1>(), tinf, tup); return result | calc_bitmask(fs, long_constant<N-1l>(), tinf, tup);
} }
template<typename T> template<typename T>
...@@ -557,12 +568,12 @@ struct mexpr_fwd_ { ...@@ -557,12 +568,12 @@ struct mexpr_fwd_ {
}; };
template<typename T> template<typename T>
struct mexpr_fwd_<false, const T&, T> { struct mexpr_fwd_<false,const T&,T> {
typedef std::reference_wrapper<const T> type; typedef std::reference_wrapper<const T> type;
}; };
template<typename T> template<typename T>
struct mexpr_fwd_<true, T&, T> { struct mexpr_fwd_<true,T&,T> {
typedef std::reference_wrapper<T> type; typedef std::reference_wrapper<T> type;
}; };
...@@ -594,12 +605,14 @@ inline const any_tuple& detach_if_needed(const any_tuple& tup, std::false_type) ...@@ -594,12 +605,14 @@ inline const any_tuple& detach_if_needed(const any_tuple& tup, std::false_type)
return tup; return tup;
} }
inline void* fetch_data(cow_ptr<abstract_tuple>& vals, std::true_type) { template<typename Ptr>
return vals->mutable_native_data(); inline void* fetch_native_data(Ptr& ptr, std::true_type) {
return ptr->mutable_native_data();
} }
inline const void* fetch_data(const cow_ptr<abstract_tuple>& vals, std::false_type) { template<typename Ptr>
return vals->native_data(); inline const void* fetch_native_data(const Ptr& ptr, std::false_type) {
return ptr->native_data();
} }
} } // namespace cppa::detail } } // namespace cppa::detail
...@@ -618,7 +631,12 @@ class match_expr { ...@@ -618,7 +631,12 @@ class match_expr {
static constexpr size_t num_cases = sizeof...(Cases); static constexpr size_t num_cases = sizeof...(Cases);
static constexpr bool has_manipulator = static constexpr bool has_manipulator =
util::tl_exists<cases_list, detail::is_manipulator_case>::value; util::tl_exists<cases_list,detail::is_manipulator_case>::value;
typedef detail::long_constant<static_cast<long>(num_cases)-1l>
idx_token_type;
static constexpr idx_token_type idx_token = idx_token_type{};
template<typename... Args> template<typename... Args>
match_expr(Args&&... args) : m_cases(std::forward<Args>(args)...) { match_expr(Args&&... args) : m_cases(std::forward<Args>(args)...) {
...@@ -653,7 +671,7 @@ class match_expr { ...@@ -653,7 +671,7 @@ class match_expr {
return bitmask != 0; return bitmask != 0;
} }
return can_unroll_expr(m_cases, return can_unroll_expr(m_cases,
std::integral_constant<size_t,num_cases-1>(), idx_token,
*type_token, *type_token,
tup); tup);
} }
...@@ -674,7 +692,7 @@ class match_expr { ...@@ -674,7 +692,7 @@ class match_expr {
template<typename... Args> template<typename... Args>
bool operator()(Args&&... args) { bool operator()(Args&&... args) {
typedef detail::tdata< typedef detail::tdata<
typename detail::mexpr_fwd<has_manipulator, Args>::type...> typename detail::mexpr_fwd<has_manipulator,Args>::type...>
tuple_type; tuple_type;
// applies implicit conversions etc // applies implicit conversions etc
tuple_type tup{std::forward<Args>(args)...}; tuple_type tup{std::forward<Args>(args)...};
...@@ -697,18 +715,20 @@ class match_expr { ...@@ -697,18 +715,20 @@ class match_expr {
auto impl_type = detail::statically_typed; auto impl_type = detail::statically_typed;
ptr_type ptr_arg = nullptr; ptr_type ptr_arg = nullptr;
bool invoke_result = true;
return unroll_expr(m_cases, bool unroll_result = unroll_expr(m_cases,
bitmask, invoke_result,
std::integral_constant<size_t,num_cases-1>(), bitmask,
type_token, idx_token,
impl_type, type_token,
ptr_arg, impl_type,
static_cast<ref_type>(tup)); ptr_arg,
static_cast<ref_type>(tup));
return unroll_result && invoke_result;
} }
template<class... OtherCases> template<class... OtherCases>
match_expr<Cases..., OtherCases...> match_expr<Cases...,OtherCases...>
or_else(const match_expr<OtherCases...>& other) const { or_else(const match_expr<OtherCases...>& other) const {
detail::tdata<ge_reference_wrapper<Cases>..., detail::tdata<ge_reference_wrapper<Cases>...,
ge_reference_wrapper<OtherCases>... > all_cases; ge_reference_wrapper<OtherCases>... > all_cases;
...@@ -752,9 +772,9 @@ class match_expr { ...@@ -752,9 +772,9 @@ class match_expr {
static constexpr size_t cache_size = 10; static constexpr size_t cache_size = 10;
typedef std::pair<const std::type_info*, std::uint64_t> cache_element; typedef std::pair<const std::type_info*,std::uint64_t> cache_element;
util::fixed_vector<cache_element, cache_size> m_cache; util::fixed_vector<cache_element,cache_size> m_cache;
// ring buffer like access to m_cache // ring buffer like access to m_cache
size_t m_cache_begin; size_t m_cache_begin;
...@@ -788,7 +808,7 @@ class match_expr { ...@@ -788,7 +808,7 @@ class match_expr {
if (m_cache_end == m_cache_begin) advance_(m_cache_begin); if (m_cache_end == m_cache_begin) advance_(m_cache_begin);
m_cache[i].first = type_token; m_cache[i].first = type_token;
m_cache[i].second = calc_bitmask(m_cases, m_cache[i].second = calc_bitmask(m_cases,
std::integral_constant<size_t,num_cases-1>(), idx_token,
*type_token, *type_token,
value); value);
} }
...@@ -805,19 +825,23 @@ class match_expr { ...@@ -805,19 +825,23 @@ class match_expr {
template<class Tuple> template<class Tuple>
bool invoke_impl(Tuple& tup) { bool invoke_impl(Tuple& tup) {
std::integral_constant<bool,has_manipulator> mutator_token; std::integral_constant<bool,has_manipulator> mutator_token;
// returns either a reference or a new object
decltype(detail::detach_if_needed(tup, mutator_token)) tref = detail::detach_if_needed(tup, mutator_token); decltype(detail::detach_if_needed(tup, mutator_token)) tref = detail::detach_if_needed(tup, mutator_token);
auto& vals = tref.vals(); auto& vals = tref.vals();
auto ndp = fetch_data(vals, mutator_token); auto ndp = fetch_native_data(vals, mutator_token);
auto token_ptr = vals->type_token(); auto token_ptr = vals->type_token();
auto bitmask = get_cache_entry(token_ptr, *vals); auto bitmask = get_cache_entry(token_ptr, *vals);
auto impl_type = vals->impl_type(); auto impl_type = vals->impl_type();
return unroll_expr(m_cases, bool invoke_result = true; // maybe set to false by an invoked functor
bitmask, bool unroll_result = unroll_expr(m_cases,
std::integral_constant<size_t,num_cases-1>(), invoke_result,
*token_ptr, bitmask,
impl_type, idx_token,
ndp, *token_ptr,
*vals); impl_type,
ndp,
*vals);
return invoke_result && unroll_result;
} }
}; };
...@@ -831,8 +855,8 @@ struct match_expr_from_type_list<util::type_list<Args...> > { ...@@ -831,8 +855,8 @@ struct match_expr_from_type_list<util::type_list<Args...> > {
}; };
template<typename... Lhs, typename... Rhs> template<typename... Lhs, typename... Rhs>
inline match_expr<Lhs..., Rhs...> operator,(const match_expr<Lhs...>& lhs, inline match_expr<Lhs...,Rhs...> operator,(const match_expr<Lhs...>& lhs,
const match_expr<Rhs...>& rhs) { const match_expr<Rhs...>& rhs) {
return lhs.or_else(rhs); return lhs.or_else(rhs);
} }
...@@ -887,7 +911,7 @@ struct match_expr_concat_impl { ...@@ -887,7 +911,7 @@ struct match_expr_concat_impl {
>::type >::type
combined_type; combined_type;
auto lvoid = []() { }; auto lvoid = []() { };
typedef detail::default_behavior_impl<combined_type, decltype(lvoid)> typedef detail::default_behavior_impl<combined_type,decltype(lvoid)>
impl_type; impl_type;
detail::collect_tdata(all_cases, arg0.cases(), args.cases()...); detail::collect_tdata(all_cases, arg0.cases(), args.cases()...);
return new impl_type(all_cases, util::duration{}, lvoid); return new impl_type(all_cases, util::duration{}, lvoid);
...@@ -900,7 +924,7 @@ struct match_expr_concat_impl<true> { ...@@ -900,7 +924,7 @@ struct match_expr_concat_impl<true> {
template<class TData, class Token, typename F> template<class TData, class Token, typename F>
static detail::behavior_impl* __(const TData& data, Token, const timeout_definition<F>& arg0) { static detail::behavior_impl* __(const TData& data, Token, const timeout_definition<F>& arg0) {
typedef typename match_expr_from_type_list<Token>::type combined_type; typedef typename match_expr_from_type_list<Token>::type combined_type;
typedef detail::default_behavior_impl<combined_type, F> impl_type; typedef detail::default_behavior_impl<combined_type,F> impl_type;
return new impl_type(data, arg0); return new impl_type(data, arg0);
} }
...@@ -925,7 +949,7 @@ struct match_expr_concat_impl<true> { ...@@ -925,7 +949,7 @@ struct match_expr_concat_impl<true> {
template<typename F> template<typename F>
static detail::behavior_impl* _(const timeout_definition<F>& arg0) { static detail::behavior_impl* _(const timeout_definition<F>& arg0) {
typedef detail::default_behavior_impl<detail::dummy_match_expr, F> impl_type; typedef detail::default_behavior_impl<detail::dummy_match_expr,F> impl_type;
return new impl_type(detail::dummy_match_expr{}, arg0); return new impl_type(detail::dummy_match_expr{}, arg0);
} }
......
...@@ -136,7 +136,12 @@ class message_future { ...@@ -136,7 +136,12 @@ class message_future {
template<typename F> template<typename F>
behavior bhvr_from_fun(F fun) { behavior bhvr_from_fun(F fun) {
auto handle_sync_failure = [] { self->handle_sync_failure(); }; auto handle_sync_failure = []() -> bool {
self->handle_sync_failure();
return false; // do not treat this as a match to cause a
// continuation to be invoked only in case
// `fun` was invoked
};
return { return {
on(atom("EXITED"), any_vals) >> handle_sync_failure, on(atom("EXITED"), any_vals) >> handle_sync_failure,
on(atom("TIMEOUT")) >> handle_sync_failure, on(atom("TIMEOUT")) >> handle_sync_failure,
......
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