Commit fd02800e authored by Dominik Charousset's avatar Dominik Charousset

Fix behavior_impl on MSVC

parent 8de9e2ee
...@@ -36,6 +36,11 @@ decltype(auto) apply_args(F& f, detail::int_list<Is...>, Tuple& tup) { ...@@ -36,6 +36,11 @@ decltype(auto) apply_args(F& f, detail::int_list<Is...>, Tuple& tup) {
return f(get<Is>(tup)...); return f(get<Is>(tup)...);
} }
template <class F, size_t... Is, class Tuple>
decltype(auto) apply_args(F& f, std::index_sequence<Is...>, Tuple& tup) {
return f(get<Is>(tup)...);
}
template <class F, long... Is, class Tuple> template <class F, long... Is, class Tuple>
decltype(auto) apply_args(F& f, Tuple& tup) { decltype(auto) apply_args(F& f, Tuple& tup) {
auto token = get_indices(tup); auto token = get_indices(tup);
......
...@@ -98,31 +98,30 @@ struct with_generic_timeout<true, std::tuple<Ts...>> { ...@@ -98,31 +98,30 @@ struct with_generic_timeout<true, std::tuple<Ts...>> {
std::tuple>::type; std::tuple>::type;
}; };
template <class Tuple> struct dummy_timeout_definition {
class default_behavior_impl; timespan timeout = infinite;
template <class... Ts>
class default_behavior_impl<std::tuple<Ts...>> : public behavior_impl {
public:
using tuple_type = std::tuple<Ts...>;
using back_type = typename tl_back<type_list<Ts...>>::type; constexpr void handler() {
// nop
}
};
static constexpr bool has_timeout = is_timeout_definition<back_type>::value; template <class Tuple, class TimeoutDefinition = dummy_timeout_definition>
class default_behavior_impl;
static constexpr size_t num_cases = sizeof...(Ts) - (has_timeout ? 1 : 0); template <class... Ts, class TimeoutDefinition>
class default_behavior_impl<std::tuple<Ts...>, TimeoutDefinition>
: public behavior_impl {
public:
using super = behavior_impl;
default_behavior_impl(tuple_type&& tup) : cases_(std::move(tup)) { using tuple_type = std::tuple<Ts...>;
if constexpr (has_timeout) {
this->timeout_ = std::get<num_cases>(cases_).timeout;
}
}
template <class... Us> default_behavior_impl(tuple_type&& tup, TimeoutDefinition timeout_definition)
default_behavior_impl(Us&&... xs) : cases_(std::forward<Us>(xs)...) { : super(timeout_definition.timeout),
if constexpr (has_timeout) { cases_(std::move(tup)),
this->timeout_ = std::get<num_cases>(cases_).timeout; timeout_definition_(std::move(timeout_definition)) {
} // nop
} }
virtual match_result invoke(detail::invoke_result_visitor& f, virtual match_result invoke(detail::invoke_result_visitor& f,
...@@ -136,22 +135,20 @@ public: ...@@ -136,22 +135,20 @@ public:
auto result = match_result::no_match; auto result = match_result::no_match;
auto dispatch = [&](auto& fun) { auto dispatch = [&](auto& fun) {
using fun_type = std::decay_t<decltype(fun)>; using fun_type = std::decay_t<decltype(fun)>;
if constexpr (!is_timeout_definition<fun_type>::value) { using trait = get_callable_trait_t<fun_type>;
using trait = get_callable_trait_t<fun_type>; auto arg_types = to_type_id_list<typename trait::decayed_arg_types>();
auto arg_types = to_type_id_list<typename trait::decayed_arg_types>(); if (arg_types == msg.types()) {
if (arg_types == msg.types()) { typename trait::message_view_type xs{msg};
typename trait::message_view_type xs{msg}; using fun_result = decltype(detail::apply_args(fun, xs));
using fun_result = decltype(detail::apply_args(fun, xs)); if constexpr (std::is_same<void, fun_result>::value) {
if constexpr (std::is_same<void, fun_result>::value) { detail::apply_args(fun, xs);
detail::apply_args(fun, xs); result = f.visit(unit) ? match_result::match : match_result::skip;
result = f.visit(unit) ? match_result::match : match_result::skip; } else {
} else { auto invoke_res = detail::apply_args(fun, xs);
auto invoke_res = detail::apply_args(fun, xs); result = f.visit(invoke_res) ? match_result::match
result = f.visit(invoke_res) ? match_result::match : match_result::skip;
: match_result::skip;
}
return true;
} }
return true;
} }
return false; return false;
}; };
...@@ -160,20 +157,24 @@ public: ...@@ -160,20 +157,24 @@ public:
} }
void handle_timeout() override { void handle_timeout() override {
if constexpr (has_timeout) { timeout_definition_.handler();
std::get<num_cases>(cases_).handler();
}
} }
private: private:
tuple_type cases_; tuple_type cases_;
TimeoutDefinition timeout_definition_;
}; };
template <class Tuple> template <class TimeoutDefinition>
struct behavior_factory { struct behavior_factory_t {
TimeoutDefinition& tdef;
template <class... Ts> template <class... Ts>
typename behavior_impl::pointer operator()(Ts&&... xs) const { auto operator()(Ts&... xs) {
return make_counted<default_behavior_impl<Tuple>>(std::forward<Ts>(xs)...); using impl = default_behavior_impl<std::tuple<Ts...>, TimeoutDefinition>;
return make_counted<impl>(std::make_tuple(std::move(xs)...),
std::move(tdef));
} }
}; };
...@@ -183,10 +184,18 @@ struct make_behavior_t { ...@@ -183,10 +184,18 @@ struct make_behavior_t {
} }
template <class... Ts> template <class... Ts>
intrusive_ptr<default_behavior_impl<std::tuple<Ts...>>> auto operator()(Ts... xs) const {
operator()(Ts... xs) const { if constexpr ((is_timeout_definition<Ts>::value || ...)) {
using type = default_behavior_impl<std::tuple<Ts...>>; auto args = std::tie(xs...);
return make_counted<type>(std::move(xs)...); auto& tdef = std::get<sizeof...(Ts) - 1>(args);
behavior_factory_t<std::decay_t<decltype(tdef)>> f{tdef};
std::make_index_sequence<sizeof...(Ts) - 1> indexes;
return detail::apply_args(f, indexes, args);
} else {
using type = default_behavior_impl<std::tuple<Ts...>>;
dummy_timeout_definition dummy;
return make_counted<type>(std::make_tuple(std::move(xs)...), dummy);
}
} }
}; };
......
...@@ -32,6 +32,9 @@ ...@@ -32,6 +32,9 @@
#ifdef CAF_CLANG #ifdef CAF_CLANG
# pragma clang diagnostic push # pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wc99-extensions" # pragma clang diagnostic ignored "-Wc99-extensions"
#elif defined(CAF_MSVC)
# pragma warning(push)
# pragma warning(disable : 4200)
#endif #endif
namespace caf::detail { namespace caf::detail {
...@@ -152,4 +155,6 @@ void message_data_init(byte* storage, T&& x, Ts&&... xs) { ...@@ -152,4 +155,6 @@ void message_data_init(byte* storage, T&& x, Ts&&... xs) {
#ifdef CAF_CLANG #ifdef CAF_CLANG
# pragma clang diagnostic pop # pragma clang diagnostic pop
#elif defined(MSVC)
# pragma warning(pop)
#endif #endif
...@@ -230,8 +230,10 @@ public: ...@@ -230,8 +230,10 @@ public:
private: private:
typed_behavior() = default; typed_behavior() = default;
template <class... Ts> template <class... Ts, class TimeoutDefinition>
void set(intrusive_ptr<detail::default_behavior_impl<std::tuple<Ts...>>> bp) { void set(intrusive_ptr<
detail::default_behavior_impl<std::tuple<Ts...>, TimeoutDefinition>>
bp) {
using found_signatures = detail::type_list<deduce_mpi_t<Ts>...>; using found_signatures = detail::type_list<deduce_mpi_t<Ts>...>;
using m = interface_mismatch_t<found_signatures, signatures>; using m = interface_mismatch_t<found_signatures, signatures>;
// trigger static assert on mismatch // trigger static assert on mismatch
......
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