Link Search Menu Expand Document

Flux

The Flux base class gathers all the inputs or all the outputs for a given node. Parameters on a node are considered to be inputs to a node.

Flux base class header.

struct InputTraits {
  typedef InputCompute IOCompute;
  static const EntityDID IOComputeEntityDID = EntityDID::kInputEntity;
  static const ComponentIID FluxIID = ComponentIID::kIInputs;
  static const ComponentDID FluxDID = ComponentDID::kInputs;
  static const char* folder_name;
};

struct OutputTraits {
  typedef OutputCompute IOCompute;
  static const EntityDID IOComputeEntityDID = EntityDID::kOutputEntity;
  static const ComponentIID FluxIID = ComponentIID::kIOutputs;
  static const ComponentDID FluxDID = ComponentDID::kOutputs;
  static const char* folder_name;
};

//--------------------------------------------------------------------------
// The Flux base class maintains a record of either the inputs or outputs of
// a nodal compute.
//--------------------------------------------------------------------------

template <class Traits>
class COMPUTES_EXPORT Flux: public Component {
 public:
  static ComponentIID kIID() {
      return Traits::FluxIID;
  }
  static ComponentDID kDID() {
    return Traits::FluxDID;
  }

  Flux(Entity* entity);
  virtual ~Flux();

  // Our relative positioning.
  virtual size_t get_exposed_index(const std::string& name) const;
  virtual size_t get_num_exposed() const;
  virtual size_t get_num_hidden() const;
  virtual size_t get_total() const;

  virtual const std::unordered_map<std::string, Dep<typename Traits::IOCompute> >& get_hidden() const;
  virtual const std::unordered_map<std::string, Dep<typename Traits::IOCompute> >& get_exposed() const;
  virtual const std::unordered_map<std::string, Dep<typename Traits::IOCompute> >& get_all() const;

  virtual bool has(const std::string& name) const;


 protected:

  virtual const Dep<typename Traits::IOCompute>& get(const std::string& name) const;

  // Our state.
  virtual void update_wires();
  virtual void gather(std::unordered_map<std::string, size_t>& exposed_ordering,
                      std::unordered_map<std::string, Dep<typename Traits::IOCompute> >& hidden,
                      std::unordered_map<std::string, Dep<typename Traits::IOCompute> >& exposed,
                      std::unordered_map<std::string, Dep<typename Traits::IOCompute> >& all);

  Dep<typename Traits::IOCompute> _null;
  Dep<BaseNodeGraphManipulator> _manipulator;

  // Alphabetical ordering of exposed inputs/outputs.
  std::unordered_map<std::string, size_t> _exposed_ordering;
  std::unordered_map<std::string, Dep<typename Traits::IOCompute> > _hidden;
  std::unordered_map<std::string, Dep<typename Traits::IOCompute> > _exposed;
  std::unordered_map<std::string, Dep<typename Traits::IOCompute> > _all;
};

Output base class implementation.

const char* InputTraits::folder_name = kInputsFolderName;
const char* OutputTraits::folder_name = kOutputsFolderName;


template<class Traits>
Flux<Traits>::Flux(Entity* entity)
    : Component(entity, kIID(), kDID()),
      _manipulator(this),
      _null(this) {
  get_dep_loader()->register_fixed_dep(_manipulator, Path());
}

template<class Traits>
Flux<Traits>::~Flux() {
}

