Skip to content

Commit

Permalink
Enable creation of reusable pipe pieces
Browse files Browse the repository at this point in the history
  • Loading branch information
TillHeinzel committed Sep 7, 2019
1 parent 8ed65b1 commit 4ab9f94
Show file tree
Hide file tree
Showing 13 changed files with 361 additions and 161 deletions.
2 changes: 1 addition & 1 deletion include/pipes2/detail/api/makePipes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "pipes2/detail/pipes/makeSource.hpp"
#include "pipes2/detail/pipes/makeSink.hpp"

#include "pipes2/detail/api/ensureValidOutput.hpp"
#include "pipes2/detail/api/ensureValidInputOutput.hpp"

// throughput pipes
namespace tillh::pipes2
Expand Down
4 changes: 1 addition & 3 deletions include/pipes2/detail/api/pipingOperator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@

#include "pipes2/detail/core/connect.hpp"

#include "pipes2/detail/api/ensureValidOutput.hpp"

namespace tillh::pipes2
{
template<class Lhs, class Rhs, std::enable_if_t<(detail::sends<Lhs> || detail::canSend<Lhs>) && (detail::receives<Rhs> || detail::canReceive<Rhs>), bool> = true>
auto operator>>=(Lhs && lhs, Rhs && rhs)
{
return connectPrimary(std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
return connectPrimary(FWD(lhs), FWD(rhs));
}
}
41 changes: 27 additions & 14 deletions include/pipes2/detail/core/Node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,43 @@

#include "pipes2/detail/util/metaprogramming.hpp"
#include "pipes2/detail/util/ignoreWarning.hpp"
#include "pipes2/detail/util/FWD.hpp"

#include "pipes2/detail/core/traits.hpp"

namespace tillh::pipes2
{
template<class OpT, class ConnectionsT, class PrimaryConnectionT>
template<class OpT, class ConnectionsT>
struct Node
{
using Op = OpT;
using Connections = ConnectionsT;
using PrimaryConnection = PrimaryConnectionT;

template<class Connections_, class PrimaryConnection_, class Op_>
Node(Connections_&& _connections, PrimaryConnection_&& _connectPrimaryion,
Op_&& _op): primaryConnection(std::forward<PrimaryConnection_>(_connectPrimaryion)), connections(
std::forward<Connections_>(_connections)),
op(std::forward<Op_>(_op))
template<class Connections_, class Op_>
Node(Connections_&& _connections, Op_&& _op):
connections(std::forward<Connections_>(_connections)), op(std::forward<Op_>(_op))
{}

PrimaryConnection primaryConnection;
template<class... Rhss>
auto operator()(Rhss&& ... rhss) const
{
return connectSecondary(*this, FWD(rhss)...);
}

Connections connections;
Op op;
};

struct NoPrimary {};
struct OpenConnectionPlaceHolder {};
struct PrimaryOpenConnectionPlaceHolder {};
}

namespace tillh::pipes2
{
template<class Op, class Connections, class PrimaryConnection>
auto makeNode(Op op, Connections connections, PrimaryConnection primaryConnection)
template<class Op, class Connections>
auto makeNode(Op op, Connections connections)
{
return Node<Op, Connections, PrimaryConnection>(std::move(connections), std::move(primaryConnection), std::move(op));
return Node<Op, Connections>(std::move(connections), std::move(op));
}


Expand All @@ -58,7 +61,17 @@ namespace tillh::pipes2
template<bool hasPrimaryConnection, std::size_t secondaryConnections, class Op>
auto makeNode(Op op)
{
constexpr auto makePrimary = [] {if constexpr(hasPrimaryConnection) { return OpenConnectionPlaceHolder(); } else { return NoPrimary(); }};
return makeNode(op, makeOpenConnections(std::make_index_sequence<secondaryConnections>()), makePrimary());
constexpr auto makePrimary = []
{
if constexpr(hasPrimaryConnection)
{
return std::make_tuple(PrimaryOpenConnectionPlaceHolder());
}
else
{
return std::tuple<>();
}
};
return makeNode(op, std::tuple_cat(makeOpenConnections(std::make_index_sequence<secondaryConnections>()), makePrimary()));
}
}
59 changes: 45 additions & 14 deletions include/pipes2/detail/core/connect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ namespace tillh::pipes2
template<>
struct openCountT<OpenConnectionPlaceHolder> : int_constant<1> {};

template<class Op, class... Connections, class Primary>
struct openCountT<Node<Op, std::tuple<Connections...>, Primary>> : sum<openCountT<Connections>...> {};
template<class Op, class... Connections>
struct openCountT<Node<Op, std::tuple<Connections...>>> : sum<openCountT<Connections>...> {};

template<class T>
constexpr static std::size_t openCount = openCountT<T>::value;
Expand Down Expand Up @@ -77,15 +77,34 @@ namespace tillh::pipes2
));
}
}

