Newer
Older
Martin Christoph Hierholzer
committed
/*
* Application.h
*
* Created on: Jun 07, 2016
* Author: Martin Hierholzer
*/
#ifndef CHIMERATK_APPLICATION_H
#define CHIMERATK_APPLICATION_H
#include <mutex>
Martin Christoph Hierholzer
committed
#include <mtca4u/DeviceBackend.h>
Martin Christoph Hierholzer
committed
#include <ControlSystemAdapter/DevicePVManager.h>
Martin Christoph Hierholzer
committed
#include "ApplicationException.h"
#include "VariableNetwork.h"
#include "Flags.h"
Martin Christoph Hierholzer
committed
#include "ImplementationAdapter.h"
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
namespace ChimeraTK {
Martin Christoph Hierholzer
committed
class ApplicationModule;
class AccessorBase;
Martin Christoph Hierholzer
committed
class InvalidAccessor;
class VariableNetwork;
Martin Christoph Hierholzer
committed
template<typename UserType>
class Accessor;
Martin Christoph Hierholzer
committed
template<typename UserType>
class DeviceAccessor;
Martin Christoph Hierholzer
committed
class Application {
public:
/** Constructor: the first instance will be created explicitly by the control system adapter code. Any second
* instance is not allowed, thus calling the constructor multiple times will throw an exception.
* Design note: We are not using a true singleton pattern, since Application is an abstract base class. The
* actual instance is created as a static variable.
* The application developer should derive his application from this class and implement the initialise()
* function only. */
Martin Christoph Hierholzer
committed
Application(const std::string& name);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** The destructor will remove the global pointer to the instance and allows creating another instance
* afterwards. This is mostly useful for writing tests, as it allows to run several applications sequentially
* in the same executable. Note that any ApplicationModules etc. owned by this Application are no longer
* valid after destroying the Application and must be destroyed as well (or at least no longer used). */
virtual ~Application();
Martin Christoph Hierholzer
committed
/** Set the process variable manager. This will be called by the control system adapter initialisation code. */
void setPVManager(boost::shared_ptr<mtca4u::DevicePVManager> const &processVariableManager) {
_processVariableManager = processVariableManager;
}
/** Obtain the process variable manager. */
boost::shared_ptr<mtca4u::DevicePVManager> getPVManager() {
return _processVariableManager;
}
/** Initialise and run the application */
void run();
Martin Christoph Hierholzer
committed
/** Instead of running the application, just initialise it and output the published variables to an XML file. */
void generateXML();
Martin Christoph Hierholzer
committed
/** Obtain instance of the application. Will throw an exception if called before the instance has been
* created by the control system adapter. */
static Application& getInstance() {
// @todo TODO Throw the exception if instance==nullptr !!!
return *instance;
}
Martin Christoph Hierholzer
committed
/** Output the connections requested in the initialise() function to std::cout. This may be done also before
* makeConnections() has been called. */
void dumpConnections();
Martin Christoph Hierholzer
committed
protected:
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
friend class ApplicationModule;
Martin Christoph Hierholzer
committed
friend class VariableNetwork;
Martin Christoph Hierholzer
committed
friend class VariableNetworkNode;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
template<typename UserType>
friend class Accessor;
Martin Christoph Hierholzer
committed
/** To be implemented by the user: Instantiate all application modules and connect the variables to each other */
virtual void initialise() = 0;
/** Make the connections between accessors as requested in the initialise() function. */
void makeConnections();
Martin Christoph Hierholzer
committed
/** Make the connections for a single network */
void makeConnectionsForNetwork(VariableNetwork &network);
/** UserType-dependent part of makeConnectionsForNetwork() */
Martin Christoph Hierholzer
committed
template<typename UserType>
void typedMakeConnection(VariableNetwork &network);
Martin Christoph Hierholzer
committed
/** Register a connection between two Accessors */
void connectAccessors(AccessorBase &a, AccessorBase &b);
Martin Christoph Hierholzer
committed
/** Register a connection between two VariableNetworkNode */
Martin Christoph Hierholzer
committed
VariableNetwork& connect(VariableNetworkNode a, VariableNetworkNode b);
/** Return a VariableNetworkNode for a device register with a not yet defined direction */
template<typename UserType>
VariableNetworkNode DevReg(const std::string &deviceAlias, const std::string ®isterName, UpdateMode mode);
VariableNetworkNode DevReg(const std::string &deviceAlias, const std::string ®isterName, UpdateMode mode,
const std::type_info &valTyp=typeid(AnyType));
/** Return a VariableNetworkNode for a control system variable with a not yet defined direction */
template<typename UserType>
VariableNetworkNode CtrlVar(const std::string &publicName);
VariableNetworkNode CtrlVar(const std::string &publicName, const std::type_info &valTyp=typeid(AnyType));
Martin Christoph Hierholzer
committed
/** Return a VariableNetworkNode for a feeding device register (i.e. a register that will be read by the application) */
template<typename UserType>
Martin Christoph Hierholzer
committed
VariableNetworkNode feedingDevReg(const std::string &deviceAlias, const std::string ®isterName, UpdateMode mode);
VariableNetworkNode feedingDevReg(const std::string &deviceAlias, const std::string ®isterName, UpdateMode mode,
Martin Christoph Hierholzer
committed
const std::type_info &valTyp=typeid(AnyType));
/** Return a VariableNetworkNode for a consuming control system variable */
template<typename UserType>
Martin Christoph Hierholzer
committed
VariableNetworkNode consumingCtrlVar(const std::string &publicName);
VariableNetworkNode consumingCtrlVar(const std::string &publicName, const std::type_info &valTyp=typeid(AnyType));
Martin Christoph Hierholzer
committed
/** Return a VariableNetworkNode for a consuming control system variable */
template<typename UserType>
Martin Christoph Hierholzer
committed
VariableNetworkNode feedingCtrlVar(const std::string &publicName);
VariableNetworkNode feedingCtrlVar(const std::string &publicName, const std::type_info &valTyp=typeid(AnyType));
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Register a connection between a device read-only register and the control system adapter */
template<typename UserType>
Martin Christoph Hierholzer
committed
void feedDeviceRegisterToControlSystem(const std::string &deviceAlias, const std::string ®isterName,
Martin Christoph Hierholzer
committed
const std::string& publicName, AccessorBase &trigger=InvalidAccessor());
Martin Christoph Hierholzer
committed
/** Register a connection between a device write-only register and the control system adapter */
template<typename UserType>
Martin Christoph Hierholzer
committed
void consumeDeviceRegisterFromControlSystem(const std::string &deviceAlias, const std::string ®isterName,
Martin Christoph Hierholzer
committed
const std::string& publicName);
Martin Christoph Hierholzer
committed
/** Perform the actual connection of an accessor to a device register */
Martin Christoph Hierholzer
committed
template<typename UserType>
boost::shared_ptr<mtca4u::ProcessVariable> createDeviceAccessor(const std::string &deviceAlias,
const std::string ®isterName, VariableDirection direction, UpdateMode mode);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Create a process variable with the PVManager, which is exported to the control system adapter */
Martin Christoph Hierholzer
committed
template<typename UserType>
boost::shared_ptr<mtca4u::ProcessVariable> createProcessScalar(VariableDirection direction,
const std::string &name);
Martin Christoph Hierholzer
committed
/** Create a local process variable which is not exported. The first element in the returned pair will be the
* sender, the second the receiver. */
Martin Christoph Hierholzer
committed
template<typename UserType>
Martin Christoph Hierholzer
committed
std::pair< boost::shared_ptr<mtca4u::ProcessVariable>, boost::shared_ptr<mtca4u::ProcessVariable> >
Martin Christoph Hierholzer
committed
createProcessScalar();
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Register an application module with the application. Will be called automatically by all modules in their
* constructors. */
void registerModule(ApplicationModule &module) {
moduleList.push_back(&module);
}
Martin Christoph Hierholzer
committed
/** The name of the application */
std::string applicationName;
Martin Christoph Hierholzer
committed
/** List of application modules */
std::list<ApplicationModule*> moduleList;
Martin Christoph Hierholzer
committed
/** List of ImplementationAdapters */
std::list<boost::shared_ptr<ImplementationAdapterBase>> adapterList;
Martin Christoph Hierholzer
committed
/** List of variable networks */
std::list<VariableNetwork> networkList;
Martin Christoph Hierholzer
committed
/** Find the network containing one of the given registers. If no network has been found, create an empty one
* and add it to the networkList. */
VariableNetwork& findOrCreateNetwork(AccessorBase *a, AccessorBase *b);
VariableNetwork& findOrCreateNetwork(AccessorBase *a);
/** Find the network containing one of the given registers. If no network has been found, invalidNetwork
* is returned. */
VariableNetwork& findNetwork(AccessorBase *a);
/** Instance of VariableNetwork to indicate an invalid network */
VariableNetwork invalidNetwork;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Pointer to the process variable manager used to create variables exported to the control system */
boost::shared_ptr<mtca4u::DevicePVManager> _processVariableManager;
/** Pointer to the only instance of the Application */
static Application *instance;
/** Mutex for thread-safety when setting the instance pointer */
static std::mutex instance_mutex;
Martin Christoph Hierholzer
committed
/** Map of DeviceBackends used by this application. The map key is the alias name from the DMAP file */
std::map<std::string, boost::shared_ptr<mtca4u::DeviceBackend>> deviceMap;
Martin Christoph Hierholzer
committed
};
} /* namespace ChimeraTK */
#endif /* CHIMERATK_APPLICATION_H */