* @brief BaseObject is the ”zeroth-level-object” of the architecture.
* Each module in PARTONS is referred to with a unique class name and a unique int used as ID.
*
* Any C++ object in PARTONS can inherit of it. It fulfills several needs:
* 1. It contains a clone function to be used to the factory to provide the user an object identified by a simple key (a string).
* 2. It carries information on the identity of a specific object among others to transmit an explicit message to the logger (i.e. understandable by a human being, not an address in memory).
* 3. It handles Packets to allow systematic computations over lists of inputs e.g. with threads.
* 4. It allows the registry to store pointers to all modules in a generic way.
*/
classBaseObject{
public:
/**
* Constructor.
* Takes a string parameter that represents the class's name of the child instance class.
*
* @param className class's name of child class.
*/
BaseObject(conststd::string&className);
/**
* Default destructor.
*/
virtual~BaseObject();
/**
* Virtual clone function to allow the factory to clone all derived members object stored in the BaseObjectRegistry.
* @return
*/
virtualBaseObject*clone()const;
/**
* Because of the initialization step order of the program, objects are registered in a total random order and some objects depend on others.
* To avoid the problem of pointer resolution order, this method is called by the BaseObjectRegistery after all objects are well registered in it.
* See BaseObjectRegistry class documentation for more details.
*/
virtualvoidresolveObjectDependencies();
/**
* Return a pre-formatted characters string for output visualization of class member's values.
*
* @return a pre-formatted characters string.
*/
virtualstd::stringtoString()const;
/**
* Used to split a complex C++ object into a concatenation of simple types.
*
* @param packet
*/
voidserialize(ElemUtils::Packet&packet)const;
/**
* Used to rebuild a complex C++ object from a concatenation of simple type.
*
* @param packet
*/
voidunserialize(ElemUtils::Packet&packet);
/**
* Overload of < operator to sort BaseObject object by its indexId value.
*
* @param other
* @return
*/
booloperator<(constBaseObject&other)const;
// ##### GETTERS & SETTERS #####
/**
*
* @return Name of last child class.
*/
conststd::string&getClassName()const;
/**
*
* @return Unique id identifying each object.
*/
unsignedintgetObjectId()const;
/**
*
* @return Integer used when object is created from database. It is related to the id column value in the right database table.
*/
intgetIndexId()const;
/**
*
* @param indexId Integer used when object is created from database. It is related to the id column value in the right database table.
*/
voidsetIndexId(intindexId);
protected:
/**
* Copy constructor.
*
* @param other
*/
BaseObject(constBaseObject&other);
/**
* Print info message into logger.
*
* @param functionName Name of the function throwing an information. Use \_\_func\_\_ to set it automatically.
* @param message Message to the logger.
*/
voidinfo(conststd::string&functionName,
conststd::string&message)const;
/**
* Print debug message into logger.
*
* @param functionName ame of the function throwing an information. Use \_\_func\_\_ to set it automatically.
* @param message Message to the logger.
*/
voiddebug(conststd::string&functionName,
conststd::string&message)const;
/**
* Print warning message into logger.
*
* @param functionName ame of the function throwing an information. Use \_\_func\_\_ to set it automatically.
* @param message Message to the logger.
*/
voidwarn(conststd::string&functionName,
conststd::string&message)const;
/**
* Use in automation process to throw exception when a parameter is missing from the XML scenario file.
* @brief Container to store data to be used by base objects.
*
* This class is a container to store data used by base objects in the automation process.
* An object of this class is intended to be created by a XML parser during running PARTONS runtime from a specific XML file, which can be local or can be retrieved from a database.
* Therefore, this class may be seen as a representation of a set of parameters encoded in a XML file, like:
\code{.py}
<kinematics type="GPDKinematic">
<param name="x" value="0.1" />
<param name="xi" value="0.05" />
<param name="t" value="-0.3" />
<param name="MuF2" value="8." />
<param name="MuR2" value="8." />
</kinematics>
\endcode
*/
classBaseObjectData:publicBaseObject{
public:
/**
* Default constructor.
*/
BaseObjectData();
/**
* Assignment constructor.
* @param moduleType Type of module intended to use parameters stored in this class.
* @param moduleClassName Name of module intended to use parameters stored in this class.
*/
BaseObjectData(conststd::string&moduleType,
conststd::string&moduleClassName);
/**
* Destructor.
*/
virtual~BaseObjectData();
/**
* Add submodule, i.e. indicate that this BaseObjectData object has a tree-like structure.
* @param moduleType Type of module intended to use parameters stored in this class.
* @param moduleClassName Name of module intended to use parameters stored in this class.
* @return Reference to added BaseObjectData object.
* Get map to build a tree-like structure of BaseObjectData objects to be used if submodules are used. The keys in the map indicate type of modules intended to use parameters stored in corresponding BaseObjectData objects.
* Type of module intended to use parameters stored in this class.
*/
std::stringm_moduleType;
/**
* Name of module intended to use parameters stored in this class.
*/
std::stringm_moduleClassName;
/**
* Parameters stored in this class.
*/
Parametersm_parameters;
/**
* Map to build a tree-like structure of BaseObjectData objects to be used if submodules are used. The keys in the map indicate type of modules intended to use parameters stored in corresponding BaseObjectData objects.
*/
std::map<std::string,BaseObjectData>m_subModules;
//Mutable keyword is use too indicate that member can be modify in const function. In this case useful with iterator m_it & isAvailable() function.
* @brief Provides a clone (returned as a BaseObject pointer) of an object identified by its class name and previously stored in the BaseObjectRegistry.
* Furthermore, a pointer to each clone is registered in order to destroy it later on if it becomes orphan.\n
* This class is only instantiable by the class Partons to avoid any error at the initialization of the program.
*/
classBaseObjectFactory{
public:
/**
* Default destructor.
*/
virtual~BaseObjectFactory();
/**
* Provides a clone of the desired object class stored in the registry identified by its integer identifier.
*
* @param classId
* @return
*/
BaseObject*newBaseObject(unsignedintclassId);
/**
* Provides a clone of the desired object class stored in the registry identified by its string class name.
// To allow only ObjectFactoryManager class to create a unique of this class.
// Used to avoid multiple singleton class and to avoid multithreading problem especially when getInstance() is called.
// There is a bad behaviour with first instance initialization and mutex.
friendclassObjectFactoryManager;
sf::Mutexm_mutex;///< Mutex to secure concurrent access to the map of instanciated obejcts.
BaseObjectRegistry*m_pBaseObjectRegistry;///< Pointer to ask BaseObjectRegistry pointer associated to a specific object class.
std::map<unsignedint,BaseObject*>m_pInstantiatedObject;///< Store BaseObject pointer created by the factory; used at the end of the program to delete orphan pointer.
/**
* Private default constructor to ensure the creation of a single instance of the class, managed by Parton's class.
* @brief The Registry is the analog of a phonebook, which lists all available objects (modules or services most of the time) identified by a unique integer identifier or by a unique string (class name) for translation. And only one species of each.
*
* From the point of view of software engineering, the registry corresponds to the singleton design pattern which ensures that it is unique.
* When a new module or services are created, the first thing to do is to call this unique instance, and to register the new module or services with a name provided by the developer of the class.
* In turn the Registry gives a unique identifier encoded in a integer variable for performance purposes.
* Registry stores pointers to all objects in a generic way, i.e. whatever their nature are: pointers to GPDModule, to RunningAlphaStrongModule, to AutomationService, etc.
* This is achieved by requiring all objects to derive from a single parent class named BaseObject.
*/
classBaseObjectRegistry{
public:
/**
* Static function to be able to retrieve a unique instance pointer of this class anywhere in the code.
*
* @return a unique instance of this class
*/
staticBaseObjectRegistry*getInstance();
/**
* Default destructor
*/
virtual~BaseObjectRegistry();
/**
* Store a unique instance of a module identified by a unique string character key.
* @param pBaseObject: an instance of the module built by its default constructor.
* But it is impossible to guarantee the order in which they are added to the registry will be made upon the resolution of statics variables (mechanism of self-registration)
* So we need to perform this task just before the use of PARTONS software to resolve dependencies between all kind of registered objects.
*/
voidresolveBaseObjectDependencies();
/**
* Try to find stored object identified by its unique class identifier.
*
* @param classId
* @return reference to object in memory or throw an exception
*/
BaseObject*get(unsignedintclassId)const;
/**
* Try to find stored object identified by its class name.
*
* @param className
* @return reference to object in memory or throw an exception
*/
BaseObject*get(conststd::string&className)const;
/**
* Print information about current state of the registry (size of the registry, which objects are stored, ...).
* Private pointer of this class for a unique instance.
*/
staticBaseObjectRegistry*m_pInstance;
/**
* Private default constructor for a unique instance.
*/
BaseObjectRegistry();
/**
* Because of PARTONS is a program using threads we must ensure that only one object manipulates the registry at the same time to avoid memory access violation.
* It's performed by a mechanism called mutex or semaphore.
*/
mutablesf::Mutexm_mutex;
std::map<unsignedint,BaseObject*>m_baseObjectList;///< List of registered objects identified by their unique integer identifier.
std::map<std::string,BaseObject*>m_translateList;///< List of registered objects identified by their class name.
std::map<std::string,unsignedint>m_classIdByClassName;///< Translation map between class id and class name.
staticunsignedintm_uniqueClassIdCounter;///< Increment unique class identifier.
/**
* For performance purposes, it's faster to compare two integers than two strings when we search for an object in the registry.
* This method return a unique integer identifier when a new class object is added to the registry.
* It's just an integer incremented one by one.
*
* @return Unique identifier by class.
*/
unsignedintgetUniqueClassId();
/**
* Try to find an object into the registry by its class name.
*
* @param className
* @return Pointer to object if class name found into registry, NULL else.