namespace tillh::pipes2
{
enum class ConnectMode{Primary, Secondary};
enum class ConnectMode { Primary, Secondary, Any };

template<ConnectMode mode>
using mode_constant = std::integral_constant<ConnectMode, mode>;

using primary_constant = mode_constant<ConnectMode::Primary>;
using secondary_constant = mode_constant<ConnectMode::Secondary>;
using any_constant = mode_constant<ConnectMode::Secondary>;

template<class T>
decltype(auto) clearPrimary(T&& t)
{
return FWD(t);
}

inline auto clearPrimary(PrimaryOpenConnectionPlaceHolder)
{
return OpenConnectionPlaceHolder();
}

template<class Op, class Connections>
auto clearPrimary(Node<Op, Connections>&& node)
{
return makeNode(std::move(node.op), tuple_replace<tuple_back<Connections>>(std::move(node.connections), clearPrimary(getLast(node.connections))));
}

template<class Connection, std::size_t... Indices, class NewConnects>
auto connectIndices(Connection&& connection, std::index_sequence<Indices...>, NewConnects newConnects)
Expand All @@ -96,7 +115,7 @@ namespace tillh::pipes2
}
else
{
return connectImpl(secondary_constant(), std::forward<Connection>(connection), std::get<Indices>(newConnects)...);
return clearPrimary(connectImpl(secondary_constant(), std::forward<Connection>(connection), std::get<Indices>(newConnects)...));
}
}

Expand All @@ -114,6 +133,7 @@ namespace tillh::pipes2
return connectIndexWise_impl(std::forward<Connections>(connections), indices, newConnects, std::make_index_sequence<connectionCount>());
}
}

namespace tillh::pipes2
{
template<class Node, class... Children>
Expand All @@ -122,37 +142,48 @@ namespace tillh::pipes2
static_assert(sizeof...(children) > 0);
static_assert(sizeof...(children) <= openCount<remove_cv_ref_t<Node>>);
auto indices = getIndices<sizeof...(children), remove_cv_ref_t<Node>>();
return makeNode(std::forward<Node>(node).op, connectIndexWise(std::forward<Node>(node).connections, indices, std::forward_as_tuple(children...)), std::forward<Node>(node).primaryConnection);
return makeNode(std::forward<Node>(node).op, connectIndexWise(std::forward<Node>(node).connections, indices, std::forward_as_tuple(children...)));
}

template<class Node, class Child>
auto connectPrimaryImpl(Node&& node, Child&& child)
{
return makeNode(FWD(node).op, FWD(node).connections, connectImpl(primary_constant(), FWD(node).primaryConnection, FWD(child)));
static_assert(canPrimaryConnect<remove_cv_ref_t<Node>>);
constexpr std::size_t lastIndex = tuple_back<typename remove_cv_ref_t<Node>::Connections>;
return makeNode(FWD(node).op, tuple_replace<lastIndex>(FWD(node).connections, connectImpl(primary_constant(), getLast(FWD(node).connections), FWD(child))));
}

template<ConnectMode mode, class Lhs, class... Rhss>
auto connectImpl(mode_constant<mode>, Lhs&& lhs, Rhss&& ... rhss)
{
static_assert(sizeof...(Rhss) > 0, "at least 1 rhs needed");

if constexpr(std::is_same_v<remove_cv_ref_t<Lhs>, OpenConnectionPlaceHolder>)
if constexpr(mode == ConnectMode::Secondary)
{
static_assert(sizeof...(Rhss) == 1, "there should never be a call to connect one placeholder with multiple nodes");
return getFirst(FWD(rhss)...);
if constexpr(std::is_same_v<remove_cv_ref_t<Lhs>, OpenConnectionPlaceHolder>)
{
static_assert(sizeof...(Rhss) == 1, "there should never be a call to connect one placeholder with multiple nodes");
return getFirst(FWD(rhss)...);
}
else
{
return evaluateIfFinished(connectSecondaryImpl(FWD(lhs), FWD(rhss)...));
}
}
else
else if(mode == ConnectMode::Primary)
{
if constexpr(mode == ConnectMode::Secondary)
if constexpr(std::is_same_v<remove_cv_ref_t<Lhs>, PrimaryOpenConnectionPlaceHolder>)
{
return evaluateIfFinished(connectSecondaryImpl(FWD(lhs), FWD(rhss)...));
static_assert(sizeof...(Rhss) == 1, "there should never be a call to connect one placeholder with multiple nodes");
return getFirst(FWD(rhss)...);
}
else if(mode == ConnectMode::Primary)
else
{
static_assert(sizeof...(Rhss) == 1, "can only primaryconnect 1 at a time");
return evaluateIfFinished(connectPrimaryImpl(FWD(lhs), FWD(rhss)...));
}
}

}

template<ConnectMode mode, class Source, class Node, class... Rhss>
Expand Down
15 changes: 4 additions & 11 deletions include/pipes2/detail/core/evaluate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,14 @@

