Commit d2d653e5 authored by Dominik Charousset's avatar Dominik Charousset

Fix behavior of skip_message when using or_else

parent b09795be
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define CAF_DETAIL_BEHAVIOR_IMPL_HPP #define CAF_DETAIL_BEHAVIOR_IMPL_HPP
#include <tuple> #include <tuple>
#include <iterator>
#include <type_traits> #include <type_traits>
#include "caf/none.hpp" #include "caf/none.hpp"
...@@ -70,10 +71,10 @@ public: ...@@ -70,10 +71,10 @@ public:
behavior_impl(duration tout = duration{}); behavior_impl(duration tout = duration{});
virtual bhvr_invoke_result invoke(message&); bhvr_invoke_result invoke(message&);
inline bhvr_invoke_result invoke(message&& arg) { inline bhvr_invoke_result invoke(message&& x) {
message tmp(std::move(arg)); message tmp(std::move(x));
return invoke(tmp); return invoke(tmp);
} }
...@@ -87,10 +88,24 @@ public: ...@@ -87,10 +88,24 @@ public:
pointer or_else(const pointer& other); 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: protected:
iterator begin_;
iterator end_;
duration timeout_; duration timeout_;
match_case_info* begin_;
match_case_info* end_;
}; };
template <size_t Pos, size_t Size> template <size_t Pos, size_t Size>
......
...@@ -28,37 +28,32 @@ namespace { ...@@ -28,37 +28,32 @@ namespace {
class combinator final : public behavior_impl { class combinator final : public behavior_impl {
public: public:
bhvr_invoke_result invoke(message& arg) { void handle_timeout() override {
auto res = first->invoke(arg); // the second behavior overrides the timeout handling of first behavior
return res ? res : second->invoke(arg); return second_->handle_timeout();
} }
void handle_timeout() { pointer copy(const generic_timeout_definition& tdef) const override {
// the second behavior overrides the timeout handling of return new combinator(first_, second_->copy(tdef));
// first behavior
return second->handle_timeout();
} }
pointer copy(const generic_timeout_definition& tdef) const { combinator(const pointer& x, const pointer& y)
return new combinator(first, second->copy(tdef)); : behavior_impl(y->timeout()),
} first_(x),
second_(y) {
combinator(const pointer& p0, const pointer& p1) cases_.reserve(x->size() + y->size());
: behavior_impl(p1->timeout()), for (auto mci : *x)
first(p0), cases_.push_back(mci);
second(p1) { for (auto mci : *y)
// nop cases_.push_back(mci);
} begin_ = &cases_[0];
end_ = begin_ + cases_.size();
protected:
match_case** get_cases(size_t&) {
// never called
return nullptr;
} }
private: private:
pointer first; std::vector<match_case_info> cases_;
pointer second; pointer first_;
pointer second_;
}; };
} // namespace <anonymous> } // namespace <anonymous>
...@@ -67,22 +62,17 @@ behavior_impl::~behavior_impl() { ...@@ -67,22 +62,17 @@ behavior_impl::~behavior_impl() {
// nop // nop
} }
behavior_impl::behavior_impl(duration tout) behavior_impl::behavior_impl(duration tout) : timeout_(tout) {
: timeout_(tout),
begin_(nullptr),
end_(nullptr) {
// nop // nop
} }
bhvr_invoke_result behavior_impl::invoke(message& msg) { bhvr_invoke_result behavior_impl::invoke(message& msg) {
auto msg_token = msg.type_token(); auto msg_token = msg.type_token();
bhvr_invoke_result res; 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) 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 res;
}
}
return none; return none;
} }
......
...@@ -95,4 +95,32 @@ CAF_TEST(composition3) { ...@@ -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() 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