Newer
Older
Martin Christoph Hierholzer
committed
/*
* Module.h
*
* Created on: Jun 27, 2016
* Author: Martin Hierholzer
*/
#ifndef CHIMERATK_MODULE_H
#define CHIMERATK_MODULE_H
Martin Christoph Hierholzer
committed
#include "VariableNetworkNode.h"
Martin Christoph Hierholzer
committed
#include "EntityOwner.h"
Martin Christoph Hierholzer
committed
namespace ChimeraTK {
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Base class for ApplicationModule, DeviceModule and ControlSystemModule, to have a common interface for these
* module types. */
Martin Christoph Hierholzer
committed
class Module : public EntityOwner {
Martin Christoph Hierholzer
committed
public:
/** Constructor: register the module with its owner. If eliminateHierarchy is true, the hierarchy level
* introduced by this module will be eliminated from the "dynamic" data model (see
* EntityOwner::setEliminateHierarchy()). The tags given as the last argument are added to all variables
* in this module recursively (see EntityOwner::addTag()). */
Module(EntityOwner *owner, const std::string &name, const std::string &description,
bool eliminateHierarchy=false, const std::unordered_set<std::string> &tags={});
Martin Christoph Hierholzer
committed
/** Default constructor: Allows late initialisation of modules (e.g. when creating arrays of modules).
*
* This construtor also has to be here to mitigate a bug in gcc. It is needed to allow constructor
* inheritance of modules owning other modules. This constructor will not actually be called then.
* See this bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67054 */
Module() : EntityOwner("invalid", "invalid module"), _owner{nullptr} {}
Martin Christoph Hierholzer
committed
/** Destructor */
Martin Christoph Hierholzer
committed
virtual ~Module();
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Move constructor */
Module(Module &&other)
: EntityOwner(std::move(other))
{
_owner = other._owner;
_owner->registerModule(this, false);
// note: the other module unregisters itself in its destructor - will will be called next after any move operation
Martin Christoph Hierholzer
committed
}
Module& operator=(Module &&other) {
_name = std::move(other._name);
_description = std::move(other._description);
_owner = other._owner;
_owner->registerModule(this, false);
Martin Christoph Hierholzer
committed
accessorList = std::move(other.accessorList);
moduleList = std::move(other.moduleList);
_eliminateHierarchy = other._eliminateHierarchy;
_tags = std::move(other._tags);
// note: the other module unregisters itself in its destructor - will will be called next after any move operation
Martin Christoph Hierholzer
committed
return *this;
}
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Delete other assignment operators */
Module& operator=(Module &other) = delete;
Module& operator=(const Module &other) = delete;
Martin Christoph Hierholzer
committed
/** Prepare the execution of the module. This function is called before any module is started (including internal
* modules like FanOuts) and before the initial values of the variables are pushed into the queues. */
Martin Christoph Hierholzer
committed
virtual void prepare() {};
/** Execute the module. */
virtual void run() {};
/** Terminate the module. Must/will be called before destruction, if run() was called previously. */
Martin Christoph Hierholzer
committed
virtual void terminate() {};
Martin Christoph Hierholzer
committed
/** Wait for receiving an update for any of the push-type variables in the group. Any poll-type variables are
* read after receiving the update. If no push-type variables are in the group, this function will just read
* all variables. The returned TransferElement will be the push-type variable which has been updated. */
boost::shared_ptr<mtca4u::TransferElement> readAny();
Martin Christoph Hierholzer
committed
/** Read all readable variables in the group. If there are push-type variables in the group, this call will block
* until all of the variables have received an update. All push-type variables are read first, the poll-type
* variables are therefore updated with the latest values upon return. */
Martin Christoph Hierholzer
committed
void readAll();
/** Just call readNonBlocking() on all readable variables in the group. */
Martin Christoph Hierholzer
committed
void readAllNonBlocking();
/** Just call readLatest() on all readable variables in the group. */
Martin Christoph Hierholzer
committed
void readAllLatest();
/** Just call write() on all writable variables in the group. */
Martin Christoph Hierholzer
committed
void writeAll();
Martin Christoph Hierholzer
committed
/** Function call operator: Return VariableNetworkNode of the given variable name */
Martin Christoph Hierholzer
committed
virtual VariableNetworkNode operator()(const std::string& variableName) const;
Martin Christoph Hierholzer
committed
/** Subscript operator: Return sub-module of the given name */
Martin Christoph Hierholzer
committed
virtual Module& operator[](const std::string& moduleName) const;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/**
* Connect the entire module into another module. All variables inside this module and all
Martin Christoph Hierholzer
committed
* submodules are connected to the target module. All variables and submodules must have an equally
* named and typed counterpart in the target module (or the target module allows creation of
* such entities, as in case of a ControlSystemModule). The target module may contain additional
* variables or submodules, which are ignored.
*
* If an optional trigger node is specified, this trigger node is applied to all poll-type output variables
* of the target module, which are being connected during this operation, if the corresponding variable
Martin Christoph Hierholzer
committed
* in this module is push-type.
Martin Christoph Hierholzer
committed
*/
void connectTo(const Module &target, VariableNetworkNode trigger={}) const;
std::string getQualifiedName() const override {
Martin Christoph Hierholzer
committed
return ( (_owner != nullptr) ? _owner->getQualifiedName() : "" ) + "/" + _name;
}
/** Set a new owner. The caller has to take care himself that the Module gets unregistered with the old owner
* and registered with the new one. Do not use in user code! */
void setOwner(EntityOwner *newOwner) {
_owner = newOwner;
}
EntityOwner* getOwner() const { return _owner; }
Martin Christoph Hierholzer
committed
protected:
/** Owner of this instance */
EntityOwner *_owner{nullptr};
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
};
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
} /* namespace ChimeraTK */
#endif /* CHIMERATK_MODULE_H */