Commit 8181610d authored by Dominik Charousset's avatar Dominik Charousset

Allow composable states to modify handler inputs

parent a78b7351
......@@ -36,6 +36,7 @@ void hello_world(event_based_actor* self, const actor& buddy) {
}
int main() {
// our CAF environment
actor_system system;
// create a new actor that calls 'mirror()'
auto mirror_actor = system.spawn(mirror);
......
......@@ -20,7 +20,15 @@
#ifndef CAF_ABSTRACT_COMPOSABLE_STATE_HPP
#define CAF_ABSTRACT_COMPOSABLE_STATE_HPP
#include <utility>
#include "caf/fwd.hpp"
#include "caf/sec.hpp"
#include "caf/message.hpp"
#include "caf/detail/int_list.hpp"
#include "caf/detail/apply_args.hpp"
#include "caf/detail/pseudo_tuple.hpp"
namespace caf {
......@@ -30,6 +38,28 @@ public:
virtual ~abstract_composable_state();
virtual void init_behavior(behavior& x) = 0;
template <class Derived, class... Ts>
auto invoke_mutable(Derived* thisptr, const Ts&...)
-> decltype(std::declval<Derived>()(std::declval<Ts>()...)) {
// re-dispatch on current message via lambda expression
auto f = [thisptr](Ts&... xs) {
return (*thisptr)(xs...);
};
// reference to the current message
auto& msg = thisptr->self->current_message();
if (! msg.template match_elements<Ts...>())
return sec::invalid_invoke_mutable;
// make sure no other actor accesses the same data
msg.force_unshare();
// fill a pseudo tuple with values and invoke f
detail::pseudo_tuple<Ts...> buf;
// msg is guaranteed to be detached, hence we don't need to
// check this condition over and over again via mutable_at
for (size_t i = 0; i < msg.size(); ++i)
buf[i] = const_cast<void*>(msg.at(i));
return detail::apply_args(f, detail::get_indices(buf), buf);
}
};
} // namespace caf
......
......@@ -116,7 +116,6 @@ public:
init_behavior_impl(this, token, x);
}
protected:
typed_actor_pointer<Clauses...> self;
};
......
......@@ -29,6 +29,8 @@ namespace caf {
enum class sec : uint8_t {
/// Indicates that a dynamically typed actor dropped an unexpected message.
unexpected_message = 1,
/// Indicates that a call to `invoke_mutable` failed in a composable state.
invalid_invoke_mutable,
/// Indicates that a response message did not match the provided handler.
unexpected_response,
/// Indicates that the receiver of a request is no longer alive.
......
......@@ -135,6 +135,10 @@ public:
* miscellaneous actor operations *
****************************************************************************/
message& current_message() {
return self_->current_message();
}
actor_system& system() const {
return self_->system();
}
......
......@@ -99,8 +99,13 @@ public:
return i->second;
}
result<void> operator()(put_atom, const std::string& key, const std::string& value) override {
values_[key] = value;
result<void> operator()(put_atom put, const std::string& key,
const std::string& value) override {
return invoke_mutable(this, put, key, value);
}
result<void> operator()(put_atom, std::string& key, std::string& value) {
values_.emplace(std::move(key), std::move(value));
return unit;
}
......
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