From 9480401416a5b58299867fbef99174d84b9cfa93 Mon Sep 17 00:00:00 2001 From: FritzFlorian Date: Fri, 19 Jul 2019 11:25:29 +0200 Subject: [PATCH] Refine flow through system with better template programming. We separated the structure (input-output flow) from the rest of the architecture and reworked some template programming to have better access to the types required at compile time. --- NOTES.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ app/playground/main.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++-------------------------- lib/pls/CMakeLists.txt | 14 ++++++++------ lib/pls/include/pls/dataflow/input.h | 26 -------------------------- lib/pls/include/pls/dataflow/inputs.h | 6 ------ lib/pls/include/pls/dataflow/internal/buffer.h | 38 ++++++++++++++++++++++++++++++++++++++ lib/pls/include/pls/dataflow/internal/graph.h | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pls/include/pls/dataflow/internal/in_port.h | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pls/include/pls/dataflow/internal/input.h | 61 ------------------------------------------------------------- lib/pls/include/pls/dataflow/internal/inputs.h | 112 ---------------------------------------------------------------------------------------------------------------- lib/pls/include/pls/dataflow/internal/out_port.h | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pls/include/pls/dataflow/internal/output.h | 41 ----------------------------------------- lib/pls/include/pls/dataflow/internal/outputs.h | 38 -------------------------------------- lib/pls/include/pls/dataflow/output.h | 28 ---------------------------- lib/pls/include/pls/dataflow/outputs.h | 7 +------ 15 files changed, 505 insertions(+), 350 deletions(-) delete mode 100644 lib/pls/include/pls/dataflow/input.h create mode 100644 lib/pls/include/pls/dataflow/internal/buffer.h create mode 100644 lib/pls/include/pls/dataflow/internal/graph.h create mode 100644 lib/pls/include/pls/dataflow/internal/in_port.h delete mode 100644 lib/pls/include/pls/dataflow/internal/input.h delete mode 100644 lib/pls/include/pls/dataflow/internal/inputs.h create mode 100644 lib/pls/include/pls/dataflow/internal/out_port.h delete mode 100644 lib/pls/include/pls/dataflow/internal/output.h delete mode 100644 lib/pls/include/pls/dataflow/internal/outputs.h delete mode 100644 lib/pls/include/pls/dataflow/output.h diff --git a/NOTES.md b/NOTES.md index dc12969..a4481d5 100644 --- a/NOTES.md +++ b/NOTES.md @@ -4,6 +4,80 @@ A collection of stuff that we noticed during development. Useful later on two write a project report and to go back in time to find out why certain decisions where made. +## 19.07.2019 - Colored tokens, recursion and where to put memory + +While implementing dataflow graphs we encountered some obstacles. +The most severe one the most severe one that impacts the +internal design of the API, end user features and performance +is how to handle token flows, especially colored tokens for parallel +and/or recursive calls. + +The basic issue here is, that each execution instance requires its +own isolated environment to execute in. Therefore, each invocation +instance (parallel or recursive) needs an unique identifier. +This identifier is usually realized using colored tokens, +as for example in this \[1] classic dataflow language implementation. +The problem with this is, that in our environment we are constrained +to static memory allocation and lock-free programming. +To handle static memory allocation we first decided to follow an model +introduced by EMBB, associating an clock to each colored token, +which maps it to an slot in an array of possible parallel execution +instances. This works fine in EMBB, as they put two major limitations +on their execution model: no cycles and no recursion. +(Issues arise with correcly coloring tokens in an lock-free matter +without too much contention, leading us to believe that this +method scales very bad, especially with smaller workloads) + +While we could simply implement that, we wondered if there is a way to +better fit dataflow in our existing, task-stack based programming +approach. + +After some investigation we found some core statements: +- The dataflow graph itself describes only programming execution, +it should therefore not be tightly coupled with data/buffer management +- Each invocation of an dataflow graph is logically a task in our model, +it therefore makes sense to map the memory and coordination resources +required for one invocation instance directly to this task +- What we do is in fact not 'pure' dataflow programming, as we do not +try to re-create a full programming language (e.g. we do not care about +memory management and loops described in \[1]) +- What we do is more close to functional programming with single +assignment rules and recursion (see Elixir for a nice syntactic example) + +Our plan is therefore the following: +Separate structure of the dataflow from execution and map +one execution instance to one active task in our runtime system. + +This, conveniently, also mitigates most issues related to +memory allocation/parallelism in the graph and makes for a +nicer end user API (no more buffer types/parallelism in templates). + + +\[1] J. B. Dennis, “First version of a data flow procedure language,” in Programming Symposium, vol. 19, B. Robinet, Ed. Berlin, Heidelberg: Springer Berlin Heidelberg, 1974, pp. 362–376. + + +## 19.07.2019 - Variadic Templates for input/output goups + +We searched for the correct way to represent an nodes +or graphs input/output pairs for a while and found the +solution in partial specialization of templates. + +```C++ +template +class graph {}; + +template +class graph, outputs> { ... }; +``` + +The above code allows us to enforce an end-user API that is +clean while still giving us full access on the input/output variadic +template types. The end user API is the following: + +```C++ +graph, outputs> g; +``` + ## 03.07.2019 - Outline/Plan for our Dataflow API The following describes our ideas for what we expect/want to build diff --git a/app/playground/main.cpp b/app/playground/main.cpp index cd9e742..74c05de 100644 --- a/app/playground/main.cpp +++ b/app/playground/main.cpp @@ -2,35 +2,52 @@ #include #include #include +#include -#include -#include -#include +#include +#include +#include +#include +#include int main() { using namespace pls::dataflow; + using namespace pls::dataflow::internal; + + out_port port1; + out_port port2; + graph::type, inputs, outputs> tmp{}; + + port1 >> tmp.in_port<0>(); + port2 >> tmp.in_port<1>(); + + port1.push_token({1, {}}); + port2.push_token({2, {}}); + +// using namespace pls::dataflow; +// +// graph, outputs, 2> graph2; +// graph2.input<0>() >> graph2.output<1>(); +// graph2.input<1>() >> graph2.output<0>(); +// +// graph, outputs, 2> graph1; +// graph1.input<0>() >> graph2.external_input<0>(); +// graph1.input<1>() >> graph2.external_input<1>(); +// graph2.external_output<0>() >> graph1.output<0>(); +// graph2.external_output<1>() >> graph1.output<1>(); +// +// graph1.push_input(1, 2); +// graph1.push_input(3, 4); +// +// auto result1 = graph1.get_output(); +// std::cout << std::get<0>(result1) << ", " << std::get<1>(result1) << std::endl; +// +// graph1.push_input(5, 6); +// +// auto result2 = graph1.get_output(); +// std::cout << std::get<0>(result2) << ", " << std::get<1>(result2) << std::endl; +// +// auto result3 = graph1.get_output(); +// std::cout << std::get<0>(result3) << ", " << std::get<1>(result3) << std::endl; - graph, outputs, 2> graph2; - graph2.input<0>() >> graph2.output<1>(); - graph2.input<1>() >> graph2.output<0>(); - - graph, outputs, 2> graph1; - graph1.input<0>() >> graph2.external_input<0>(); - graph1.input<1>() >> graph2.external_input<1>(); - graph2.external_output<0>() >> graph1.output<0>(); - graph2.external_output<1>() >> graph1.output<1>(); - - graph1.push_input(1, 2); - graph1.push_input(3, 4); - - auto result1 = graph1.get_output(); - std::cout << std::get<0>(result1) << ", " << std::get<1>(result1) << std::endl; - - graph1.push_input(5, 6); - - auto result2 = graph1.get_output(); - std::cout << std::get<0>(result2) << ", " << std::get<1>(result2) << std::endl; - - auto result3 = graph1.get_output(); - std::cout << std::get<0>(result3) << ", " << std::get<1>(result3) << std::endl; } diff --git a/lib/pls/CMakeLists.txt b/lib/pls/CMakeLists.txt index 41a974b..6735058 100644 --- a/lib/pls/CMakeLists.txt +++ b/lib/pls/CMakeLists.txt @@ -10,12 +10,13 @@ add_library(pls STATIC include/pls/algorithms/scan_impl.h include/pls/dataflow/dataflow.h + include/pls/dataflow/inputs.h + include/pls/dataflow/outputs.h include/pls/dataflow/internal/token.h - include/pls/dataflow/graph.h - include/pls/dataflow/internal/inputs.h - include/pls/dataflow/internal/outputs.h - include/pls/dataflow/internal/input.h - include/pls/dataflow/internal/output.h + include/pls/dataflow/internal/in_port.h + include/pls/dataflow/internal/out_port.h + include/pls/dataflow/internal/graph.h + include/pls/dataflow/internal/buffer.h include/pls/internal/base/spin_lock.h include/pls/internal/base/tas_spin_lock.h src/internal/base/tas_spin_lock.cpp @@ -47,7 +48,8 @@ add_library(pls STATIC include/pls/internal/scheduling/scheduler_impl.h include/pls/internal/scheduling/task.h src/internal/scheduling/task.cpp include/pls/internal/scheduling/scheduler_memory.h src/internal/scheduling/scheduler_memory.cpp - include/pls/internal/scheduling/lambda_task.h include/pls/dataflow/inputs.h include/pls/dataflow/outputs.h include/pls/dataflow/input.h include/pls/dataflow/output.h) + include/pls/internal/scheduling/lambda_task.h + ) # Add everything in `./include` to be in the include path of this project target_include_directories(pls PUBLIC diff --git a/lib/pls/include/pls/dataflow/input.h b/lib/pls/include/pls/dataflow/input.h deleted file mode 100644 index 700bcec..0000000 --- a/lib/pls/include/pls/dataflow/input.h +++ /dev/null @@ -1,26 +0,0 @@ - -#ifndef PLS_DATAFLOW_INPUT_H_ -#define PLS_DATAFLOW_INPUT_H_ - -#include "pls/dataflow/internal/input.h" - -namespace pls { -namespace dataflow { - -template -class input { - template - friend - class output; - - using internal_type = internal::input; - internal_type &internal_input_; - - public: - explicit input(internal_type &internal_input) : internal_input_{internal_input} {}; -}; - -} -} - -#endif //PLS_DATAFLOW_INPUT_H_ diff --git a/lib/pls/include/pls/dataflow/inputs.h b/lib/pls/include/pls/dataflow/inputs.h index 8e397fa..d1bb05d 100644 --- a/lib/pls/include/pls/dataflow/inputs.h +++ b/lib/pls/include/pls/dataflow/inputs.h @@ -2,17 +2,11 @@ #ifndef PLS_DATAFLOW_INPUTS_H_ #define PLS_DATAFLOW_INPUTS_H_ -#include - -#include "internal/inputs.h" - namespace pls { namespace dataflow { template struct inputs { - template - using internal_inputs = internal::inputs; }; } diff --git a/lib/pls/include/pls/dataflow/internal/buffer.h b/lib/pls/include/pls/dataflow/internal/buffer.h new file mode 100644 index 0000000..4546b27 --- /dev/null +++ b/lib/pls/include/pls/dataflow/internal/buffer.h @@ -0,0 +1,38 @@ + +#ifndef PLS_DATAFLOW_INTERNAL_BUFFER_H_ +#define PLS_DATAFLOW_INTERNAL_BUFFER_H_ + +#include + +#include "in_port.h" + +namespace pls { +namespace dataflow { +namespace internal { + +template +struct static_buffer_impl { + std::array buffer_; + + const T &operator[](size_t i) const { return buffer_[i]; } + T &operator[](size_t i) { return buffer_[i]; } + + static_buffer_impl() : buffer_{} {}; + explicit static_buffer_impl(T init) : buffer_(init) {}; + + int capacity() const { + return P; + } +}; + +template +struct static_buffer { + template + using type = static_buffer_impl; +}; + +} +} +} + +#endif //PLS_DATAFLOW_INTERNAL_BUFFER_H_ diff --git a/lib/pls/include/pls/dataflow/internal/graph.h b/lib/pls/include/pls/dataflow/internal/graph.h new file mode 100644 index 0000000..1cb7905 --- /dev/null +++ b/lib/pls/include/pls/dataflow/internal/graph.h @@ -0,0 +1,147 @@ + +#ifndef PLS_DATAFLOW_INTERNAL_GRAPH_H_ +#define PLS_DATAFLOW_INTERNAL_GRAPH_H_ + +#include +#include +#include + +#include "buffer.h" +#include "in_port.h" +#include "out_port.h" + +#include "pls/dataflow/inputs.h" +#include "pls/dataflow/outputs.h" + +namespace pls { +namespace dataflow { +namespace internal { + +struct graph_invocation { + enum state { clear, running, finished }; + + explicit graph_invocation(int num_outputs) : num_outputs_{num_outputs}, outputs_missing_{num_outputs} {}; + + void reset() { + state_ = clear; + internal_call_ = false; + previous_color_ = {}; + + outputs_missing_ = num_outputs_; + } + + const int num_outputs_; + std::atomic outputs_missing_; + + state state_{clear}; + + bool internal_call_{false}; + token_color previous_color_{}; +}; + +template class B, typename INS, typename OUTS> +class graph {}; + +template class B, typename I0, typename ...I, typename O0, typename ...O> +class graph, pls::dataflow::outputs> { + private: + using self_type = graph, pls::dataflow::outputs>; + struct in_port_cb { + self_type &self_; + + explicit in_port_cb(self_type &self) : self_{self} {}; + + template + void token_pushed(token token) { + self_.in_port_token_pushed(token); + } + }; + struct output_cb { + const self_type &self_; + + explicit output_cb(self_type &self) : self_{self} {}; + + template + void token_pushed(token token) { + self_.output_token_pushed(token); + } + }; + + // Type-Defs used internally + using my_type = graph, pls::dataflow::outputs>; + + using multi_in_port_type = multi_in_port; + using multi_out_port_type = multi_out_port; + + using input_tuple = std::tuple; + using output_tuple = std::tuple; + + public: + template + using in_port_at = typename multi_in_port_type::template in_port_type_at; + template + using out_port_at = typename multi_out_port_type::template out_port_type_at; + + template + in_port_at &in_port() { + return in_port_.template get(); + } + + template + out_port_at &out_port() { + return out_port_.template get(); + } + + template + void in_port_token_pushed(token token) { + auto my_clock = input_clock_++; + + auto index = token.color().get_index(buffer_size_); + + std::cout << "Token pushed at " << POS << " with value " << token.value() << std::endl; + +// std::get(inputs_[index]) = token; +// +// auto remaining = --inputs_required_[index]; +// if (remaining == 0) { +// std::cout << "All tokens at clock " << token.color().clock_ << std::endl; +// } + } + + template + void output_token_pushed(token token) { + + } + + graph() : in_port_cb_{*this}, in_port_{in_port_cb_}, out_port_{}, invocations_{} { + buffer_size_ = invocations_.capacity(); + } + + private: + void reset_input(int i) { + inputs_missing_[i] = + } + + // Input/Output ports + in_port_cb in_port_cb_; + multi_in_port_type in_port_; + multi_out_port_type out_port_; + + const int buffer_size_; + + // Clocks and state for execution + std::atomic input_clock_{0}; + std::atomic output_clock_{0}; + + B input_buffer_; + B> inputs_missing_; + + B invocations_; + B output_buffer_; +}; + +} +} +} + +#endif //PLS_DATAFLOW_INTERNAL_GRAPH_H_ diff --git a/lib/pls/include/pls/dataflow/internal/in_port.h b/lib/pls/include/pls/dataflow/internal/in_port.h new file mode 100644 index 0000000..89f9ebe --- /dev/null +++ b/lib/pls/include/pls/dataflow/internal/in_port.h @@ -0,0 +1,122 @@ + +#ifndef PLS_DATAFLOW_INTERNAL_INPUT_H_ +#define PLS_DATAFLOW_INTERNAL_INPUT_H_ + +#include "pls/internal/base/error_handling.h" +#include "token.h" + +namespace pls { +namespace dataflow { +namespace internal { + +/** + * Represents a single, logical input port (no data store, simply signal propagation). + * @tparam T Type of the input port + */ +template +class in_port { + template + friend + class out_port; + + protected: + virtual void token_pushed(token token) = 0; + + private: + bool connected_{false}; + + void push_token(token token) { + token_pushed(token); + } + + void connect() { + if (connected_) { + PLS_ERROR("Must only connect on input once. Disconnect the output pointing to it before reconnecting.") + } + connected_ = true; + } +}; + +/** + * Represents multiple input ports bundled together (a tuple of inputs). + * Allows for a unified callback method to handle multiple typed inputs. + * + * template + * void token_pushed(token token) { Notified when tokens arrive } + * + * @tparam CB The class implementing a callback + * @tparam N Put 0 to start the recursive implementation + * @tparam I A variadic list of input types + */ +template +class multi_in_port { + // end of template recursion + public: + explicit multi_in_port(CB &) {}; +}; +template +class multi_in_port : public in_port { + private: + // Helpers for managing recursive types + using my_type = multi_in_port; + using child_type = multi_in_port; + using value_type = I0; + + public: + explicit multi_in_port(CB &cb) : cb_{cb}, rec_{cb} {}; + + void token_pushed(token token) override { + cb_.template token_pushed(token); + } + + // Helper struct required for recursive access to types by index + template + struct type_at { + }; + template + struct type_at<0, T0, T...> { + using type = T0; + using in_port_type = in_port; + }; + template + struct type_at { + using type = typename type_at::type; + using in_port_type = in_port; + }; + + // Simple interface to get types by index + template + using in_port_type_at = typename type_at::in_port_type; + template + using value_type_at = typename type_at::type; + + // Helper struct required for recursive access to input's by index + template + struct get_at { + static RES_T &get(MY_T &self) { + return get_at::get(self.rec_); + } + }; + template + struct get_at<0, RESULT, CURRENT> { + static RESULT &get(CURRENT &self) { + return self; + } + }; + + // Simple interface to access input's by index + template + in_port_type_at &get() { + return get_at, my_type>::get(*this); + } + + private: + child_type rec_; + CB &cb_; +}; + +} +} +} + +#endif //PLS_DATAFLOW_INTERNAL_INPUT_H_ diff --git a/lib/pls/include/pls/dataflow/internal/input.h b/lib/pls/include/pls/dataflow/internal/input.h deleted file mode 100644 index c5b0f97..0000000 --- a/lib/pls/include/pls/dataflow/internal/input.h +++ /dev/null @@ -1,61 +0,0 @@ - -#ifndef PLS_DATAFLOW_INTERNAL_INPUT_H_ -#define PLS_DATAFLOW_INTERNAL_INPUT_H_ - -#include - -#include "pls/internal/base/error_handling.h" - -#include "token.h" - -namespace pls { -namespace dataflow { -namespace internal { - -class push_token_cb { - public: - virtual void token_pushed(int pos, token_color color) = 0; -}; - -template -class input { - template - friend - class output; - - std::array, P> tokens_; - bool connected_{false}; - - push_token_cb *cb_{nullptr}; - int input_pos_{0}; - - void connect() { - if (connected_) { - PLS_ERROR("Must only connect on input once. Disconnect the output pointing to it before reconnecting.") - } - connected_ = true; - } - - public: - input() = default; - - void push_token(token token) { - tokens_[token.color().get_index(P)] = token; - cb_->token_pushed(input_pos_, token.color()); - } - - token token_at(int p) { - return tokens_[p]; - } - - void set_cb(push_token_cb *cb, int input_pos) { - cb_ = cb; - input_pos_ = input_pos; - } -}; - -} -} -} - -#endif //PLS_DATAFLOW_INTERNAL_INPUT_H_ diff --git a/lib/pls/include/pls/dataflow/internal/inputs.h b/lib/pls/include/pls/dataflow/internal/inputs.h deleted file mode 100644 index 100665d..0000000 --- a/lib/pls/include/pls/dataflow/internal/inputs.h +++ /dev/null @@ -1,112 +0,0 @@ - -#ifndef PLS_DATAFLOW_INTERNAL_INPUTS_H_ -#define PLS_DATAFLOW_INTERNAL_INPUTS_H_ - -#include -#include - -#include "input.h" -#include "outputs.h" - -namespace pls { -namespace dataflow { -namespace internal { - -template -class inputs : push_token_cb { - public: - using raw_types = std::tuple; - using values_type = std::tuple...>; - - template - using raw_type_at = typename std::tuple_element::type; - template - using value_type_at = typename std::tuple_element::type; - static constexpr unsigned int num_values = std::tuple_size::value; - - private: - values_type values_; - std::array, P> required_inputs_; - CB cb_; - - public: - explicit inputs(CB cb) : cb_{cb} { - for (int i = 0; i < P; i++) { - required_inputs_[i] = num_values; - } - init_cb<0, I...>::call(this); - } - inputs(inputs &&other) = delete; - inputs(const inputs &other) = delete; - inputs &operator=(inputs &&other) = delete; - inputs &operator=(const inputs &other) = delete; - - void token_pushed(int pos, token_color color) override { - auto index = color.get_index(P); - int current_required = --required_inputs_[index]; - - cb_.one_input(pos, color); - - if (current_required == 0) { - cb_.all_inputs(color); - required_inputs_[index] = num_values; - } - } - - template - typename std::tuple_element::type &get() { - return std::get(values_); - } - - raw_types get_outputs(int p) { - return fill_output<0, I...>::call(*this, p); - } - template - struct fill_output { - static std::tuple<> call(inputs &self, int p) { - return {}; - } - }; - template - struct fill_output { - static std::tuple call(inputs &self, int p) { - std::tuple().token_at(p).value())> our_tuple{self.get().token_at(p).value()}; - return std::tuple_cat(our_tuple, fill_output::call(self, p)); - } - }; - - void push_to_outputs(outputs &outputs, int input_index, token_color new_color) { - push_to_outputs_rec<0, I...>::call(this, &outputs, input_index, new_color); - } - template - struct push_to_outputs_rec { - static void call(inputs *inputs, outputs *outputs, int input_index, token_color new_color) {} - }; - template - struct push_to_outputs_rec { - static void call(inputs *inputs, outputs *outputs, int input_index, token_color new_color) { - auto token = inputs->get().token_at(input_index); - outputs->template get().push_token({token.value(), new_color}); - push_to_outputs_rec::call(inputs, outputs, input_index, new_color); - } - }; - -// TODO: Change CB code using proper templating to save method calls during execution... - template - struct init_cb { - static void call(inputs *inputs) {} - }; - template - struct init_cb { - static void call(inputs *inputs) { - inputs->get().set_cb(inputs, POS); - init_cb::call(inputs); - } - }; -}; - -} -} -} - -#endif //PLS_DATAFLOW_INTERNAL_INPUTS_H_ diff --git a/lib/pls/include/pls/dataflow/internal/out_port.h b/lib/pls/include/pls/dataflow/internal/out_port.h new file mode 100644 index 0000000..0904547 --- /dev/null +++ b/lib/pls/include/pls/dataflow/internal/out_port.h @@ -0,0 +1,72 @@ + +#ifndef PLS_DATAFLOW_INTERNAL_OUTPUT_H_ +#define PLS_DATAFLOW_INTERNAL_OUTPUT_H_ + +#include + +#include "in_port.h" + +namespace pls { +namespace dataflow { +namespace internal { + +template +class out_port { + public: + void connect(in_port &target) { + if (connected_) { + PLS_ERROR("Must only connect output once. Please disconnect it before reconnecting.") + } + + target.connect(); + target_ = ⌖ + connected_ = true; + } + + void operator>>(in_port &input) { + connect(input); + } + + void push_token(token token) { + target_->push_token(token); + } + + private: + bool connected_{false}; + in_port *target_{nullptr}; +}; + +/** + * Represents multiple output ports bundled together (a tuple of inputs). + * + * @tparam I A variadic list of input types + */ +template +class multi_out_port { + private: + // Helpers for managing recursive types + using value_tuple_type = std::tuple; + using out_port_tupel_type = std::tuple, out_port...>; + + public: + // Simple interface to get types by index + template + using out_port_type_at = typename std::tuple_element::type; + template + using value_type_at = typename std::tuple_element::type; + + // Simple interface to access input's by index + template + out_port_type_at &get() { + return std::get(outputs_); + } + + private: + out_port_tupel_type outputs_; +}; + +} +} +} + +#endif //PLS_DATAFLOW_INTERNAL_OUTPUT_H_ diff --git a/lib/pls/include/pls/dataflow/internal/output.h b/lib/pls/include/pls/dataflow/internal/output.h deleted file mode 100644 index f6f9812..0000000 --- a/lib/pls/include/pls/dataflow/internal/output.h +++ /dev/null @@ -1,41 +0,0 @@ - -#ifndef PLS_DATAFLOW_INTERNAL_OUTPUT_H_ -#define PLS_DATAFLOW_INTERNAL_OUTPUT_H_ - -#include "token.h" -#include "input.h" - -#include "pls/internal/base/error_handling.h" - -namespace pls { -namespace dataflow { -namespace internal { - -template -class output { - input *target_; - bool connected_; - - public: - output() : target_{nullptr}, connected_{false} {}; - - void connect(input &target) { - if (connected_) { - PLS_ERROR("Must only connect output once. Please disconnect it before reconnecting.") - } - - target.connect(); - target_ = ⌖ - connected_ = true; - } - - void push_token(token token) { - target_->push_token(token); - } -}; - -} -} -} - -#endif //PLS_DATAFLOW_INTERNAL_OUTPUT_H_ diff --git a/lib/pls/include/pls/dataflow/internal/outputs.h b/lib/pls/include/pls/dataflow/internal/outputs.h deleted file mode 100644 index 77ae3c1..0000000 --- a/lib/pls/include/pls/dataflow/internal/outputs.h +++ /dev/null @@ -1,38 +0,0 @@ - -#ifndef PLS_DATAFLOW_INTERNAL_OUTPUTS_H_ -#define PLS_DATAFLOW_INTERNAL_OUTPUTS_H_ - -#include - -#include "output.h" - -namespace pls { -namespace dataflow { -namespace internal { - -template -class outputs { - public: - using raw_types = std::tuple; - using values_type = std::tuple...>; - - template - using raw_type_at = typename std::tuple_element::type; - template - using value_type_at = typename std::tuple_element::type; - - private: - values_type values_; - - public: - template - value_type_at &get() { - return std::get(values_); - } -}; - -} -} -} - -#endif //PLS_DATAFLOW_INTERNAL_OUTPUTS_H_ diff --git a/lib/pls/include/pls/dataflow/output.h b/lib/pls/include/pls/dataflow/output.h deleted file mode 100644 index 6988ab9..0000000 --- a/lib/pls/include/pls/dataflow/output.h +++ /dev/null @@ -1,28 +0,0 @@ - -#ifndef PLS_DATAFLOW_OUTPUT_H_ -#define PLS_DATAFLOW_OUTPUT_H_ - -#include "input.h" - -#include "pls/dataflow/internal/output.h" - -namespace pls { -namespace dataflow { - -template -class output { - using internal_type = internal::output; - internal_type &internal_output_; - - public: - explicit output(internal_type &internal_output) : internal_output_{internal_output} {}; - - void operator>>(const input &input) { - internal_output_.connect(input.internal_input_); - } -}; - -} -} - -#endif //PLS_DATAFLOW_OUTPUT_H_ diff --git a/lib/pls/include/pls/dataflow/outputs.h b/lib/pls/include/pls/dataflow/outputs.h index e7a5a80..d4a7967 100644 --- a/lib/pls/include/pls/dataflow/outputs.h +++ b/lib/pls/include/pls/dataflow/outputs.h @@ -2,16 +2,11 @@ #ifndef PLS_DATAFLOW_OUTPUTS_H_ #define PLS_DATAFLOW_OUTPUTS_H_ -#include "internal/outputs.h" -#include "outputs.h" - namespace pls { namespace dataflow { -template +template struct outputs { - template - using internal_outputs = internal::outputs; }; } -- libgit2 0.26.0