Newer
Older
Martin Christoph Hierholzer
committed
/*
* VariableNetwork.h
*
* Created on: Jun 14, 2016
* Author: Martin Hierholzer
*/
#ifndef CHIMERATK_VARIABLE_NETWORK_H
#define CHIMERATK_VARIABLE_NETWORK_H
#include <list>
#include <string>
Martin Christoph Hierholzer
committed
#include <iostream>
Martin Christoph Hierholzer
committed
#include <typeinfo>
#include <boost/mpl/for_each.hpp>
#include "Flags.h"
namespace ChimeraTK {
class AccessorBase;
/** This class describes a network of variables all connected to each other. */
class VariableNetwork {
public:
/** Define accessor types */
Martin Christoph Hierholzer
committed
enum class NodeType {
Martin Christoph Hierholzer
committed
Device, ControlSystem, Application, invalid
Martin Christoph Hierholzer
committed
};
Martin Christoph Hierholzer
committed
/** Structure describing a node of the network */
struct Node {
Martin Christoph Hierholzer
committed
NodeType type{NodeType::invalid};
Martin Christoph Hierholzer
committed
UpdateMode mode{UpdateMode::invalid};
/** Pointer to Accessor if type == Application */
AccessorBase *appNode{nullptr};
/** Public name if type == ControlSystem */
std::string publicName;
/** Device information if type == Device */
Martin Christoph Hierholzer
committed
std::string deviceAlias;
std::string registerName;
Martin Christoph Hierholzer
committed
/** Function checking if the node requires a fixed implementation */
bool hasImplementation() const {
return type == NodeType::Device || type == NodeType::ControlSystem;
}
/** Print node information to std::cout */
void dump() const {
if(type == NodeType::Application) std::cout << " type = Application" << std::endl;
if(type == NodeType::ControlSystem) std::cout << " type = ControlSystem ('" << publicName << "')" << std::endl;
if(type == NodeType::Device) std::cout << " type = Device (" << deviceAlias << ": "
<< registerName << ")" << std::endl;
}
Martin Christoph Hierholzer
committed
/** Compare two nodes */
bool operator==(const Node& other) const {
if(other.type != type) return false;
if(other.mode != mode) return false;
if(other.appNode != appNode) return false;
if(other.publicName != publicName) return false;
if(other.deviceAlias != deviceAlias) return false;
if(other.registerName != registerName) return false;
return true;
}
bool operator!=(const Node& other) const {
return !operator==(other);
}
Martin Christoph Hierholzer
committed
};
Martin Christoph Hierholzer
committed
/** Add an application-side node (i.e. an Accessor) to the network. */
void addAppNode(AccessorBase &a);
Martin Christoph Hierholzer
committed
/** Add control-system-to-device publication. The given accessor will be used to derive the requred value type.
* The name will be the name of the process variable visible in the control system adapter. */
Martin Christoph Hierholzer
committed
void addFeedingPublication(AccessorBase &a, const std::string& name);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Add control-system-to-device publication. The given accessor will be used to derive the requred value type.
* The name will be the name of the process variable visible in the control system adapter. */
void addFeedingPublication(const std::type_info &typeInfo, const std::string& name);
Martin Christoph Hierholzer
committed
/** Add device-to-control-system publication. */
Martin Christoph Hierholzer
committed
void addConsumingPublication(const std::string& name);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Add a device register as a consuming node (i.e. which will be written by this network) */
void addConsumingDeviceRegister(const std::string &deviceAlias, const std::string ®isterName,
Martin Christoph Hierholzer
committed
UpdateMode mode);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Add a device register as a feeding node (i.e. which will be read from this network) */
void addFeedingDeviceRegister(AccessorBase &a, const std::string &deviceAlias, const std::string ®isterName,
Martin Christoph Hierholzer
committed
UpdateMode mode);
/** Add a device register as a feeding node (i.e. which will be read from this network) */
void addFeedingDeviceRegister(const std::type_info &typeInfo, const std::string &deviceAlias,
const std::string ®isterName, UpdateMode mode);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Check if the network already has a feeding node connected to it. */
bool hasFeedingNode() const;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Count the number of consuming nodes in the network */
size_t countConsumingNodes() const;
/** Count the number of nodes requiring a fixed implementation */
size_t countFixedImplementations() const;
Martin Christoph Hierholzer
committed
/** Check if either of the given accessors is part of this network. If the second argument is omitted, only
* the first accessor will be checked. */
Martin Christoph Hierholzer
committed
bool hasAppNode(AccessorBase *a, AccessorBase *b=nullptr) const;
Martin Christoph Hierholzer
committed
/** Obtain the type info of the UserType. If the network type has not yet been determined (i.e. if no output
* accessor has been assigned yet), the typeid of void will be returned. */
const std::type_info& getValueType() const {
return *valueType;
}
Martin Christoph Hierholzer
committed
/** Return the feeding node */
const Node& getFeedingNode() const { return feeder; }
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Return list of consuming nodes */
const std::list<Node>& getConsumingNodes() const { return consumerList; }
Martin Christoph Hierholzer
committed
/** Dump the network structure to std::cout */
void dump() const;
Martin Christoph Hierholzer
committed
/** Compare two networks */
bool operator==(const VariableNetwork &other) const {
if(other.feeder != feeder) return false;
if(other.valueType != valueType) return false;
if(other.consumerList != consumerList) return false;
return true;
}
bool operator!=(const VariableNetwork &other) const {
return !operator==(other);
}
Martin Christoph Hierholzer
committed
protected:
Martin Christoph Hierholzer
committed
/** Feeding node (i.e. the node providing values to the network) */
Node feeder;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** List of consuming nodes (i.e. the nodes receiving values from the network) */
std::list<Node> consumerList;
Martin Christoph Hierholzer
committed
/** The network value type id. Since in C++, std::type_info is non-copyable and typeid() returns a reference to
* an object with static storage duration, we have to (and can safely) store a pointer here. */
const std::type_info* valueType{&typeid(void)};
};
} /* namespace ChimeraTK */
#endif /* CHIMERATK_VARIABLE_NETWORK_H */