detail namespace, linking ngcore to nglib

This commit is contained in:
Christopher Lackner 2018-12-12 11:05:17 +01:00
parent 60d4ef13ba
commit 83df85f274
5 changed files with 103 additions and 95 deletions

View File

@ -32,32 +32,32 @@ namespace ngcore
#ifdef WIN #ifdef WIN
// windows does demangling in typeid(T).name() // windows does demangling in typeid(T).name()
std::string demangle(const char* typeinfo) { return typeinfo; } std::string Demangle(const char* typeinfo) { return typeinfo; }
#else #else
std::string demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, std::string Demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo,
nullptr, nullptr,
nullptr, nullptr,
&status); } &status); }
#endif #endif
// clang-tidy should ignore this static object // clang-tidy should ignore this static object
static std::unique_ptr<std::map<std::string, ClassArchiveInfo>> type_register; // NOLINT static std::unique_ptr<std::map<std::string, detail::ClassArchiveInfo>> type_register; // NOLINT
const ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname) const detail::ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname)
{ {
if(type_register == nullptr) type_register = if(type_register == nullptr) type_register =
std::make_unique<std::map<std::string, ClassArchiveInfo>>(); std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
return (*type_register)[classname]; return (*type_register)[classname];
} }
void Archive :: SetArchiveRegister(const std::string& classname, const ClassArchiveInfo& info) void Archive :: SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info)
{ {
if(type_register == nullptr) type_register = if(type_register == nullptr) type_register =
std::make_unique<std::map<std::string, ClassArchiveInfo>>(); std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
(*type_register)[classname] = info; (*type_register)[classname] = info;
} }
bool Archive :: IsRegistered(const std::string& classname) bool Archive :: IsRegistered(const std::string& classname)
{ {
if(type_register == nullptr) type_register = if(type_register == nullptr) type_register =
std::make_unique<std::map<std::string, ClassArchiveInfo>>(); std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
return type_register->count(classname) != 0; return type_register->count(classname) != 0;
} }
} // namespace ngcore } // namespace ngcore

View File

@ -25,12 +25,14 @@ namespace ngcore
void SetLibraryVersion(const std::string& library, const VersionInfo& version); void SetLibraryVersion(const std::string& library, const VersionInfo& version);
class Archive; class Archive;
NGCORE_API std::string demangle(const char* typeinfo); NGCORE_API std::string Demangle(const char* typeinfo);
namespace detail
{
// create new pointer of type T if it is default constructible, else throw // create new pointer of type T if it is default constructible, else throw
template<typename T, typename ...Rest> template<typename T, typename ...Rest>
T* constructIfPossible_impl(Rest... /*unused*/) T* constructIfPossible_impl(Rest... /*unused*/)
{ throw std::runtime_error(std::string(demangle(typeid(T).name())) + " is not default constructible!"); } { throw std::runtime_error(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); }
template<typename T, typename= typename std::enable_if<std::is_constructible<T>::value>::type> template<typename T, typename= typename std::enable_if<std::is_constructible<T>::value>::type>
T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT
@ -55,7 +57,7 @@ namespace ngcore
// Check if class is archivable // Check if class is archivable
template<typename T> template<typename T>
struct is_Archivable struct is_Archivable_struct
{ {
private: private:
template<typename T2> template<typename T2>
@ -80,11 +82,15 @@ namespace ngcore
// to the type stored in this info // to the type stored in this info
std::function<void*(const std::type_info&, void*)> downcaster; std::function<void*(const std::type_info&, void*)> downcaster;
}; };
} // namespace detail
template<typename T>
constexpr bool is_archivable = detail::is_Archivable_struct<T>::value;
// Base Archive class // Base Archive class
class NGCORE_API Archive class NGCORE_API Archive
{ {
bool is_output; const bool is_output;
// how many different shared_ptr/pointer have been (un)archived // how many different shared_ptr/pointer have been (un)archived
int shared_ptr_count, ptr_count; int shared_ptr_count, ptr_count;
// maps for archived shared pointers and pointers // maps for archived shared pointers and pointers
@ -103,11 +109,11 @@ namespace ngcore
template<typename T, typename ... Bases> template<typename T, typename ... Bases>
friend class RegisterClassForArchive; friend class RegisterClassForArchive;
// Returns ClassArchiveInfo of demangled typeid // Returns ClassArchiveInfo of Demangled typeid
static const ClassArchiveInfo& GetArchiveRegister(const std::string& classname); static const detail::ClassArchiveInfo& GetArchiveRegister(const std::string& classname);
// Set ClassArchiveInfo for demangled typeid, this is done by creating an instance of // Set ClassArchiveInfo for Demangled typeid, this is done by creating an instance of
// RegisterClassForArchive<type, bases...> // RegisterClassForArchive<type, bases...>
static void SetArchiveRegister(const std::string& classname, const ClassArchiveInfo& info); static void SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info);
static bool IsRegistered(const std::string& classname); static bool IsRegistered(const std::string& classname);
public: public:
Archive() = delete; Archive() = delete;
@ -121,8 +127,8 @@ namespace ngcore
Archive& operator=(const Archive&) = delete; Archive& operator=(const Archive&) = delete;
Archive& operator=(Archive&&) = delete; Archive& operator=(Archive&&) = delete;
bool Output () { return is_output; } bool Output () const { return is_output; }
bool Input () { return !is_output; } bool Input () const { return !is_output; }
virtual const VersionInfo& getVersion(const std::string& library) = 0; virtual const VersionInfo& getVersion(const std::string& library) = 0;
// Pure virtual functions that have to be implemented by In-/OutArchive // Pure virtual functions that have to be implemented by In-/OutArchive
@ -141,7 +147,7 @@ namespace ngcore
template<typename T> template<typename T>
Archive& operator & (std::complex<T>& c) Archive& operator & (std::complex<T>& c)
{ {
if(is_output) if(Output())
(*this) << c.real() << c.imag(); (*this) << c.real() << c.imag();
else else
{ {
@ -157,10 +163,10 @@ namespace ngcore
Archive& operator & (std::vector<T>& v) Archive& operator & (std::vector<T>& v)
{ {
size_t size; size_t size;
if(is_output) if(Output())
size = v.size(); size = v.size();
(*this) & size; (*this) & size;
if(!is_output) if(Input())
v.resize(size); v.resize(size);
Do(&v[0], size); Do(&v[0], size);
return (*this); return (*this);
@ -168,7 +174,7 @@ namespace ngcore
template<typename T1, typename T2> template<typename T1, typename T2>
Archive& operator& (std::map<T1, T2>& map) Archive& operator& (std::map<T1, T2>& map)
{ {
if(is_output) if(Output())
{ {
(*this) << size_t(map.size()); (*this) << size_t(map.size());
for(auto& pair : map) for(auto& pair : map)
@ -190,7 +196,7 @@ namespace ngcore
} }
// Archive arrays ===================================================== // Archive arrays =====================================================
// this functions can be overloaded in Archive implementations for more efficiency // this functions can be overloaded in Archive implementations for more efficiency
template <typename T, typename = typename std::enable_if<is_Archivable<T>::value>::type> template <typename T, typename = typename std::enable_if<is_archivable<T>>::type>
Archive & Do (T * data, size_t n) Archive & Do (T * data, size_t n)
{ for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; // NOLINT { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; // NOLINT
@ -216,7 +222,7 @@ namespace ngcore
{ for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; // NOLINT { for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; // NOLINT
// Archive a class implementing a (void DoArchive(Archive&)) method ======= // Archive a class implementing a (void DoArchive(Archive&)) method =======
template<typename T, typename=std::enable_if_t<has_DoArchive<T>::value>> template<typename T, typename=std::enable_if_t<detail::has_DoArchive<T>::value>>
Archive& operator & (T& val) Archive& operator & (T& val)
{ {
val.DoArchive(*this); return *this; val.DoArchive(*this); return *this;
@ -237,11 +243,11 @@ namespace ngcore
// Downcasting is only possible for our registered classes // Downcasting is only possible for our registered classes
if(typeid(T) != typeid(*ptr)) if(typeid(T) != typeid(*ptr))
{ {
if(!IsRegistered(demangle(typeid(*ptr).name()))) if(!IsRegistered(Demangle(typeid(*ptr).name())))
throw std::runtime_error(std::string("Archive error: Polymorphic type ") throw std::runtime_error(std::string("Archive error: Polymorphic type ")
+ demangle(typeid(*ptr).name()) + Demangle(typeid(*ptr).name())
+ " not registered for archive"); + " not registered for archive");
reg_ptr = GetArchiveRegister(demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get());
// if there was a true downcast we have to store more information // if there was a true downcast we have to store more information
if(reg_ptr != static_cast<void*>(ptr.get()) ) if(reg_ptr != static_cast<void*>(ptr.get()) )
neededDowncast = true; neededDowncast = true;
@ -255,14 +261,14 @@ namespace ngcore
(*this) & neededDowncast & p; (*this) & neededDowncast & p;
// if we did downcast we store the true type as well // if we did downcast we store the true type as well
if(neededDowncast) if(neededDowncast)
(*this) << demangle(typeid(*ptr).name()); (*this) << Demangle(typeid(*ptr).name());
shared_ptr2nr[reg_ptr] = shared_ptr_count++; shared_ptr2nr[reg_ptr] = shared_ptr_count++;
return *this; return *this;
} }
// if found store the position and if it has to be downcasted and how // if found store the position and if it has to be downcasted and how
(*this) << pos->second << neededDowncast; (*this) << pos->second << neededDowncast;
if(neededDowncast) if(neededDowncast)
(*this) << demangle(typeid(*ptr).name()); (*this) << Demangle(typeid(*ptr).name());
} }
else // Input else // Input
{ {
@ -277,7 +283,7 @@ namespace ngcore
// -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it
if (nr == -1) if (nr == -1)
{ {
T* p; T* p = nullptr;
bool neededDowncast; bool neededDowncast;
(*this) & neededDowncast & p; (*this) & neededDowncast & p;
ptr = std::shared_ptr<T>(p); ptr = std::shared_ptr<T>(p);
@ -333,11 +339,11 @@ namespace ngcore
void* reg_ptr = static_cast<void*>(p); void* reg_ptr = static_cast<void*>(p);
if(typeid(T) != typeid(*p)) if(typeid(T) != typeid(*p))
{ {
if(!IsRegistered(demangle(typeid(*p).name()))) if(!IsRegistered(Demangle(typeid(*p).name())))
throw std::runtime_error(std::string("Archive error: Polymorphic type ") throw std::runtime_error(std::string("Archive error: Polymorphic type ")
+ demangle(typeid(*p).name()) + Demangle(typeid(*p).name())
+ " not registered for archive"); + " not registered for archive");
reg_ptr = GetArchiveRegister(demangle(typeid(*p).name())).downcaster(typeid(T), static_cast<void*>(p)); reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast<void*>(p));
} }
auto pos = ptr2nr.find(reg_ptr); auto pos = ptr2nr.find(reg_ptr);
// if the pointer is not found in the map create a new entry // if the pointer is not found in the map create a new entry
@ -351,18 +357,18 @@ namespace ngcore
} }
else else
throw std::runtime_error(std::string("Archive error: Class ") + throw std::runtime_error(std::string("Archive error: Class ") +
demangle(typeid(*p).name()) + " does not provide a default constructor!"); Demangle(typeid(*p).name()) + " does not provide a default constructor!");
else else
{ {
// if a pointer to a base class is archived, the class hierarchy must be registered // if a pointer to a base class is archived, the class hierarchy must be registered
// to avoid compile time issues we allow this behaviour only for "our" classes that // to avoid compile time issues we allow this behaviour only for "our" classes that
// implement a void DoArchive(Archive&) member function // implement a void DoArchive(Archive&) member function
// To recreate the object we need to store the true type of it // To recreate the object we need to store the true type of it
if(!IsRegistered(demangle(typeid(*p).name()))) if(!IsRegistered(Demangle(typeid(*p).name())))
throw std::runtime_error(std::string("Archive error: Polymorphic type ") throw std::runtime_error(std::string("Archive error: Polymorphic type ")
+ demangle(typeid(*p).name()) + Demangle(typeid(*p).name())
+ " not registered for archive"); + " not registered for archive");
return (*this) << -3 << demangle(typeid(*p).name()) & (*p); return (*this) << -3 << Demangle(typeid(*p).name()) & (*p);
} }
} }
else else
@ -370,7 +376,7 @@ namespace ngcore
(*this) & pos->second; (*this) & pos->second;
bool downcasted = !(reg_ptr == static_cast<void*>(p) ); bool downcasted = !(reg_ptr == static_cast<void*>(p) );
// store if the class has been downcasted and the name // store if the class has been downcasted and the name
(*this) << downcasted << demangle(typeid(*p).name()); (*this) << downcasted << Demangle(typeid(*p).name());
} }
} }
else else
@ -381,7 +387,7 @@ namespace ngcore
p = nullptr; p = nullptr;
else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...)
{ {
p = constructIfPossible<T>(); p = detail::constructIfPossible<T>();
nr2ptr.push_back(p); nr2ptr.push_back(p);
(*this) & *p; (*this) & *p;
} }
@ -457,7 +463,7 @@ namespace ngcore
static void* tryUpcast(const std::type_info& ti, T* p) static void* tryUpcast(const std::type_info& ti, T* p)
{ {
try try
{ return GetArchiveRegister(demangle(typeid(B1).name())).upcaster(ti, static_cast<void*>(dynamic_cast<B1*>(p))); } { return GetArchiveRegister(Demangle(typeid(B1).name())).upcaster(ti, static_cast<void*>(dynamic_cast<B1*>(p))); }
catch(std::exception&) catch(std::exception&)
{ return Caster<T, Brest...>::tryUpcast(ti, p); } { return Caster<T, Brest...>::tryUpcast(ti, p); }
} }
@ -467,7 +473,7 @@ namespace ngcore
if(typeid(B1) == ti) if(typeid(B1) == ti)
return dynamic_cast<T*>(static_cast<B1*>(p)); return dynamic_cast<T*>(static_cast<B1*>(p));
try try
{ return GetArchiveRegister(demangle(typeid(B1).name())).downcaster(ti, static_cast<void*>(dynamic_cast<T*>(static_cast<B1*>(p)))); } { return GetArchiveRegister(Demangle(typeid(B1).name())).downcaster(ti, static_cast<void*>(dynamic_cast<T*>(static_cast<B1*>(p)))); }
catch(std::exception&) catch(std::exception&)
{ return Caster<T, Brest...>::tryDowncast(ti, p); } { return Caster<T, Brest...>::tryDowncast(ti, p); }
} }
@ -482,15 +488,15 @@ namespace ngcore
{ {
static_assert(all_of_tmpl<std::is_base_of<Bases,T>::value...>, static_assert(all_of_tmpl<std::is_base_of<Bases,T>::value...>,
"Variadic template arguments must be base classes of T"); "Variadic template arguments must be base classes of T");
ClassArchiveInfo info; detail::ClassArchiveInfo info;
info.creator = [this,&info](const std::type_info& ti) -> void* info.creator = [this,&info](const std::type_info& ti) -> void*
{ return typeid(T) == ti ? constructIfPossible<T>() { return typeid(T) == ti ? detail::constructIfPossible<T>()
: Archive::Caster<T, Bases...>::tryUpcast(ti, constructIfPossible<T>()); }; : Archive::Caster<T, Bases...>::tryUpcast(ti, detail::constructIfPossible<T>()); };
info.upcaster = [this](const std::type_info& ti, void* p) -> void* info.upcaster = [this](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryUpcast(ti, static_cast<T*>(p)); }; { return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryUpcast(ti, static_cast<T*>(p)); };
info.downcaster = [this](const std::type_info& ti, void* p) -> void* info.downcaster = [this](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryDowncast(ti, p); }; { return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryDowncast(ti, p); };
Archive::SetArchiveRegister(std::string(demangle(typeid(T).name())),info); Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info);
} }

View File

@ -403,7 +403,7 @@ namespace netgen
// Only provide this function if T is archivable // Only provide this function if T is archivable
template<typename T2=T> template<typename T2=T>
auto DoArchive(Archive& archive) -> typename std::enable_if<is_Archivable<T2>::value, void>::type auto DoArchive(Archive& archive) -> typename std::enable_if<is_archivable<T2>, void>::type
{ {
if(archive.Output()) if(archive.Output())
archive << size; archive << size;

View File

@ -32,6 +32,8 @@ if(NOT WIN32)
endif(USE_GUI) endif(USE_GUI)
endif(NOT WIN32) endif(NOT WIN32)
target_link_libraries(nglib PUBLIC ngcore)
target_link_libraries( nglib PRIVATE ${OCC_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${X11_Xmu_LIB} ${JPEG_LIBRARIES} ${MKL_LIBRARIES} ${ZLIB_LIBRARIES} ${OCC_LIBRARIES} ) target_link_libraries( nglib PRIVATE ${OCC_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${X11_Xmu_LIB} ${JPEG_LIBRARIES} ${MKL_LIBRARIES} ${ZLIB_LIBRARIES} ${OCC_LIBRARIES} )
if(USE_OCC AND NOT WIN32) if(USE_OCC AND NOT WIN32)

View File

@ -108,7 +108,7 @@ void testSharedPointer(Archive& in, Archive& out)
{ {
SECTION("Same shared ptr") SECTION("Same shared ptr")
{ {
static_assert(has_DoArchive<SharedPtrHolder>::value, ""); static_assert(detail::has_DoArchive<SharedPtrHolder>::value, "");
SharedPtrAndPtrHolder holder, holder2; SharedPtrAndPtrHolder holder, holder2;
holder.names.push_back(make_shared<string>("name")); holder.names.push_back(make_shared<string>("name"));
holder2.names = holder.names; // same shared ptr holder2.names = holder.names; // same shared ptr