template<class Traits>
void Flux<Traits>::update_wires() {
  internal();

  std::unordered_map<std::string, size_t> next_exposed_ordering;
  std::unordered_map<std::string, Dep<typename Traits::IOCompute> > next_hidden;
  std::unordered_map<std::string, Dep<typename Traits::IOCompute> > next_exposed;
  std::unordered_map<std::string, Dep<typename Traits::IOCompute> > next_all;
  gather(next_exposed_ordering, next_hidden, next_exposed, next_all);

  // If we're already up to date, then return right away.
  if (next_exposed_ordering == _exposed_ordering &&
      next_hidden == _hidden &&
      next_exposed == _exposed &&
      next_all == _all) {
    return;
  }

  // Update our values.
  _exposed_ordering = next_exposed_ordering;
  _hidden = next_hidden;
  _exposed = next_exposed;
  _all = next_all;

  // Update the topologies.
  if (Traits::FluxDID == ComponentDID::kOutputs) {
    _manipulator->set_output_topology(our_entity(), _exposed_ordering);
  } else if (Traits::FluxDID == ComponentDID::kInputs) {
    _manipulator->set_input_topology(our_entity(), _exposed_ordering);
  }
}

template<class Traits>
void Flux<Traits>::gather(std::unordered_map<std::string, size_t>& exposed_ordering,
                          std::unordered_map<std::string, Dep<typename Traits::IOCompute> >& hidden,
                          std::unordered_map<std::string, Dep<typename Traits::IOCompute> >& exposed,
                          std::unordered_map<std::string, Dep<typename Traits::IOCompute> >& all) {
  internal();

  exposed_ordering.clear();
  hidden.clear();
  exposed.clear();
  exposed_ordering.clear();

  std::vector<std::string> exposed_names;

  // Loop through all the inputs or outputs.
  Entity* space = has_entity(Path({".",Traits::folder_name}));
  if (space) {
    const Entity::NameToChildMap& children = space->get_children();
    for (auto iter: children) {
      Entity* child = iter.second;
      // If the child is not an input or output, then skip it.
      if (child->get_did() != Traits::IOComputeEntityDID) {
        continue;
      }
      // Grab a dep on the input or output.
      Dep<typename Traits::IOCompute> dep = get_dep<typename Traits::IOCompute>(child);
      if (dep) {
        if (dep->is_exposed()) {
          // If the input or output is exposed, record it in the exposed set.
          exposed.insert({child->get_name(),dep});
          exposed_names.push_back(child->get_name());
        } else {
          // If the input or output is not exposed, record it in the hidden set.
          hidden.insert({child->get_name(),dep});
        }
      }
    }
  }

  // Sort the exposed inputs/outputs alphabetically.
  std::sort(exposed_names.begin(), exposed_names.end());
  for (size_t i=0; i<exposed_names.size(); ++i) {
    exposed_ordering[exposed_names[i]] = i;
  }

  // Cache a merged map of the exposed and hidden.
  all = exposed;
  all.insert(hidden.begin(), hidden.end());
}

template<class Traits>
size_t Flux<Traits>::get_exposed_index(const std::string& name) const {
  external();
  if (_exposed_ordering.count(name)) {
    return _exposed_ordering.at(name);
  }
  return -1;
}

template<class Traits>
size_t Flux<Traits>::get_num_exposed() const {
  external();
  return _exposed.size();
}

template<class Traits>
size_t Flux<Traits>::get_num_hidden() const {
  external();
  return _hidden.size();
}

template<class Traits>
size_t Flux<Traits>::get_total() const {
  external();
  return _exposed.size() + _hidden.size();
}

template<class Traits>
const std::unordered_map<std::string, Dep<typename Traits::IOCompute> >& Flux<Traits>::get_hidden() const {
  external();
  return _hidden;
}

template<class Traits>
const std::unordered_map<std::string, Dep<typename Traits::IOCompute> >& Flux<Traits>::get_exposed() const {
  external();
  return _exposed;
}

template<class Traits>
const std::unordered_map<std::string, Dep<typename Traits::IOCompute> >& Flux<Traits>::get_all() const {
  external();
  return _all;
}

template<class Traits>
bool Flux<Traits>::has(const std::string& name) const {
  external();
  if (_all.count(name)) {
    return true;
  }
  return false;
}

template<class Traits>
const Dep<typename Traits::IOCompute>& Flux<Traits>::get(const std::string& name) const {
  external();
  if (_all.count(name)) {
    return _all.at(name);
  }
  return _null;
}