Commit 35c558a9 authored by Dominik Charousset's avatar Dominik Charousset

Fix behavior of skip_message when using or_else

parent 02bc07c8
......@@ -21,6 +21,7 @@
#define CAF_DETAIL_BEHAVIOR_IMPL_HPP
#include <tuple>
#include <iterator>
#include <type_traits>
#include "caf/none.hpp"
......@@ -70,10 +71,10 @@ public:
behavior_impl(duration tout = duration{});
virtual bhvr_invoke_result invoke(message&);
bhvr_invoke_result invoke(message&);
inline bhvr_invoke_result invoke(message&& arg) {
message tmp(std::move(arg));
inline bhvr_invoke_result invoke(message&& x) {
message tmp(std::move(x));
return invoke(tmp);
}
......@@ -87,10 +88,24 @@ public:
pointer or_else(const pointer& other);
using iterator = match_case_info*;
inline iterator begin() {
return begin_;
}
inline iterator end() {
return end_;
}
inline size_t size() const {
return std::distance(begin_, end_);
}
protected:
iterator begin_;
iterator end_;
duration timeout_;
match_case_info* begin_;
match_case_info* end_;
};
template <size_t Pos, size_t Size>
......
......@@ -28,37 +28,32 @@ namespace {
class combinator final : public behavior_impl {
public:
bhvr_invoke_result invoke(message& arg) {
auto res = first->invoke(arg);
return res ? res : second->invoke(arg);
void handle_timeout() override {
// the second behavior overrides the timeout handling of first behavior
return second_->handle_timeout();
}
void handle_timeout() {
// the second behavior overrides the timeout handling of
// first behavior
return second->handle_timeout();
pointer copy(const generic_timeout_definition& tdef) const override {
return new combinator(first_, second_->copy(tdef));
}
pointer copy(const generic_timeout_definition& tdef) const {
return new combinator(first, second->copy(tdef));
}
combinator(const pointer& p0, const pointer& p1)
: behavior_impl(p1->timeout()),
first(p0),
second(p1) {
// nop
}
protected:
match_case** get_cases(size_t&) {
// never called
return nullptr;
combinator(const pointer& x, const pointer& y)
: behavior_impl(y->timeout()),
first_(x),
second_(y) {
cases_.reserve(x->size() + y->size());
for (auto mci : *x)
cases_.push_back(mci);
for (auto mci : *y)
cases_.push_back(mci);
begin_ = &cases_[0];
end_ = begin_ + cases_.size();
}
private:
pointer first;
pointer second;
std::vector<match_case_info> cases_;
pointer first_;
pointer second_;
};
} // namespace <anonymous>
......@@ -67,22 +62,17 @@ behavior_impl::~behavior_impl() {
// nop
}
behavior_impl::behavior_impl(duration tout)
: timeout_(tout),
begin_(nullptr),
end_(nullptr) {
behavior_impl::behavior_impl(duration tout) : timeout_(tout) {
// nop
}
bhvr_invoke_result behavior_impl::invoke(message& msg) {
auto msg_token = msg.type_token();
bhvr_invoke_result res;
for (auto i = begin_; i != end_; ++i) {
for (auto i = begin_; i != end_; ++i)
if ((i->has_wildcard || i->type_token == msg_token)
&& i->ptr->invoke(res, msg) != match_case::no_match) {
&& i->ptr->invoke(res, msg) != match_case::no_match)
return res;
}
}
return none;
}
......
......@@ -95,4 +95,32 @@ CAF_TEST(composition3) {
);
}
CAF_TEST(composition4) {
auto impl = [](event_based_actor* self, const actor& buddy) {
return
message_handler{
[=](int i) -> skip_message_t {
self->send(buddy, "skip: " + std::to_string(i));
return skip_message();
}
}.or_else(message_handler{
[=](int i) {
self->send(buddy, "handle: " + std::to_string(i));
}
});
};
scoped_actor self;
auto testee = spawn(impl, self);
for (int i = 0; i < 3; ++i)
self->send(testee, i);
int i = 0;
self->receive_for(i, 3)(
[&](const std::string& str) {
CAF_CHECK_EQUAL(str, "skip: " + std::to_string(i));
}
);
self->send_exit(testee, exit_reason::user_shutdown);
self->await_all_other_actors_done();
}
CAF_TEST_FIXTURE_SCOPE_END()
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