mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-26 05:50:32 +05:00
234 lines
6.7 KiB
C++
234 lines
6.7 KiB
C++
#include "ngcore_api.hpp"
|
|
#include "utils.hpp"
|
|
#include "logging.hpp"
|
|
#include "simd_generic.hpp"
|
|
|
|
#ifdef WIN32
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <windows.h>
|
|
#undef WIN32_LEAN_AND_MEAN
|
|
#else // WIN32
|
|
#include <cxxabi.h>
|
|
#include <dlfcn.h>
|
|
#endif //WIN32
|
|
//
|
|
#include <array>
|
|
#include <filesystem>
|
|
#include <iostream>
|
|
#include <regex>
|
|
#include <string>
|
|
#include <thread>
|
|
|
|
#include "ngstream.hpp"
|
|
|
|
|
|
namespace ngcore
|
|
{
|
|
namespace detail
|
|
{
|
|
// see https://github.com/RobotLocomotion/drake/blob/master/common/nice_type_name.cc
|
|
static const auto demangle_regexes =
|
|
std::array<std::pair<std::regex, std::string>, 8>{
|
|
// Remove unwanted keywords and following space. (\b is word boundary.)
|
|
std::make_pair(std::regex("\\b(class|struct|enum|union) "), ""),
|
|
// Tidy up anonymous namespace.
|
|
{std::regex("[`(]anonymous namespace[')]"), "(anonymous)"},
|
|
// Replace Microsoft __int64 with long long.
|
|
{std::regex("\\b__int64\\b"), "long long"},
|
|
// Temporarily replace spaces we want to keep with "!". (\w is
|
|
// alphanumeric or underscore.)
|
|
{std::regex("(\\w) (\\w)"), "$1!$2"},
|
|
{std::regex(" "), ""}, // Delete unwanted spaces.
|
|
// Some compilers throw in extra namespaces like "__1" or "__cxx11".
|
|
// Delete them.
|
|
{std::regex("\\b__[[:alnum:]_]+::"), ""},
|
|
{std::regex("!"), " "}, // Restore wanted spaces.
|
|
|
|
// Recognize std::string's full name and abbreviate.
|
|
{std::regex("\\bstd::basic_string<char,std::char_traits<char>,"
|
|
"std::allocator<char>>"), "std::string"}
|
|
};
|
|
std::string CleanupDemangledName( std::string s )
|
|
{
|
|
for(const auto & [r, sub] : demangle_regexes)
|
|
s = std::regex_replace (s,r,sub);
|
|
#ifdef EMSCRIPTEN
|
|
// for some reason regex_replace is not working at all
|
|
std::string temp = s;
|
|
s = "";
|
|
for(auto c : temp)
|
|
if(c!=' ')
|
|
s+=c;
|
|
#endif // EMSCRIPTEN
|
|
|
|
return s;
|
|
}
|
|
} // namespace detail
|
|
|
|
// parallel netgen
|
|
int id = 0, ntasks = 1;
|
|
|
|
#ifdef WIN32
|
|
// windows does demangling in typeid(T).name()
|
|
NGCORE_API std::string Demangle(const char* typeinfo) {
|
|
std::string name = typeinfo;
|
|
return detail::CleanupDemangledName(name);
|
|
}
|
|
#else
|
|
NGCORE_API std::string Demangle(const char* typeinfo)
|
|
{
|
|
int status=0;
|
|
try
|
|
{
|
|
char *s = abi::__cxa_demangle(typeinfo, nullptr, nullptr, &status);
|
|
std::string result;
|
|
if (s == nullptr)
|
|
result = typeinfo;
|
|
else
|
|
{
|
|
result = s;
|
|
free(s);
|
|
}
|
|
result = detail::CleanupDemangledName(result);
|
|
return result;
|
|
}
|
|
catch( const std::exception & e )
|
|
{
|
|
GetLogger("utils")->warn("{}:{} cannot demangle {}, status: {}, error:{}", __FILE__, __LINE__, typeinfo, status, e.what());
|
|
}
|
|
std::string name = typeinfo;
|
|
return detail::CleanupDemangledName(name);
|
|
}
|
|
#endif
|
|
|
|
double seconds_per_tick = [] () noexcept
|
|
{
|
|
auto tick_start = GetTimeCounter();
|
|
double tstart = WallTime();
|
|
double tend = WallTime()+0.001;
|
|
|
|
// wait for 1ms and compare wall time with time counter
|
|
while(WallTime()<tend);
|
|
|
|
auto tick_end = GetTimeCounter();
|
|
tend = WallTime();
|
|
|
|
return (tend-tstart)/static_cast<double>(tick_end-tick_start);
|
|
}();
|
|
|
|
const std::chrono::time_point<TClock> wall_time_start = TClock::now();
|
|
|
|
int printmessage_importance = getenv("NG_MESSAGE_LEVEL") ? atoi(getenv("NG_MESSAGE_LEVEL")) : 0;
|
|
bool NGSOStream :: glob_active = true;
|
|
|
|
NGCORE_API int GetCompiledSIMDSize()
|
|
{
|
|
return GetDefaultSIMDSize();
|
|
}
|
|
|
|
NGCORE_API bool IsRangeCheckEnabled()
|
|
{
|
|
#ifdef NETGEN_ENABLE_CHECK_RANGE
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
NGCORE_API std::filesystem::path GetTempFilename()
|
|
{
|
|
static int counter = 0;
|
|
auto path = std::filesystem::temp_directory_path();
|
|
path += ".temp_netgen_file_"+ToString(counter++)+"_"+ToString(GetTimeCounter());
|
|
return path;
|
|
}
|
|
|
|
|
|
SharedLibrary :: SharedLibrary(const std::filesystem::path & lib_name_, std::optional<std::filesystem::path> directory_to_delete_, bool global )
|
|
: lib_name(lib_name_),directory_to_delete(directory_to_delete_)
|
|
{
|
|
Load(lib_name, global);
|
|
}
|
|
|
|
SharedLibrary :: ~SharedLibrary()
|
|
{
|
|
Unload();
|
|
if(directory_to_delete)
|
|
for([[maybe_unused]] auto i : Range(5))
|
|
{
|
|
// on Windows, a (detached?) child process of the compiler/linker might still block the directory
|
|
// wait for it to finish (up to a second)
|
|
try
|
|
{
|
|
std::filesystem::remove_all(*directory_to_delete);
|
|
directory_to_delete = std::nullopt;
|
|
break;
|
|
}
|
|
catch(const std::exception &e)
|
|
{
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
|
}
|
|
}
|
|
if(directory_to_delete)
|
|
std::cerr << "Could not delete " << directory_to_delete->string() << std::endl;
|
|
}
|
|
|
|
void SharedLibrary :: Load( const std::filesystem::path & lib_name_, bool global )
|
|
{
|
|
Unload();
|
|
lib_name = lib_name_;
|
|
#ifdef WIN32
|
|
lib = LoadLibraryW(lib_name.wstring().c_str());
|
|
if (!lib) throw std::runtime_error(std::string("Could not load library ") + lib_name.string());
|
|
#else // WIN32
|
|
auto flags = RTLD_NOW;
|
|
if (global) flags |= RTLD_GLOBAL;
|
|
lib = dlopen(lib_name.c_str(), flags);
|
|
if(lib == nullptr) throw std::runtime_error(dlerror());
|
|
#endif // WIN32
|
|
}
|
|
|
|
void SharedLibrary :: Unload() {
|
|
if(lib)
|
|
{
|
|
#ifdef WIN32
|
|
FreeLibrary((HMODULE)lib);
|
|
#else // WIN32
|
|
int rc = dlclose(lib);
|
|
if(rc != 0) std::cerr << "Failed to close library " << lib_name << std::endl;
|
|
#endif // WIN32
|
|
}
|
|
}
|
|
|
|
void* SharedLibrary :: GetRawSymbol( std::string func_name )
|
|
{
|
|
#ifdef WIN32
|
|
void* func = GetProcAddress((HMODULE)lib, func_name.c_str());
|
|
if(func == nullptr)
|
|
throw std::runtime_error(std::string("Could not find function ") + func_name + " in library " + lib_name.string());
|
|
#else // WIN32
|
|
void* func = dlsym(lib, func_name.c_str());
|
|
if(func == nullptr)
|
|
throw std::runtime_error(dlerror());
|
|
#endif // WIN32
|
|
|
|
return func;
|
|
}
|
|
|
|
void* GetRawSymbol( std::string func_name )
|
|
{
|
|
void * func = nullptr;
|
|
#ifdef WIN32
|
|
throw std::runtime_error("GetRawSymbol not implemented on WIN32");
|
|
#else // WIN32
|
|
func = dlsym(RTLD_DEFAULT, func_name.c_str());
|
|
if(func == nullptr)
|
|
throw std::runtime_error(dlerror());
|
|
#endif // WIN32
|
|
return func;
|
|
}
|
|
|
|
|
|
} // namespace ngcore
|
|
|