Commit 71d2e3e9 authored by Dominik Charousset's avatar Dominik Charousset

Make composition of stream stages type-safe

parent 4c886d32
......@@ -26,6 +26,7 @@
#include "caf/expected.hpp"
#include "caf/optional.hpp"
#include "caf/replies_to.hpp"
#include "caf/stream_result.hpp"
#include "caf/detail/implicit_conversions.hpp"
......@@ -51,14 +52,21 @@ struct dmi<result<Ys...> (Xs...)> {
output_tuple<implicit_conversions_t<Ys>...>>;
};
// case #2b: function returning a std::tuple<...>
// case #2b: function returning a stream_result<...>
template <class Y, class... Xs>
struct dmi<stream_result<Y> (Xs...)> {
using type = typed_mpi<type_list<typename std::decay<Xs>::type...>,
output_tuple<implicit_conversions_t<Y>>>;
};
// case #2c: function returning a std::tuple<...>
template <class... Ys, class... Xs>
struct dmi<std::tuple<Ys...> (Xs...)> {
using type = typed_mpi<type_list<typename std::decay<Xs>::type...>,
output_tuple<implicit_conversions_t<Ys>...>>;
};
// case #2c: function returning a std::tuple<...>
// case #2d: function returning a std::tuple<...>
template <class... Ys, class... Xs>
struct dmi<delegated<Ys...> (Xs...)> {
using type = typed_mpi<type_list<typename std::decay<Xs>::type...>,
......@@ -80,6 +88,14 @@ struct dmi<optional<Y> (Xs...)> : dmi<Y (Xs...)> {};
template <class Y, class... Xs>
struct dmi<expected<Y> (Xs...)> : dmi<Y (Xs...)> {};
// case #5: function returning an annotated_stream<>
template <class Y, class... Ys, class... Xs>
struct dmi<annotated_stream<Y, Ys...> (Xs...)> : dmi<Y (Xs...)> {
using type =
typed_mpi<type_list<typename std::decay<Xs>::type...>,
output_tuple<stream<Y>, strip_and_convert_t<Ys>...>>;
};
// -- dmfou = deduce_mpi_function_object_unboxing
template <class T, bool isClass = std::is_class<T>::value>
......
......@@ -53,6 +53,10 @@ template <class...> class typed_actor_pointer;
template <class...> class typed_response_promise;
template <class...> class typed_event_based_actor;
// -- variadic templates with 1 fixed argument ---------------------------------
template <class, class...> class annotated_stream;
// -- classes ------------------------------------------------------------------
class actor;
......@@ -183,6 +187,7 @@ using weak_actor_ptr = weak_intrusive_ptr<actor_control_block>;
// -- intrusive pointer aliases ------------------------------------------------
using stream_handler_ptr = intrusive_ptr<stream_handler>;
using strong_actor_ptr = intrusive_ptr<actor_control_block>;
// -- unique pointer aliases ---------------------------------------------------
......
This diff is collapsed.
......@@ -20,11 +20,14 @@
#ifndef CAF_STREAM_HPP
#define CAF_STREAM_HPP
#include "caf/fwd.hpp"
#include "caf/stream_id.hpp"
#include "caf/stream_handler.hpp"
#include "caf/meta/type_name.hpp"
namespace caf {
/// Marker type for constructing invalid `stream` objects.
struct invalid_stream_t {};
/// Identifies an unbound sequence of messages.
......@@ -41,14 +44,36 @@ public:
// nop
}
/// Convenience constructor for returning the result of `self->new_stream`
/// and similar functions.
stream(stream_id sid, stream_handler_ptr sptr)
: id_(std::move(sid)),
ptr_(std::move(sptr)) {
// nop
}
/// Convenience constructor for returning the result of `self->new_stream`
/// and similar functions.
stream(stream other, stream_handler_ptr sptr)
: id_(std::move(other.id_)),
ptr_(std::move(sptr)) {
// nop
}
stream(invalid_stream_t) {
// nop
}
/// Returns the unique identifier for this stream.
inline const stream_id& id() const {
return id_;
}
/// Returns the handler assigned to this stream on this actor.
inline const stream_handler_ptr& ptr() const {
return ptr_;
}
template <class Inspector>
friend typename Inspector::result_type inspect(Inspector& f, stream& x) {
return f(meta::type_name("stream"), x.id_);
......@@ -56,10 +81,24 @@ public:
private:
stream_id id_;
stream_handler_ptr ptr_;
};
/// @relates stream
constexpr invalid_stream_t invalid_stream = invalid_stream_t{};
/// Identifies an unbound sequence of messages annotated with the additional
/// handshake arguments emitted to the next stage.
template <class T, class... Ts>
class annotated_stream final : public stream<T> {
public:
/// Dennotes the supertype.
using super = stream<T>;
// Import constructors.
using super::super;
};
} // namespace caf
#endif // CAF_STREAM_HPP
......@@ -49,6 +49,7 @@ struct stream_msg : tag::boxing_type {
/// Identifies content types that propagate errors in both directions.
flows_both_ways
};
/// Initiates a stream handshake.
struct open {
/// Allows visitors to dispatch on this tag.
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2016 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#ifndef CAF_STREAM_RESULT_HPP
#define CAF_STREAM_RESULT_HPP
#include "caf/fwd.hpp"
#include "caf/stream_id.hpp"
#include "caf/stream_handler.hpp"
#include "caf/meta/type_name.hpp"
namespace caf {
/// Terminates a stream by reducing it to a single value.
template <class T>
class stream_result {
public:
stream_result() = default;
stream_result(stream_result&&) = default;
stream_result(const stream_result&) = default;
stream_result& operator=(stream_result&&) = default;
stream_result& operator=(const stream_result&) = default;
stream_result(stream_id sid) : id_(std::move(sid)) {
// nop
}
/// Convenience constructor for returning the result of `self->new_stream_result`
/// and similar functions.
stream_result(stream_id sid, stream_handler_ptr sptr)
: id_(std::move(sid)),
ptr_(std::move(sptr)) {
// nop
}
/// Convenience constructor for returning the result of `self->new_stream_result`
/// and similar functions.
stream_result(stream_result other, stream_handler_ptr sptr)
: id_(std::move(other.id_)),
ptr_(std::move(sptr)) {
// nop
}
/// Returns the unique identifier for this stream_result.
inline const stream_id& id() const {
return id_;
}
/// Returns the handler assigned to this stream_result on this actor.
inline const stream_handler_ptr& ptr() const {
return ptr_;
}
template <class Inspector>
friend typename Inspector::result_type inspect(Inspector& f, stream_result& x) {
return f(meta::type_name("stream_result"), x.id_);
}
private:
stream_id id_;
stream_handler_ptr ptr_;
};
} // namespace caf
#endif // CAF_STREAM_RESULT_HPP
......@@ -379,7 +379,7 @@ scheduled_actor::categorize(mailbox_element& x) {
return message_category::internal;
}
case make_type_token<stream_msg>(): {
auto sm = content.move_if_unshared<stream_msg>(0);
auto& sm = content.get_mutable_as<stream_msg>(0);
auto e = streams_.end();
stream_msg_visitor f{this, sm.sid, streams_.find(sm.sid), e};
auto res = apply_visitor(f, sm.content);
......
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