Commit 5616bec9 authored by Dominik Charousset's avatar Dominik Charousset

Enable composable behaviors to use streaming API

parent 0ea433f3
......@@ -18,12 +18,12 @@
#pragma once
#include "caf/param.hpp"
#include "caf/abstract_composable_behavior.hpp"
#include "caf/behavior.hpp"
#include "caf/param.hpp"
#include "caf/replies_to.hpp"
#include "caf/typed_actor.hpp"
#include "caf/typed_actor_pointer.hpp"
#include "caf/abstract_composable_behavior.hpp"
namespace caf {
......@@ -106,4 +106,3 @@ public:
};
} // namespace caf
......@@ -84,15 +84,27 @@ private:
flag flag_;
};
/// Convenience alias that wraps `T` into `param<T>`
/// unless `T` is arithmetic or an atom constant.
/// Converts `T` to `param<T>` unless `T` is arithmetic, an atom constant, or
/// a stream handshake.
template <class T>
using param_t =
typename std::conditional<
std::is_arithmetic<T>::value || is_atom_constant<T>::value,
T,
param<T>
>::type;
struct add_param : std::conditional<std::is_arithmetic<T>::value, T, param<T>> {
// nop
};
template <atom_value V>
struct add_param<atom_constant<V>> {
using type = atom_constant<V>;
};
template <class T>
struct add_param<stream<T>> {
using type = stream<T>;
};
/// Convenience alias that wraps `T` into `param<T>` unless `T` is arithmetic,
/// a stream handshake or an atom constant.
template <class T>
using param_t = typename add_param<T>::type;
/// Unpacks `param<T>` to `T`.
template <class T>
......@@ -112,4 +124,3 @@ struct param_decay {
};
} // namespace caf
......@@ -58,7 +58,11 @@ public:
}
/// @private
scheduled_actor* internal_ptr() const {
scheduled_actor* internal_ptr() const noexcept {
return view_.internal_ptr();
}
operator scheduled_actor*() const noexcept {
return view_.internal_ptr();
}
......
......@@ -112,23 +112,27 @@ public:
/// Returns a pointer to the sender of the current message.
/// @pre `current_mailbox_element() != nullptr`
inline strong_actor_ptr& current_sender() {
strong_actor_ptr& current_sender() {
return self_->current_sender();
}
/// Returns a pointer to the currently processed mailbox element.
inline mailbox_element* current_mailbox_element() {
mailbox_element* current_mailbox_element() {
return self_->current_mailbox_element();
}
/// @private
actor_control_block* ctrl() const {
actor_control_block* ctrl() const noexcept {
CAF_ASSERT(self_ != nullptr);
return actor_control_block::from(self_);;
}
/// @private
scheduled_actor* internal_ptr() const {
scheduled_actor* internal_ptr() const noexcept {
return self_;
}
operator scheduled_actor*() const noexcept {
return self_;
}
......@@ -137,4 +141,3 @@ private:
};
} // namespace caf
This diff is collapsed.
......@@ -18,13 +18,14 @@
#pragma once
#include <type_traits>
#include "caf/all.hpp"
#include "caf/config.hpp"
#include "caf/detail/gcd.hpp"
#include "caf/meta/annotation.hpp"
#include "caf/test/unit_test.hpp"
#include "caf/detail/gcd.hpp"
CAF_PUSH_WARNINGS
/// The type of `_`.
......@@ -375,6 +376,71 @@ protected:
std::function<void ()> peek_;
};
template <class... Ts>
class inject_clause {
public:
inject_clause(caf::scheduler::test_coordinator& sched)
: sched_(sched), dest_(nullptr) {
// nop
}
inject_clause(inject_clause&& other) = default;
template <class Handle>
inject_clause& from(const Handle& whom) {
src_ = caf::actor_cast<caf::strong_actor_ptr>(whom);
return *this;
}
template <class Handle>
inject_clause& to(const Handle& whom) {
dest_ = caf::actor_cast<caf::strong_actor_ptr>(whom);
return *this;
}
inject_clause& to(const caf::scoped_actor& whom) {
dest_ = whom.ptr();
return *this;
}
void with(Ts... xs) {
if (src_ == nullptr)
CAF_FAIL("missing .from() in inject() statement");
if (dest_ == nullptr)
CAF_FAIL("missing .to() in inject() statement");
caf::send_as(caf::actor_cast<caf::actor>(src_),
caf::actor_cast<caf::actor>(dest_), xs...);
CAF_REQUIRE(sched_.prioritize(dest_));
auto dest_ptr = &sched_.next_job<caf::abstract_actor>();
auto ptr = dest_ptr->peek_at_next_mailbox_element();
CAF_REQUIRE(ptr != nullptr);
CAF_REQUIRE_EQUAL(ptr->sender, src_);
// TODO: replace this workaround with the make_tuple() line when dropping
// support for GCC 4.8.
std::tuple<Ts...> tmp{std::move(xs)...};
using namespace caf::detail;
elementwise_compare_inspector<decltype(tmp)> inspector{tmp};
auto ys = extract<Ts...>(dest_);
auto ys_indices = get_indices(ys);
CAF_REQUIRE(apply_args(inspector, ys_indices, ys));
run_once();
}
protected:
void run_once() {
auto ptr = caf::actor_cast<caf::abstract_actor*>(dest_);
auto dptr = dynamic_cast<caf::blocking_actor*>(ptr);
if (dptr == nullptr)
sched_.run_once();
else
dptr->dequeue(); // Drop message.
}
caf::scheduler::test_coordinator& sched_;
caf::strong_actor_ptr src_;
caf::strong_actor_ptr dest_;
};
template <class... Ts>
class allow_clause {
public:
......@@ -796,6 +862,12 @@ T unbox(T* x) {
expect_clause<CAF_EXPAND(CAF_DSL_LIST types)>{sched}.fields; \
} while (false)
#define inject(types, fields) \
do { \
CAF_MESSAGE("inject" << #types << "." << #fields); \
inject_clause<CAF_EXPAND(CAF_DSL_LIST types)>{sched}.fields; \
} while (false)
/// Convenience macro for defining allow clauses.
#define allow(types, fields) \
([&] { \
......
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