Newer
Older
Martin Christoph Hierholzer
committed
/*
* VariableNetworkNode.h
*
* Created on: Jun 23, 2016
* Author: Martin Hierholzer
*/
#ifndef CHIMERATK_VARIABLE_NETWORK_NODE_H
#define CHIMERATK_VARIABLE_NETWORK_NODE_H
Martin Christoph Hierholzer
committed
#include <unordered_set>
Martin Christoph Hierholzer
committed
#include <unordered_map>
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
#include <assert.h>
Martin Christoph Hierholzer
committed
#include <boost/shared_ptr.hpp>
#include <mtca4u/NDRegisterAccessorAbstractor.h>
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
#include "Flags.h"
Martin Christoph Hierholzer
committed
#include "ConstantAccessor.h"
Martin Christoph Hierholzer
committed
namespace ChimeraTK {
class VariableNetwork;
class AccessorBase;
class EntityOwner;
Martin Christoph Hierholzer
committed
struct VariableNetworkNode_data;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Pseudo type to identify nodes which can have arbitrary types */
class AnyType {};
Martin Christoph Hierholzer
committed
/** Class describing a node of a variable network */
class VariableNetworkNode {
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
public:
Martin Christoph Hierholzer
committed
/** Copy-constructor: Just copy the pointer to the data storage object */
VariableNetworkNode(const VariableNetworkNode &other);
/** Copy by assignment operator: Just copy the pointer to the data storage object */
VariableNetworkNode& operator=(const VariableNetworkNode &rightHandSide);
Martin Christoph Hierholzer
committed
/** Constructor for an Application node */
VariableNetworkNode(EntityOwner *owner, mtca4u::TransferElementAbstractor *accessorBridge, const std::string &name,
Martin Christoph Hierholzer
committed
VariableDirection direction, std::string unit, size_t nElements, UpdateMode mode,
Martin Christoph Hierholzer
committed
const std::string &description, const std::type_info* valueType,
const std::unordered_set<std::string> &tags={});
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Constructor for a Device node */
Martin Christoph Hierholzer
committed
VariableNetworkNode(const std::string &deviceAlias, const std::string ®isterName, UpdateMode mode,
Martin Christoph Hierholzer
committed
VariableDirection direction, const std::type_info &valTyp=typeid(AnyType), size_t nElements=0);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Constructor for a ControlSystem node */
Martin Christoph Hierholzer
committed
VariableNetworkNode(std::string publicName, VariableDirection direction,
Martin Christoph Hierholzer
committed
const std::type_info &valTyp=typeid(AnyType), size_t nElements=0);
Martin Christoph Hierholzer
committed
/** Constructor for a TriggerReceiver node triggering the data transfer of another network. The additional dummy
* argument is only there to discriminate the signature from the copy constructor and will be ignored. */
VariableNetworkNode(VariableNetworkNode& nodeToTrigger, int);
Martin Christoph Hierholzer
committed
/** Constructor to wrap a VariableNetworkNode_data pointer */
VariableNetworkNode(boost::shared_ptr<VariableNetworkNode_data> pdata);
Martin Christoph Hierholzer
committed
/** Default constructor for an invalid node */
Martin Christoph Hierholzer
committed
VariableNetworkNode();
Martin Christoph Hierholzer
committed
/** Factory function for a constant (a constructor cannot be templated) */
template<typename UserType>
static VariableNetworkNode makeConstant(bool makeFeeder, UserType value=0, size_t length=1);
Martin Christoph Hierholzer
committed
/** Change meta data (name, unit, description and optionally tags). This function may only be used on
* Application-type nodes. If the optional argument tags is omitted, the tags will not be changed. To clear the
* tags, an empty set can be passed. */
void setMetaData(const std::string &name, const std::string &unit, const std::string &description);
void setMetaData(const std::string &name, const std::string &unit, const std::string &description,
const std::unordered_set<std::string> &tags);
Martin Christoph Hierholzer
committed
/** Set the owner network of this node. If an owner network is already set, an assertion will be raised */
void setOwner(VariableNetwork *network);
/** Clear the owner network of this node. */
void clearOwner();
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Set the value type for this node. Only possible of the current value type is undecided (i.e. AnyType). */
Martin Christoph Hierholzer
committed
void setValueType(const std::type_info& newType) const;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Function checking if the node requires a fixed implementation */
bool hasImplementation() const;
/** Compare two nodes */
bool operator==(const VariableNetworkNode& other) const;
bool operator!=(const VariableNetworkNode& other) const;
Martin Christoph Hierholzer
committed
bool operator<(const VariableNetworkNode& other) const;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Connect two nodes */
VariableNetworkNode operator>>(VariableNetworkNode other);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Add a trigger */
VariableNetworkNode operator[](VariableNetworkNode trigger);
/** Check for presence of an external trigger */
Martin Christoph Hierholzer
committed
bool hasExternalTrigger() const;
/** Return the external trigger node. if no external trigger is present, an assertion will be raised. */
Martin Christoph Hierholzer
committed
VariableNetworkNode getExternalTrigger();
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Print node information to std::cout */
Martin Christoph Hierholzer
committed
void dump(std::ostream& stream=std::cout) const;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Check if the node already has an owner */
Martin Christoph Hierholzer
committed
bool hasOwner() const;
/** Add a tag. This function may only be used on Application-type nodes. Valid names for tags only contain
Martin Christoph Hierholzer
committed
* alpha-numeric characters (i.e. no spaces and no special characters). @todo enforce this!*/
void addTag(const std::string &tag);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Getter for the properties */
Martin Christoph Hierholzer
committed
NodeType getType() const;
UpdateMode getMode() const;
VariableDirection getDirection() const;
const std::type_info& getValueType() const;
Martin Christoph Hierholzer
committed
std::string getName() const;
Martin Christoph Hierholzer
committed
std::string getQualifiedName() const;
Martin Christoph Hierholzer
committed
const std::string& getUnit() const;
const std::string& getDescription() const;
VariableNetwork& getOwner() const;
Martin Christoph Hierholzer
committed
VariableNetworkNode getNodeToTrigger();
Martin Christoph Hierholzer
committed
const std::string& getPublicName() const;
const std::string& getDeviceAlias() const;
const std::string& getRegisterName() const;
Martin Christoph Hierholzer
committed
const std::unordered_set<std::string>& getTags() const;
Martin Christoph Hierholzer
committed
void setNumberOfElements(size_t nElements);
size_t getNumberOfElements() const;
mtca4u::TransferElementAbstractor& getAppAccessorNoType();
Martin Christoph Hierholzer
committed
template<typename UserType>
mtca4u::NDRegisterAccessorAbstractor<UserType>& getAppAccessor() const;
Martin Christoph Hierholzer
committed
template<typename UserType>
boost::shared_ptr<mtca4u::NDRegisterAccessor<UserType>> getConstAccessor() const;
Martin Christoph Hierholzer
committed
/** Return the unique ID of this node (will change every time the application is started). */
const void* getUniqueId() const { return pdata.get(); }
/** Change pointer to the accessor. May only be used for application nodes. */
void setAppAccessorPointer(mtca4u::TransferElementAbstractor *accessor);
EntityOwner* getOwningModule() const;
void setOwningModule(EntityOwner *newOwner) const;
Martin Christoph Hierholzer
committed
void accept(Visitor<VariableNetworkNode> &visitor) const;
Martin Christoph Hierholzer
committed
//protected: @todo make protected again (with proper interface extension)
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
boost::shared_ptr<VariableNetworkNode_data> pdata;
};
/*********************************************************************************************************************/
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** We use a pimpl pattern so copied instances of VariableNetworkNode refer to the same instance of the data
* structure and thus stay consistent all the time. */
struct VariableNetworkNode_data {
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
VariableNetworkNode_data() {}
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Type of the node (Application, Device, ControlSystem, Trigger) */
NodeType type{NodeType::invalid};
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Update mode: poll or push */
UpdateMode mode{UpdateMode::invalid};
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Node direction: feeding or consuming */
VariableDirection direction{VariableDirection::invalid};
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Value type of this node. If the type_info is the typeid of AnyType, the actual type can be decided when making
* the connections. */
const std::type_info* valueType{&typeid(AnyType)};
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Engineering unit. If equal to mtca4u::TransferElement::unitNotSet, no unit has been defined (and any unit is allowed). */
std::string unit{mtca4u::TransferElement::unitNotSet};
Martin Christoph Hierholzer
committed
/** Description */
std::string description{""};
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** The network this node belongs to */
VariableNetwork *network{nullptr};
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Pointer to implementation if type == Constant */
boost::shared_ptr<mtca4u::TransferElement> constNode;
Martin Christoph Hierholzer
committed
/** Pointer to implementation if type == Application */
mtca4u::TransferElementAbstractor *appNode{nullptr};
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Pointer to network which should be triggered by this node */
VariableNetworkNode nodeToTrigger{nullptr};
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Pointer to the network providing the external trigger. May only be used for feeding nodes with an
* update mode poll. When enabled, the update mode will be converted into push. */
VariableNetworkNode externalTrigger{nullptr};
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Public name if type == ControlSystem */
std::string publicName;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Accessor name if type == Application */
std::string name;
Martin Christoph Hierholzer
committed
std::string qualifiedName;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Device information if type == Device */
std::string deviceAlias;
std::string registerName;
Martin Christoph Hierholzer
committed
/** Number of elements in the variable. 0 means not yet decided. */
size_t nElements{0};
Martin Christoph Hierholzer
committed
/** Set of tags if type == Application */
std::unordered_set<std::string> tags;
Martin Christoph Hierholzer
committed
/** Map to store triggered versions of this node. The map key is the trigger node and the value is the node
* with the respective trigger added. */
std::map<VariableNetworkNode, VariableNetworkNode> nodeWithTrigger;
Martin Christoph Hierholzer
committed
/** Pointer to the module owning this node */
EntityOwner *owningModule{nullptr};
Martin Christoph Hierholzer
committed
};
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
/*** Implementations *************************************************************************************************/
/*********************************************************************************************************************/
Martin Christoph Hierholzer
committed
template<typename UserType>
VariableNetworkNode VariableNetworkNode::makeConstant(bool makeFeeder, UserType value, size_t length) {
VariableNetworkNode node;
node.pdata = boost::make_shared<VariableNetworkNode_data>();
Martin Christoph Hierholzer
committed
node.pdata->constNode.reset(new ConstantAccessor<UserType>(value, length));
node.pdata->type = NodeType::Constant;
node.pdata->valueType = &typeid(UserType);
node.pdata->nElements = length;
node.pdata->name = "*UNNAMED CONSTANT*";
Martin Christoph Hierholzer
committed
if(makeFeeder) {
node.pdata->direction = VariableDirection::feeding;
node.pdata->mode = UpdateMode::push;
}
else {
node.pdata->direction = VariableDirection::consuming;
node.pdata->mode = UpdateMode::poll;
}
return node;
}
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
Martin Christoph Hierholzer
committed
template<typename UserType>
mtca4u::NDRegisterAccessorAbstractor<UserType>& VariableNetworkNode::getAppAccessor() const {
Martin Christoph Hierholzer
committed
assert(typeid(UserType) == getValueType());
assert(pdata->type == NodeType::Application);
Martin Christoph Hierholzer
committed
auto accessor = static_cast<mtca4u::NDRegisterAccessorAbstractor<UserType>*>(pdata->appNode);
Martin Christoph Hierholzer
committed
assert(accessor != nullptr);
return *accessor;
}
/*********************************************************************************************************************/
Martin Christoph Hierholzer
committed
template<typename UserType>
boost::shared_ptr<mtca4u::NDRegisterAccessor<UserType>> VariableNetworkNode::getConstAccessor() const {
return boost::dynamic_pointer_cast<mtca4u::NDRegisterAccessor<UserType>>(pdata->constNode);
}
Martin Christoph Hierholzer
committed
} /* namespace ChimeraTK */
#endif /* CHIMERATK_VARIABLE_NETWORK_NODE_H */