Newer
Older
// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
// SPDX-License-Identifier: LGPL-3.0-or-later
#pragma once
Martin Christoph Hierholzer
committed
#include "Flags.h"
#include "VariableNetworkNode.h"
Martin Christoph Hierholzer
committed
#include <list>
Martin Christoph Hierholzer
committed
namespace ChimeraTK {
/********************************************************************************************************************/
/********************************************************************************************************************/
* Convenience type definition which can optionally be used as a shortcut for the type which defines a list of
* tags.
*/
using TAGS = const std::unordered_set<std::string>;
/********************************************************************************************************************/
* Base class for owners of other EntityOwners (e.g. Modules) and Accessors.
* FIXME: Unify with Module class (not straight forward!).
/** Constructor: Create EntityOwner by the given name with the given description. The specified list of
Martin Christoph Hierholzer
committed
* tags will be added to all elements directly or indirectly owned by this instance. */
EntityOwner(std::string name, std::string description, std::unordered_set<std::string> tags = {});
/** Default constructor just for late initialisation */
/** Virtual destructor to make the type polymorphic */
virtual ~EntityOwner() = default;
EntityOwner(EntityOwner&& other) noexcept { operator=(std::move(other)); }
EntityOwner(const EntityOwner& other) = delete;
/** Move assignment operator */
EntityOwner& operator=(EntityOwner&& other) noexcept;
EntityOwner& operator=(const EntityOwner& other) = delete;
/** Get the name of the module instance */
const std::string& getName() const { return _name; }
/** Get the fully qualified name of the module instance, i.e. the name
* containing all module names further up in the hierarchy. */
virtual std::string getQualifiedName() const = 0;
/** Get the description of the module instance */
const std::string& getDescription() const { return _description; }
/** Obtain the full description including the full description of the owner.
*/
virtual std::string getFullDescription() const = 0;
/** Obtain the list of accessors/variables directly associated with this
* instance */
Martin Christoph Hierholzer
committed
std::list<VariableNetworkNode> getAccessorList() const { return _accessorList; }
/** Obtain the list of submodules associated with this instance */
Martin Christoph Hierholzer
committed
std::list<Module*> getSubmoduleList() const { return _moduleList; }
/** Obtain the list of accessors/variables associated with this instance and
* any submodules */
std::list<VariableNetworkNode> getAccessorListRecursive() const;
/** Obtain the list of submodules associated with this instance and any
* submodules */
std::list<Module*> getSubmoduleListRecursive() const;
/** Called inside the constructor of Accessor: adds the accessor to the list
*/
void registerAccessor(VariableNetworkNode accessor);
/** Called inside the destructor of Accessor: removes the accessor from the
* list */
void unregisterAccessor(const VariableNetworkNode& accessor) { _accessorList.remove(accessor); }
/** Register another module as a sub-module. Will be called automatically by
* all modules in their constructors. If addTags is set to false, the tags of
* this EntityOwner will not be set to the module being registered. This is
* e.g. used in the move-constructor of Module to prevent from altering the
* tags in the move operation. */
void registerModule(Module* module, bool addTags = true);
/** Unregister another module as a sub-module. Will be called automatically by
virtual void unregisterModule(Module* module);
/** Add a tag to all Application-type nodes inside this group. It will recurse
* into any subgroups. See VariableNetworkNode::addTag() for additional
* information about tags. */
void addTag(const std::string& tag);
/** Print the full hierarchy to stdout. */
void dump(const std::string& prefix = "") const;
enum class ModuleType { ApplicationModule, ModuleGroup, VariableGroup, ControlSystem, Device, Invalid };
/** Return the module type of this module, or in case of a VirtualModule the
* module type this VirtualModule was derived from. */
virtual ModuleType getModuleType() const = 0;
/** Return the current version number which has been received with the last
Martin Christoph Hierholzer
committed
* push-type read operation. */
virtual VersionNumber getCurrentVersionNumber() const = 0;
/** Set the current version number. This function is called by the push-type
* input accessors in their read functions. */
virtual void setCurrentVersionNumber(VersionNumber versionNumber) = 0;
Martin Christoph Hierholzer
committed
/** Return the data validity flag. If any This function will be called by all output accessors in their write
* functions. */
virtual DataValidity getDataValidity() const = 0;
/** Set the data validity flag to fault and increment the fault counter. This function will be called by all input
* accessors when receiving the a faulty update if the previous update was ok. The caller of this function must
* ensure that calls to this function are paired to a subsequent call to decrementDataFaultCounter(). */
virtual void incrementDataFaultCounter() = 0;
Martin Christoph Hierholzer
committed
/** Decrement the fault counter and set the data validity flag to ok if the counter has reached 0. This function
* will be called by all input accessors when receiving the an ok update if the previous update was faulty. The
* caller of this function must ensure that calles to this function are paired to a previous call to
* incrementDataFaultCounter(). */
virtual void decrementDataFaultCounter() = 0;
Martin Killenberg
committed
/** Use pointer to the module as unique identifier.*/
virtual std::list<EntityOwner*> getInputModulesRecursively(std::list<EntityOwner*> startList) = 0;
Martin Christoph Hierholzer
committed
Martin Killenberg
committed
/** Get the ID of the circular dependency network (0 if none). This information is only available after
* the Application has finalised all connections.
*/
virtual size_t getCircularNetworkHash() const = 0;
Martin Killenberg
committed
/** Check whether this module has declared that it reached the testable mode. */
bool hasReachedTestableMode();
/**
* Create a variable name which will be automatically connected with a constant value. This can be used when a
* constant value.
*/
template<typename T>
std::string constant(T value);
/**
* Prefix for costants created by constant().
*/
static const std::string namePrefixConstant;
protected:
/** Convert HierarchyModifier into path qualification (for backwards compatibility only!) */
// Silence annoying warnings here. The calling functions are deprecated as well, it is enoug
// to get the warning from the callers of that code
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
static std::string applyHierarchyModifierToName(std::string name, HierarchyModifier hierarchyModifier);
#pragma GCC diagnostic pop
/** The name of this instance */
std::string _name;
/** The description of this instance */
std::string _description;
/** List of accessors owned by this instance */
std::list<VariableNetworkNode> _accessorList;
/** List of modules owned by this instance */
std::list<Module*> _moduleList;
/** List of tags to be added to all accessors and modules inside this module
*/
std::unordered_set<std::string> _tags;
Martin Christoph Hierholzer
committed
/** Flag used by the testable mode to identify whether a thread within the EntityOwner has reached the point where
* the testable mode lock is acquired.
* @todo This should be moved to a more proper place in the hierarchy (e.g. ModuleImpl) after InternalModule class
* has been properly unified with the normal Module class. */
std::atomic<bool> _testableModeReached{false};
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/********************************************************************************************************************/
template<typename T>
std::string EntityOwner::constant(T value) {
// Make sure every constant has its unique name to avoid differently typed inputs to be connected to the same
// constant. Note that the template type argument T may not match the expected type by the application, since the
// type of the constant is determined by the input accessor, not by the type of the value argument of this function.
// We hence need to use both the type name and a unique counter as part of the name. The unique counter lives inside
// this template function and hence counts for each type T separately!
static std::atomic<uint64_t> uid(0);
return namePrefixConstant + "/" + DataType(typeid(T)).getAsString() + "/" + std::to_string(uid++) + "/" +
userTypeToUserType<std::string>(value);
}
/********************************************************************************************************************/
Martin Christoph Hierholzer
committed
} /* namespace ChimeraTK */