Commit 3f2c5f7a authored by Dominik Charousset's avatar Dominik Charousset

Fix handling of on_exit() in event-based actors

This fixes an issue in the scheduler that prevents event-based actors from
setting a new behavior in on_exit().
parent dfcf808f
...@@ -68,7 +68,7 @@ class event_based_resume { ...@@ -68,7 +68,7 @@ class event_based_resume {
d->bhvr_stack().cleanup(); d->bhvr_stack().cleanup();
d->on_exit(); d->on_exit();
if (!d->bhvr_stack().empty()) { if (!d->bhvr_stack().empty()) {
CAF_LOG_DEBUG("on_exit did set a new behavior in on_exit"); CAF_LOG_DEBUG("on_exit did set a new behavior");
d->planned_exit_reason(exit_reason::not_exited); d->planned_exit_reason(exit_reason::not_exited);
return false; // on_exit did set a new behavior return false; // on_exit did set a new behavior
} }
...@@ -79,23 +79,30 @@ class event_based_resume { ...@@ -79,23 +79,30 @@ class event_based_resume {
} }
d->cleanup(rsn); d->cleanup(rsn);
return true; return true;
}; };
auto actor_done = [&] { auto actor_done = [&]() -> bool {
return d->bhvr_stack().empty() if (d->bhvr_stack().empty()
|| d->planned_exit_reason() != exit_reason::not_exited; || d->planned_exit_reason() != exit_reason::not_exited) {
return done_cb();
}
return false;
}; };
// actors without behavior or that have already defined // actors without behavior or that have already defined
// an exit reason must not be resumed // an exit reason must not be resumed
CAF_REQUIRE(!d->m_initialized || !actor_done()); CAF_REQUIRE(!d->m_initialized
|| (!d->bhvr_stack().empty()
&& !d->planned_exit_reason() != exit_reason::not_exited));
try { try {
if (!d->m_initialized) { if (!d->m_initialized) {
d->m_initialized = true; d->m_initialized = true;
auto bhvr = d->make_behavior(); auto bhvr = d->make_behavior();
if (bhvr) d->become(std::move(bhvr)); if (bhvr) {
// else: make_behavior() might have just called become() // make_behavior() did return a behavior instead of using become()
if (actor_done() && done_cb()) return resume_result::done; d->become(std::move(bhvr));
// else: enter resume loop }
if (actor_done()) {
return resume_result::done;
}
} }
// max_throughput = 0 means infinite // max_throughput = 0 means infinite
size_t increment = max_throughput == 0 ? 0 : 1; size_t increment = max_throughput == 0 ? 0 : 1;
...@@ -106,7 +113,7 @@ class event_based_resume { ...@@ -106,7 +113,7 @@ class event_based_resume {
auto ptr = d->next_message(); auto ptr = d->next_message();
if (ptr) { if (ptr) {
if (d->invoke_message(ptr)) { if (d->invoke_message(ptr)) {
if (actor_done() && done_cb()) { if (actor_done()) {
CAF_LOG_DEBUG("actor exited"); CAF_LOG_DEBUG("actor exited");
return resume_result::done; return resume_result::done;
} }
...@@ -114,7 +121,7 @@ class event_based_resume { ...@@ -114,7 +121,7 @@ class event_based_resume {
// handled, because the actor might have changed // handled, because the actor might have changed
// its behavior to match 'old' messages now // its behavior to match 'old' messages now
while (d->invoke_message_from_cache()) { while (d->invoke_message_from_cache()) {
if (actor_done() && done_cb()) { if (actor_done()) {
CAF_LOG_DEBUG("actor exited"); CAF_LOG_DEBUG("actor exited");
return resume_result::done; return resume_result::done;
} }
...@@ -161,7 +168,10 @@ class event_based_resume { ...@@ -161,7 +168,10 @@ class event_based_resume {
d->quit(exit_reason::unhandled_exception); d->quit(exit_reason::unhandled_exception);
} }
} }
done_cb(); if (!done_cb()) {
// actor has been "revived", try running it again later
return resumable::resume_later;
}
return resumable::done; return resumable::done;
} }
}; };
......
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