Commit 8f804ac0 authored by Dominik Charousset's avatar Dominik Charousset

Fix spawning of stateful function-based actors

parent a88e7bca
...@@ -27,6 +27,9 @@ is based on [Keep a Changelog](https://keepachangelog.com). ...@@ -27,6 +27,9 @@ is based on [Keep a Changelog](https://keepachangelog.com).
fixes a regression introduced in version 0.18.0-rc.1 fixes a regression introduced in version 0.18.0-rc.1
- Fixed an endless recursion when using the `default_inspector` from `inspect` - Fixed an endless recursion when using the `default_inspector` from `inspect`
overloads (#1147). overloads (#1147).
- CAF 0.18 added support for `make_behavior` in state classes. However, CAF
erroneously picked this member function over running the function body when
spawning function-based actors (#1149).
## [0.18.0-rc.1] - 2020-09-09 ## [0.18.0-rc.1] - 2020-09-09
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "caf/none.hpp" #include "caf/none.hpp"
#include "caf/timeout_definition.hpp" #include "caf/timeout_definition.hpp"
#include "caf/timespan.hpp" #include "caf/timespan.hpp"
#include "caf/unsafe_behavior_init.hpp"
namespace caf { namespace caf {
...@@ -45,6 +46,11 @@ public: ...@@ -45,6 +46,11 @@ public:
behavior& operator=(behavior&&) = default; behavior& operator=(behavior&&) = default;
behavior& operator=(const behavior&) = default; behavior& operator=(const behavior&) = default;
// Convenience overload to allow "unsafe" initialization of any behavior_type.
behavior(unsafe_behavior_init_t, behavior from) : behavior(std::move(from)) {
// nop
}
/// Creates a behavior from `fun` without timeout. /// Creates a behavior from `fun` without timeout.
behavior(const message_handler& mh); behavior(const message_handler& mh);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/sec.hpp" #include "caf/sec.hpp"
#include "caf/unsafe_behavior_init.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
...@@ -113,6 +114,13 @@ namespace caf::detail { ...@@ -113,6 +114,13 @@ namespace caf::detail {
template <class State, class Base> template <class State, class Base>
typename Base::behavior_type stateful_actor_base<State, Base>::make_behavior() { typename Base::behavior_type stateful_actor_base<State, Base>::make_behavior() {
// When spawning function-based actors, CAF sets `initial_behavior_fac_` to
// wrap the function invocation. This always has the highest priority.
if (this->initial_behavior_fac_) {
auto res = this->initial_behavior_fac_(this);
this->initial_behavior_fac_ = nullptr;
return {unsafe_behavior_init, std::move(res)};
}
auto dptr = static_cast<stateful_actor<State, Base>*>(this); auto dptr = static_cast<stateful_actor<State, Base>*>(this);
return dptr->state.make_behavior(); return dptr->state.make_behavior();
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "caf/message_handler.hpp" #include "caf/message_handler.hpp"
#include "caf/system_messages.hpp" #include "caf/system_messages.hpp"
#include "caf/timespan.hpp" #include "caf/timespan.hpp"
#include "caf/unsafe_behavior_init.hpp"
#include "caf/detail/typed_actor_util.hpp" #include "caf/detail/typed_actor_util.hpp"
...@@ -152,12 +153,6 @@ struct partial_behavior_init_t {}; ...@@ -152,12 +153,6 @@ struct partial_behavior_init_t {};
constexpr partial_behavior_init_t partial_behavior_init constexpr partial_behavior_init_t partial_behavior_init
= partial_behavior_init_t{}; = partial_behavior_init_t{};
/// Empty struct tag for constructing from an untyped behavior.
struct unsafe_behavior_init_t {};
constexpr unsafe_behavior_init_t unsafe_behavior_init
= unsafe_behavior_init_t{};
template <class... Sigs> template <class... Sigs>
class typed_behavior { class typed_behavior {
public: public:
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
namespace caf {
/// Empty struct tag for constructing a typed behavior from an untyped behavior.
struct unsafe_behavior_init_t {};
/// Convenience constant for constructing a typed behavior from an untyped
/// behavior.
constexpr unsafe_behavior_init_t unsafe_behavior_init
= unsafe_behavior_init_t{};
} // namespace caf
...@@ -209,4 +209,24 @@ CAF_TEST(typed actors can use typed_actor_pointer as self pointer) { ...@@ -209,4 +209,24 @@ CAF_TEST(typed actors can use typed_actor_pointer as self pointer) {
expect((int), from(testee).to(self).with(11)); expect((int), from(testee).to(self).with(11));
} }
CAF_TEST(returned behaviors take precedence over make_behavior in the state) {
struct state_type : named_state {
behavior make_behavior() {
CAF_LOG_TRACE("");
return {
[](int32_t x, int32_t y) { return x - y; },
};
}
};
auto fun = [](stateful_actor<state_type>*, int32_t num) -> behavior {
CAF_LOG_TRACE(CAF_ARG(num));
return {
[num](int32_t x, int32_t y) { return x + y + num; },
};
};
auto testee = sys.spawn<lazy_init>(fun, 10);
inject((int32_t, int32_t), from(self).to(testee).with(1, 2));
expect((int32_t), from(testee).to(self).with(13));
}
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