Commit e56200ac authored by Dominik Charousset's avatar Dominik Charousset

divide sync errors in timeouts and unexpected

this patch adds `(on_)handle_sync_timeout` to `local_actor`
parent c2f9b167
...@@ -58,12 +58,16 @@ static constexpr std::uint32_t unhandled_exception = 0x00002; ...@@ -58,12 +58,16 @@ static constexpr std::uint32_t unhandled_exception = 0x00002;
static constexpr std::uint32_t unallowed_function_call = 0x00003; static constexpr std::uint32_t unallowed_function_call = 0x00003;
/** /**
* @brief Indicates that a synchronous message timed out * @brief Indicates that the actor received an unexpected
* or the receiving actor didn't handle the message properly * synchronous reply message.
* and the killed actor did not handle sync failures manually.
*/ */
static constexpr std::uint32_t unhandled_sync_failure = 0x00004; static constexpr std::uint32_t unhandled_sync_failure = 0x00004;
/**
* @brief Indicates that a synchronous message timed out.
*/
static constexpr std::uint32_t unhandled_sync_timeout = 0x00005;
/** /**
* @brief Indicates that an actor finishied execution * @brief Indicates that an actor finishied execution
* because a connection to a remote link was * because a connection to a remote link was
......
...@@ -355,6 +355,50 @@ class local_actor : public memory_cached_mixin<actor> { ...@@ -355,6 +355,50 @@ class local_actor : public memory_cached_mixin<actor> {
*/ */
virtual void exec_behavior_stack(); virtual void exec_behavior_stack();
/**
* @brief Creates a {@link response_handle} to allow actors to response
* to a request later on.
*/
response_handle make_response_handle();
/**
* @brief Sets the handler for unexpected synchronous response messages.
*/
inline void on_sync_timeout(std::function<void()> fun) {
m_sync_timeout_handler = std::move(fun);
}
/**
* @brief Sets the handler for @p timed_sync_send timeout messages.
*/
inline void on_sync_failure(std::function<void()> fun) {
m_sync_failure_handler = std::move(fun);
}
/**
* @brief Calls <tt>on_sync_timeout(fun); on_sync_failure(fun);</tt>.
*/
inline void on_sync_timeout_or_failure(std::function<void()> fun) {
on_sync_timeout(fun);
on_sync_failure(fun);
}
/**
* @brief Invokes the handler for synchronous timeouts.
*/
inline void handle_sync_timeout() {
if (m_sync_timeout_handler) m_sync_timeout_handler();
else quit(exit_reason::unhandled_sync_timeout);
}
/**
* @brief Invokes the handler for unexpected synchronous response messages.
*/
inline void handle_sync_failure() {
if (m_sync_failure_handler) m_sync_failure_handler();
else quit(exit_reason::unhandled_sync_failure);
}
// library-internal members and member functions that shall // library-internal members and member functions that shall
// not appear in the documentation // not appear in the documentation
...@@ -442,21 +486,6 @@ class local_actor : public memory_cached_mixin<actor> { ...@@ -442,21 +486,6 @@ class local_actor : public memory_cached_mixin<actor> {
virtual void become_waiting_for(behavior&&, message_id_t) = 0; virtual void become_waiting_for(behavior&&, message_id_t) = 0;
/**
* @brief Creates a {@link response_handle} to allow actors to response
* to a request later on.
*/
response_handle make_response_handle();
inline void on_sync_failure(std::function<void()> fun) {
m_sync_failure_handler = std::move(fun);
}
inline void handle_sync_failure() {
if (m_sync_failure_handler) m_sync_failure_handler();
else quit(exit_reason::unhandled_sync_failure);
}
inline detail::behavior_stack& bhvr_stack() { inline detail::behavior_stack& bhvr_stack() {
return m_bhvr_stack; return m_bhvr_stack;
} }
...@@ -492,6 +521,7 @@ class local_actor : public memory_cached_mixin<actor> { ...@@ -492,6 +521,7 @@ class local_actor : public memory_cached_mixin<actor> {
private: private:
std::function<void()> m_sync_failure_handler; std::function<void()> m_sync_failure_handler;
std::function<void()> m_sync_timeout_handler;
# endif // CPPA_DOCUMENTATION # endif // CPPA_DOCUMENTATION
......
...@@ -95,7 +95,7 @@ class message_future { ...@@ -95,7 +95,7 @@ class message_future {
/** /**
* @brief Sets @p fun as event-handler for the response message, calls * @brief Sets @p fun as event-handler for the response message, calls
* <tt>self->handle_sync_failure()</tt> if the response message * <tt>self->handle_sync_failure()</tt> if the response message
* is an 'EXITED', 'TIMEOUT', or 'VOID' message. * is an 'EXITED' or 'VOID' message.
*/ */
template<typename F> template<typename F>
typename std::enable_if<util::is_callable<F>::value,continue_helper>::type typename std::enable_if<util::is_callable<F>::value,continue_helper>::type
...@@ -108,7 +108,7 @@ class message_future { ...@@ -108,7 +108,7 @@ class message_future {
/** /**
* @brief Blocks until the response arrives and then executes @p @p fun, * @brief Blocks until the response arrives and then executes @p @p fun,
* calls <tt>self->handle_sync_failure()</tt> if the response * calls <tt>self->handle_sync_failure()</tt> if the response
* message is an 'EXITED', 'TIMEOUT', or 'VOID' message. * message is an 'EXITED' or 'VOID' message.
*/ */
template<typename F> template<typename F>
typename std::enable_if<util::is_callable<F>::value>::type await(F fun) { typename std::enable_if<util::is_callable<F>::value>::type await(F fun) {
...@@ -142,9 +142,13 @@ class message_future { ...@@ -142,9 +142,13 @@ class message_future {
// continuation to be invoked only in case // continuation to be invoked only in case
// `fun` was invoked // `fun` was invoked
}; };
auto handle_sync_timeout = []() -> bool {
self->handle_sync_timeout();
return false;
};
return { return {
on(atom("EXITED"), any_vals) >> handle_sync_failure, on<atom("EXITED"), std::uint32_t>() >> handle_sync_failure,
on(atom("TIMEOUT")) >> handle_sync_failure, on(atom("TIMEOUT")) >> handle_sync_timeout,
on(atom("VOID")) >> handle_sync_failure, on(atom("VOID")) >> handle_sync_failure,
on(any_vals, arg_match) >> fun, on(any_vals, arg_match) >> fun,
others() >> handle_sync_failure others() >> handle_sync_failure
......
#include "test.hpp" #include "test.hpp"
#include "cppa/cppa.hpp" #include "cppa/cppa.hpp"
using namespace std;
using namespace cppa; using namespace cppa;
using namespace cppa::placeholders; using namespace cppa::placeholders;
...@@ -171,11 +172,13 @@ int main() { ...@@ -171,11 +172,13 @@ int main() {
// check wheter continuations are invoked correctly // check wheter continuations are invoked correctly
auto c = spawn<C>(); // replies only to 'gogo' messages auto c = spawn<C>(); // replies only to 'gogo' messages
// first test: sync error must occur, continuation must not be called // first test: sync error must occur, continuation must not be called
self->on_sync_failure(CPPA_CHECKPOINT_CB()); bool timeout_occured = false;
self->on_sync_timeout([&] { timeout_occured = true; });
timed_sync_send(c, std::chrono::milliseconds(500), atom("HiThere")) timed_sync_send(c, std::chrono::milliseconds(500), atom("HiThere"))
.then(CPPA_ERROR_CB("C replied to 'HiThere'!")) .then(CPPA_ERROR_CB("C replied to 'HiThere'!"))
.continue_with(CPPA_ERROR_CB("bad continuation")); .continue_with(CPPA_ERROR_CB("bad continuation"));
self->exec_behavior_stack(); self->exec_behavior_stack();
CPPA_CHECK_EQUAL(timeout_occured, true);
self->on_sync_failure(CPPA_UNEXPECTED_MSG_CB()); self->on_sync_failure(CPPA_UNEXPECTED_MSG_CB());
sync_send(c, atom("gogo")).then(CPPA_CHECKPOINT_CB()) sync_send(c, atom("gogo")).then(CPPA_CHECKPOINT_CB())
.continue_with(CPPA_CHECKPOINT_CB()); .continue_with(CPPA_CHECKPOINT_CB());
...@@ -183,7 +186,6 @@ int main() { ...@@ -183,7 +186,6 @@ int main() {
quit_actor(c, exit_reason::user_defined); quit_actor(c, exit_reason::user_defined);
await_all_others_done(); await_all_others_done();
CPPA_CHECKPOINT(); CPPA_CHECKPOINT();
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