Skip to content

Instantly share code, notes, and snippets.

@hgaiser
Created February 26, 2019 15:17
Show Gist options
  • Save hgaiser/f9220db1979274297476adddd52cf506 to your computer and use it in GitHub Desktop.
Save hgaiser/f9220db1979274297476adddd52cf506 to your computer and use it in GitHub Desktop.
#include "fizyr_flow.hpp"
void Variable::operator=(std::any v) {
// Copy the new value.
value = v;
// Check if we can run ops that haven't been executed yet.
for (auto const & op: operators)
if (op->inputsReady() && !op->executed()) {
op->_execute();
}
// Optionally notify listeners that this value has been updated.
for (auto const & callback: callbacks) { callback(); }
};
/// Simple Operator that sums all its inputs.
template<typename T>
class AddOperator: public Operator {
public:
AddOperator(std::string name): Operator(name) {}
virtual void createOutputs() {
// We create only one output.
outputs_.emplace_back(std::make_shared<Variable>(name_ + "/output"));
}
virtual void execute() {
// Sum all inputs together.
T sum;
for (auto const & input: inputs_) {
sum += std::any_cast<T>(input->value);
}
// Finally, set the output to the sum.
*outputs_[0] = sum;
}
};
int main() {
// Create input Variables.
auto input_1 = std::make_shared<Variable>("input_1");
auto input_2 = std::make_shared<Variable>("input_2");
// Create two AddOperators.
auto add_output_1 = (*std::make_shared<AddOperator<int>>("simple_add_op"))({input_1, input_2})[0];
auto add_output_2 = (*std::make_shared<AddOperator<int>>("second_add_op"))({add_output_1, input_1})[0];
// Add a callback to print when add_output_2 has been updated.
add_output_2->addCallback([add_output_2] () {
std::cout << "Variable " << add_output_2->name << " has been set to " << std::any_cast<int>(add_output_2->value) << std::endl;
});
// Set the values for the input, this automatically triggers Operators.
*input_1 = 5;
*input_2 = 6;
// Print the input and output values.
std::cout << std::any_cast<int>(input_1->value) << std::endl;
std::cout << std::any_cast<int>(input_2->value) << std::endl;
std::cout << std::any_cast<int>(add_output_1->value) << std::endl;
std::cout << std::any_cast<int>(add_output_2->value) << std::endl;
}
#include <iostream>
#include <vector>
#include <functional>
#include <optional>
#include <any>
#include <memory>
class Operator;
/// Represents a piece of data in the graph.
class Variable {
public:
/// Callbacks are called whenever the Variable changes values.
using Callback = std::function<void ()>;
Variable(std::string name) : name{name} {}
/// List of Operators that this Variable is connected to.
std::vector<std::shared_ptr<Operator>> operators;
/// List of callbacks to call when this Variable changes.
std::vector<Callback> callbacks;
/// The name of the Variable.
std::string name;
/// The Value of the Variable.
std::any value;
/// Checks to see if this Variable contains data.
operator bool() const { return value.has_value(); };
/// Updates the Variable to contain new data.
void operator=(std::any v);
/// Adds a callback which is called when this Variable is updated.
void addCallback(Callback callback) {
callbacks.push_back(callback);
}
};
/// Represents an action on one or more pieces of data.
class Operator: public std::enable_shared_from_this<Operator> {
protected:
/// List of input Variables.
std::vector<std::shared_ptr<Variable>> inputs_;
/// List of Variables that will be set after execution.
std::vector<std::shared_ptr<Variable>> outputs_;
/// Holds the state of this Operator.
bool executed_ = false;
/// The name of this Operator.
std::string name_;
public:
Operator(std::string name) : name_{name} {}
/// Constructs the Operator, returns the output Variables.
std::vector<std::shared_ptr<Variable>> operator() (std::vector<std::shared_ptr<Variable>> inputs) {
// Simply copy the inputs.
inputs_ = inputs;
// For all inputs, add this Operator as part of their list of Operators.
for (auto & input: inputs) {
input->operators.emplace_back(shared_from_this());
}
// Create outputs (virtual function).
createOutputs();
return outputs_;
}
/// Check to see if all inputs have values.
bool inputsReady() {
for (auto const & input: inputs_)
if (!(*input)) return false;
return true;
}
/// Execution wrapper, sets executed_ to true.
void _execute() {
execute();
executed_ = true;
}
/// Return if this Operator has already been executed.
bool executed() { return executed_; }
/// Return the name of this Operator.
std::string name() { return name_; };
/// Function that populates the outputs_ list.
virtual void createOutputs() = 0;
/// Function that runs on the inputs_ list and puts the results in the outputs_ list.
virtual void execute() = 0;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment