Page MenuHomec4science

id_manager.hh
No OneTemporary

File Metadata

Created
Thu, Jul 4, 15:42

id_manager.hh

/**
* @file id_manager.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Mon Sep 08 23:40:22 2014
*
* @brief This is the generic manager of objects from their IDs (string)
*
* @section LICENSE
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* LibMultiScale is free software: you can redistribute it and/or modify it
* under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* LibMultiScale is distributed in the hope that it will be useful, but
* WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __LIBMULTISCALE_ID_MANAGER_HH__
#define __LIBMULTISCALE_ID_MANAGER_HH__
/* -------------------------------------------------------------------------- */
#include "lm_common.hh"
#include "lm_object.hh"
#include <algorithm>
#include <fstream>
#include <list>
#include <map>
#include <memory>
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
struct UnknownID : public std::runtime_error {
UnknownID(const LMID &id, const std::string &manager_type)
: std::runtime_error("Unknown id: " + id +
" from manager type: " + manager_type),
id(id) {}
LMID id;
};
/* -------------------------------------------------------------------------- */
template <typename T> class IDManager {
public:
friend struct std::default_delete<IDManager<T>>;
typedef std::string typeID;
typedef std::map<typeID, T *> Cont;
protected:
IDManager();
virtual ~IDManager();
public:
static void destroy();
//! reset the communicator
void reset();
//! add a geometry as a shared pointer
typeID addObject(std::shared_ptr<T> g);
//! add a geometry as an object
typeID addObject(T &g);
//! generate a new id automatically
typeID generateNewID();
//! remove a managed object
void removeObject(const typeID &ID);
//! remove a managed object
void removeObject(const T &ID);
//! true if singleton already allocated
static bool allocated() { return static_pointer != nullptr; }
//! applies a functor for each stored entry
template <typename Func> void for_each(Func &&func) {
std::for_each(this->objects.begin(), this->objects.end(),
[&](auto &&pair) { func(*pair.second); });
}
//! return a reference to a geometry from its ID
T &getObject(const typeID &ID);
//! return a shared_pointer from its ID
std::shared_ptr<T> getSharedObject(const typeID &ID);
//! return a casted object from its ID
template <typename Cast> inline Cast &getCastedObject(const typeID &ID);
//! search id of a given geometry
typeID getID(T &obj);
protected:
//! accessor to the singleton manager
template <typename IT> static IT &getManager();
//! mapping between IDs and pointers
std::map<typeID, T *> objects;
//! mapping between IDs and shared pointers
std::map<typeID, std::shared_ptr<T>> shared_pointer_objects;
//! file to which output the object infos
std::ofstream fout;
static std::unique_ptr<IDManager<T>> static_pointer;
std::list<typeID> insert_order;
};
/* -------------------------------------------------------------------------- */
template <typename T>
template <typename IT>
inline IT &IDManager<T>::getManager() {
if (!static_pointer)
static_pointer.reset(new IT());
IT &ref = dynamic_cast<IT &>(*static_pointer);
return ref;
}
/* -------------------------------------------------------------------------- */
template <typename T> inline IDManager<T>::IDManager() {
std::string filename = "log.";
filename += typeinfo<decltype(*this)>();
fout.open(filename.c_str(), std::ios_base::out);
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline typename IDManager<T>::typeID IDManager<T>::generateNewID() {
UInt i = objects.size();
std::stringstream str;
str << "geom" << i;
return str.str();
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline typename IDManager<T>::typeID
IDManager<T>::addObject(std::shared_ptr<T> obj) {
if (obj == nullptr)
LM_FATAL("attempt to register a null pointer as " << typeid(*this).name());
typeID id = obj->getID();
if (objects.count(id) > 0 && objects[id])
LM_FATAL("ID " << id << " has already been used for " << *objects[id]);
DUMP("register object: " << obj.get(), DBG_INFO);
shared_pointer_objects[id] = obj;
objects[id] = obj.get();
DUMPFILE(fout, id << "(" << *obj << ") added to "
<< typeinfo<decltype(*this)>() << " manager");
insert_order.push_back(id);
return id;
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline typename IDManager<T>::typeID IDManager<T>::addObject(T &obj) {
typeID id = obj.getID();
if (objects.count(id) > 0 && objects[id])
LM_FATAL("ID " << id << " has already been used for " << *objects[id]);
objects[id] = &obj;
DUMPFILE(fout, id << "(" << obj << ") added to "
<< typeinfo<decltype(*this)>() << " manager");
insert_order.push_back(id);
return id;
}
/* -------------------------------------------------------------------------- */
template <typename T> inline void IDManager<T>::removeObject(const T &obj) {
typeID ID = obj.getID();
removeObject(ID);
DUMPFILE(fout,
"removed " << ID << " from manager " << typeinfo<decltype(*this)>());
}
/* -------------------------------------------------------------------------- */
template <typename T> inline void IDManager<T>::removeObject(const typeID &ID) {
if (objects.count(ID) == 0) {
DUMP("impossible to delete entry -> unknown id: " << ID, DBG_INFO);
return;
}
objects.erase(ID);
if (shared_pointer_objects.count(ID))
shared_pointer_objects.erase(ID);
insert_order.remove(ID);
}
/* -------------------------------------------------------------------------- */
template <typename T> inline T &IDManager<T>::getObject(const typeID &ID) {
if (objects.count(ID) == 0) {
throw UnknownID(ID, typeinfo<decltype(*this)>());
}
return *objects[ID];
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline std::shared_ptr<T> IDManager<T>::getSharedObject(const typeID &ID) {
if (shared_pointer_objects.count(ID) == 0) {
throw UnknownID(ID, typeinfo<decltype(*this)>());
}
return shared_pointer_objects[ID];
}
/* -------------------------------------------------------------------------- */
template <typename T>
template <typename Cast>
inline Cast &IDManager<T>::getCastedObject(const typeID &ID) {
std::string component_name = ID;
std::string output_name = "";
auto pos = component_name.find(".");
if (pos != std::string::npos) {
output_name = component_name.substr(pos + 1);
component_name = component_name.substr(0, pos);
}
if (objects.count(component_name) == 0) {
throw UnknownID(ID, typeinfo<decltype(*this)>());
}
Cast *ptr = nullptr;
if (output_name != "")
ptr = &objects[component_name]->template evalOutput<Cast>(output_name);
else
ptr = dynamic_cast<Cast *>(objects[component_name]);
if (!ptr) {
LM_FATAL("bad cast for ID: " << ID << " from "
<< typeinfo<decltype(*this)>() << " to "
<< typeinfo<Cast>());
}
return *ptr;
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline typename IDManager<T>::typeID IDManager<T>::getID(T &obj) {
for (auto &&o : objects) {
if (o.second == obj)
return o.first;
}
DUMPFILE(fout, "Warning : auto registering of " << this->getID() << " {\n"
<< *obj << "\n}");
return (addObject(obj));
}
/* -------------------------------------------------------------------------- */
template <typename T> inline IDManager<T>::~IDManager() {
destroy();
DUMPFILE(fout, "all " << typeinfo<decltype(*this)>() << " cleaned...");
fout.close();
}
/* -------------------------------------------------------------------------- */
template <typename T> inline void IDManager<T>::destroy() {
if (static_pointer == nullptr)
return;
static_pointer->shared_pointer_objects.clear();
if (static_pointer)
static_pointer.release();
}
/* -------------------------------------------------------------------------- */
template <typename T> inline void IDManager<T>::reset() {
this->shared_pointer_objects.clear();
this->objects.clear();
this->insert_order.clear();
}
/* -------------------------------------------------------------------------- */
__END_LIBMULTISCALE__
#endif /* __LIBMULTISCALE_ID_MANAGER_HH__ */

Event Timeline