Commit ca3686a7 authored by Dominik Charousset's avatar Dominik Charousset

Add diagnostic for partial response handle support

parent 9a414758
...@@ -685,6 +685,70 @@ public: ...@@ -685,6 +685,70 @@ public:
static constexpr bool value = sfinae_type::value; static constexpr bool value = sfinae_type::value;
}; };
template <class T>
class has_call_error_handler {
private:
template <class Actor>
static auto sfinae(Actor* self)
-> decltype(self->call_error_handler(std::declval<error&>()),
std::true_type());
template <class U>
static auto sfinae(...) -> std::false_type;
using sfinae_type = decltype(sfinae<T>(nullptr));
public:
static constexpr bool value = sfinae_type::value;
};
template <class T>
constexpr bool has_call_error_handler_v = has_call_error_handler<T>::value;
template <class T>
class has_add_awaited_response_handler {
private:
template <class Actor>
static auto sfinae(Actor* self)
-> decltype(self->add_awaited_response_handler(std::declval<message_id>(),
std::declval<behavior&>()),
std::true_type());
template <class U>
static auto sfinae(...) -> std::false_type;
using sfinae_type = decltype(sfinae<T>(nullptr));
public:
static constexpr bool value = sfinae_type::value;
};
template <class T>
constexpr bool has_add_awaited_response_handler_v
= has_add_awaited_response_handler<T>::value;
template <class T>
class has_add_multiplexed_response_handler {
private:
template <class Actor>
static auto sfinae(Actor* self)
-> decltype(self->add_multiplexed_response_handler(
std::declval<message_id>(), std::declval<behavior&>()),
std::true_type());
template <class U>
static auto sfinae(...) -> std::false_type;
using sfinae_type = decltype(sfinae<T>(nullptr));
public:
static constexpr bool value = sfinae_type::value;
};
template <class T>
constexpr bool has_add_multiplexed_response_handler_v
= has_add_multiplexed_response_handler<T>::value;
/// Checks whether T behaves like `std::vector`, `std::list`, or `std::set`. /// Checks whether T behaves like `std::vector`, `std::list`, or `std::set`.
template <class T> template <class T>
struct is_list_like { struct is_list_like {
......
...@@ -68,11 +68,13 @@ public: ...@@ -68,11 +68,13 @@ public:
// -- non-blocking API ------------------------------------------------------- // -- non-blocking API -------------------------------------------------------
template <class T = traits, class F = none_t, class OnError = none_t, template <class T = traits, class F, class OnError>
class = detail::enable_if_t<T::is_non_blocking>> detail::enable_if_t<T::is_non_blocking> await(F f, OnError g) const {
void await(F f, OnError g) const { static_assert(detail::has_add_awaited_response_handler_v<ActorType>,
static_assert(detail::is_callable<F>::value, "F must provide a single, " "this actor type does not support awaiting responses, "
"non-template operator()"); "try using .then instead");
static_assert(detail::is_callable<F>::value,
"F must provide a single, non-template operator()");
static_assert(detail::is_callable_with<OnError, error&>::value, static_assert(detail::is_callable_with<OnError, error&>::value,
"OnError must provide an operator() that takes a caf::error"); "OnError must provide an operator() that takes a caf::error");
using result_type = typename detail::get_callable_trait<F>::result_type; using result_type = typename detail::get_callable_trait<F>::result_type;
...@@ -83,18 +85,21 @@ public: ...@@ -83,18 +85,21 @@ public:
policy_.await(self_, std::move(f), std::move(g)); policy_.await(self_, std::move(f), std::move(g));
} }
template <class T = traits, class F = none_t, template <class T = traits, class F>
class = detail::enable_if_t<T::is_non_blocking>> detail::enable_if_t<detail::has_call_error_handler_v<ActorType> //
void await(F f) const { && T::is_non_blocking>
await(F f) const {
auto self = self_; auto self = self_;
await(std::move(f), [self](error& err) { self->call_error_handler(err); }); await(std::move(f), [self](error& err) { self->call_error_handler(err); });
} }
template <class T = traits, class F = none_t, class OnError = none_t, template <class T = traits, class F, class OnError>
class = detail::enable_if_t<T::is_non_blocking>> detail::enable_if_t<T::is_non_blocking> then(F f, OnError g) const {
void then(F f, OnError g) const { static_assert(detail::has_add_multiplexed_response_handler_v<ActorType>,
static_assert(detail::is_callable<F>::value, "F must provide a single, " "this actor type does not support multiplexed responses, "
"non-template operator()"); "try using .await instead");
static_assert(detail::is_callable<F>::value,
"F must provide a single, non-template operator()");
static_assert(detail::is_callable_with<OnError, error&>::value, static_assert(detail::is_callable_with<OnError, error&>::value,
"OnError must provide an operator() that takes a caf::error"); "OnError must provide an operator() that takes a caf::error");
using result_type = typename detail::get_callable_trait<F>::result_type; using result_type = typename detail::get_callable_trait<F>::result_type;
...@@ -105,9 +110,10 @@ public: ...@@ -105,9 +110,10 @@ public:
policy_.then(self_, std::move(f), std::move(g)); policy_.then(self_, std::move(f), std::move(g));
} }
template <class T = traits, class F = none_t, template <class T = traits, class F>
class = detail::enable_if_t<T::is_non_blocking>> detail::enable_if_t<detail::has_call_error_handler_v<ActorType> //
void then(F f) const { && T::is_non_blocking>
then(F f) const {
auto self = self_; auto self = self_;
then(std::move(f), [self](error& err) { self->call_error_handler(err); }); then(std::move(f), [self](error& err) { self->call_error_handler(err); });
} }
......
...@@ -741,7 +741,7 @@ invoke_message_result scheduled_actor::consume(mailbox_element& x) { ...@@ -741,7 +741,7 @@ invoke_message_result scheduled_actor::consume(mailbox_element& x) {
auto bhvr = std::move(mrh->second); auto bhvr = std::move(mrh->second);
multiplexed_responses_.erase(mrh); multiplexed_responses_.erase(mrh);
if (!invoke(this, bhvr, x)) { if (!invoke(this, bhvr, x)) {
CAF_LOG_DEBUG("got unexpected_response, invoke unexpected_response"); CAF_LOG_DEBUG("got unexpected_response");
auto msg = make_message( auto msg = make_message(
make_error(sec::unexpected_response, std::move(x.payload))); make_error(sec::unexpected_response, std::move(x.payload)));
bhvr(msg); bhvr(msg);
......
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