namespace tillh::pipes2
{
template<class Op, class Connections, class PrimaryConnection>
auto evaluate(Node<Op, Connections, PrimaryConnection>&& node)
template<class Op, class Connections>
auto evaluate(Node<Op, Connections>&& node)
{
using NodeT = Node<Op, Connections, PrimaryConnection>;
using NodeT = Node<Op, Connections>;
static_assert(!canSecondaryConnect<NodeT>);
static_assert(!canPrimaryConnect<NodeT>);

if constexpr(hasPrimary_v<NodeT>)
{
return makeOutput(std::move(node.op), std::tuple_cat(std::move(node.connections), std::make_tuple(std::move(node.primaryConnection))));
}
else
{
return makeOutput(std::move(node.op), std::move(node.connections));
}
return makeOutput(std::move(node.op), std::move(node.connections));
}

template<class Node>
Expand Down
12 changes: 0 additions & 12 deletions include/pipes2/detail/core/traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,3 @@ namespace tillh::pipes2
template<class T>
constexpr static bool canSecondaryConnect = canSecondaryConnectT<T>::value;
}

namespace tillh::pipes2
{
template<class T>
struct hasPrimaryT : std::false_type
{
static_assert(fail_assert<T>);
};

template<class T>
constexpr static bool hasPrimary_v = hasPrimaryT<T>::value;
}
33 changes: 15 additions & 18 deletions include/pipes2/detail/core/traits.impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ namespace tillh::pipes2::detail
template<class Source, class Tree>
struct isSender<Input<Source, Tree>> : std::true_type {};

template<class Op, class Connections, class PrimaryConnection>
struct isSender<Node<Op, Connections, PrimaryConnection>> : std::true_type {};
template<class Op, class Connections>
struct isSender<Node<Op, Connections>> : std::true_type {};

template<class Op, class Connections>
struct isReceiver<Output<Op, Connections>> : std::true_type {};

template<class Op, class Connections, class PrimaryConnection>
struct isReceiver<Node<Op, Connections, PrimaryConnection>> : std::true_type {};
template<class Op, class Connections>
struct isReceiver<Node<Op, Connections>> : std::true_type {};

template<>
struct isReceiver<OpenConnectionPlaceHolder> : std::true_type {};
Expand All @@ -46,33 +46,30 @@ namespace tillh::pipes2::detail

namespace tillh::pipes2
{
template<>
struct canPrimaryConnectT<NoPrimary> : std::false_type {};

template<class Op, class Connections>
struct canPrimaryConnectT<Output<Op, Connections>> : std::false_type {};

template<>
struct canPrimaryConnectT<OpenConnectionPlaceHolder> : std::true_type {};
struct canPrimaryConnectT<PrimaryOpenConnectionPlaceHolder> : std::true_type {};

template<class Op, class Connections, class PrimaryConnection>
struct canPrimaryConnectT<Node<Op, Connections, PrimaryConnection>> : canPrimaryConnectT<PrimaryConnection> {};
template<>
struct canPrimaryConnectT<OpenConnectionPlaceHolder> : std::false_type {};

template<class Op, class Connections>
struct canPrimaryConnectT<Node<Op, Connections>> : canPrimaryConnectT<last_element<Connections>> {};
}

namespace tillh::pipes2
{
template<>
struct canSecondaryConnectT<OpenConnectionPlaceHolder> : std::true_type {};

template<>
struct canSecondaryConnectT<PrimaryOpenConnectionPlaceHolder> : std::false_type {};

template<class Op, class Connections>
struct canSecondaryConnectT<Output<Op, Connections>> : std::false_type {};

template<class Op, class... Connections, class PrimaryConnection>
struct canSecondaryConnectT<Node<Op, std::tuple<Connections...>, PrimaryConnection>> : std::disjunction<canSecondaryConnectT<Connections>...> {};
}

namespace tillh::pipes2
{
template<class Op, class Connections, class PrimaryConnection>
struct hasPrimaryT<Node<Op, Connections, PrimaryConnection>> : std::negation<std::is_same<PrimaryConnection, NoPrimary>> {};
template<class Op, class... Connections>
struct canSecondaryConnectT<Node<Op, std::tuple<Connections...>>> : std::disjunction<canSecondaryConnectT<Connections>...> {};
}
2 changes: 1 addition & 1 deletion include/pipes2/detail/pipes/makeSource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace tillh::pipes2::detail
template<class T>
auto makeSourceInput(T&& t)
{
return makeInput(std::forward<T>(t), OpenConnectionPlaceHolder());
return makeInput(std::forward<T>(t), PrimaryOpenConnectionPlaceHolder());
}

template<class Range, std::enable_if_t<is_range_v<remove_cv_ref_t<Range>>, bool> = true>
Expand Down
Loading

0 comments on commit 4ab9f94

Please sign in to comment.