Commit a4f60453 authored by Dominik Charousset's avatar Dominik Charousset

fixed timeout handling in become() API, fixes #116

parent ec8cc487
......@@ -122,14 +122,30 @@ class behavior_stack_based_impl : public single_timeout<Base, Subtype> {
return m_bhvr_stack;
}
/**************************************************************************
* extended timeout handling (handle_timeout mem fun) *
**************************************************************************/
void handle_timeout(behavior& bhvr, std::uint32_t timeout_id) {
if (this->is_active_timeout(timeout_id)) {
this->reset_timeout();
bhvr.handle_timeout();
// request next timeout if behavior stack is not empty
// and timeout handler did not set a new timeout, e.g.,
// by calling become()
if (!this->has_active_timeout() && has_behavior()) {
this->request_timeout(get_behavior().timeout());
}
}
}
private:
void do_become(behavior_type bhvr, bool discard_old) {
if (discard_old) this->m_bhvr_stack.pop_async_back();
this->reset_timeout();
if (bhvr.timeout().valid()) {
this->request_timeout(bhvr.timeout());
}
// since we know we extend single_timeout, we can be sure
// request_timeout simply resets the timeout when it's invalid
this->request_timeout(bhvr.timeout());
this->m_bhvr_stack.push_back(std::move(unbox(bhvr)));
}
......
......@@ -79,15 +79,12 @@ class single_timeout : public Base {
return waits_for_timeout(tid);
}
inline void reset_timeout() {
m_has_timeout = false;
inline bool has_active_timeout() const {
return m_has_timeout;
}
inline void handle_timeout(behavior& bhvr, std::uint32_t timeout_id) {
if (timeout_id == m_timeout_id) {
m_has_timeout = false;
bhvr.handle_timeout();
}
inline void reset_timeout() {
m_has_timeout = false;
}
protected:
......
......@@ -62,7 +62,8 @@ actor spawn_event_testee2(actor parent) {
behavior wait4timeout(int remaining) {
CPPA_LOG_TRACE(CPPA_ARG(remaining));
return {
after(chrono::milliseconds(50)) >> [=] {
after(chrono::milliseconds(1)) >> [=] {
CPPA_PRINT(CPPA_ARG(remaining));
if (remaining == 1) {
send(parent, atom("t2done"));
quit();
......@@ -887,13 +888,32 @@ void test_spawn() {
CPPA_CHECKPOINT();
spawn<high_priority_testee_class, priority_aware>();
self->await_all_other_actors_done();
// don't try this at home, kids
// test sending message to self via scoped_actor
self->send(self, atom("check"));
self->receive (
on(atom("check")) >> [] {
CPPA_CHECKPOINT();
}
);
CPPA_CHECKPOINT();
CPPA_PRINT("check whether timeouts trigger more than once");
auto counter = make_shared<int>(0);
auto sleeper = self->spawn<monitored>([=](event_based_actor* s) {
return after(std::chrono::milliseconds(1)) >> [=] {
CPPA_PRINT("received timeout #" << (*counter + 1));
if (++*counter > 3) {
CPPA_CHECKPOINT();
s->quit();
}
};
});
self->receive(
[&](const down_msg& msg) {
CPPA_CHECK_EQUAL(msg.source, sleeper);
CPPA_CHECK_EQUAL(msg.reason, exit_reason::normal);
}
);
CPPA_CHECKPOINT();
}
int main() {
......
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