#ifndef NETGEN_CORE_UTILS_HPP #define NETGEN_CORE_UTILS_HPP #include #include #include #include #include #include #include "ngcore_api.hpp" // for NGCORE_API and CPU arch macros #if defined(__APPLE__) && defined(NETGEN_ARCH_ARM) #include #endif #ifdef NETGEN_ARCH_AMD64 #ifdef WIN32 #include // for __rdtsc() CPU time step counter #else #include // for __rdtsc() CPU time step counter #endif // WIN32 #endif // NETGEN_ARCH_AMD64 namespace ngcore { // MPI rank, nranks TODO: Rename extern NGCORE_API int id, ntasks; NGCORE_API std::string Demangle(const char* typeinfo); template std::string GetName(const T& obj) { return Demangle(typeid(obj).name()); } #if defined(__GNUC__) inline bool likely (bool x) { return bool(__builtin_expect(long(x), 1L)); } inline bool unlikely (bool x) { return bool(__builtin_expect(long(x), 0L)); } #else inline bool likely (bool x) { return x; } inline bool unlikely (bool x) { return x; } #endif using TClock = std::chrono::system_clock; extern NGCORE_API const std::chrono::time_point wall_time_start; // Time in seconds since program start inline double WallTime () noexcept { std::chrono::time_point now = TClock::now(); std::chrono::duration elapsed_seconds = now-wall_time_start; return elapsed_seconds.count(); } // High precision clock counter register using TTimePoint = size_t; extern NGCORE_API double seconds_per_tick; inline TTimePoint GetTimeCounter() noexcept { #if defined(__APPLE__) && defined(NETGEN_ARCH_ARM) return mach_absolute_time(); #elif defined(NETGEN_ARCH_AMD64) return __rdtsc(); #elif defined(NETGEN_ARCH_ARM) return __builtin_readcyclecounter(); #else #warning "Unsupported CPU architecture" return 0; #endif } template inline std::string ToString (const T& t) { std::stringstream ss; ss << t; return ss.str(); } template std::ostream& operator << (std::ostream& ost, const std::map& map) { for(auto& val : map) ost << "\n" << val.first << ": " << val.second; return ost; } template NETGEN_INLINE void Swap (T & a, T & b) { T temp = std::move(a); a = std::move(b); b = std::move(temp); } // checks if string starts with sequence inline bool StartsWith(const std::string& str, const std::string& start) { if(start.size() > str.size()) return false; return std::equal(start.begin(), start.end(), str.begin()); } // checks if string ends with sequence inline bool EndsWith(const std::string& str, const std::string& end) { if(end.size() > str.size()) return false; return std::equal(end.rbegin(), end.rend(), str.rbegin()); } template NETGEN_INLINE std::atomic & AsAtomic (T & d) { return reinterpret_cast&> (d); } NETGEN_INLINE double AtomicAdd( double & sum, double val ) { std::atomic & asum = AsAtomic(sum); double current = asum.load(); while (!asum.compare_exchange_weak(current, current + val)) ; return current; } template NETGEN_INLINE T AtomicMin( T & minval, T val ) { std::atomic & aminval = AsAtomic(minval); T current = aminval.load(); while (!aminval.compare_exchange_weak(current, std::min(current, val))) ; return current; } template NETGEN_INLINE T AtomicMax( T & maxval, T val ) { std::atomic & amaxval = AsAtomic(maxval); T current = amaxval.load(); while (!amaxval.compare_exchange_weak(current, std::max(current, val))) ; return current; } namespace detail { template struct IndexTypeHelper { private: template static constexpr auto check(T2* t) -> typename T2::index_type { return *t; } static constexpr size_t check(...); public: using type = decltype(check((T*) nullptr)); // NOLINT }; } // namespace detail // Get index type of object. If object has a typedef index_type it is this type, else size_t template using index_type = typename detail::IndexTypeHelper::type; class MyMutex { std::atomic m; public: MyMutex() { m.store(false, std::memory_order_relaxed); } void lock() { bool should = false; while (!m.compare_exchange_weak(should, true)) { should = false; #ifdef NETGEN_ARCH_AMD64 _mm_pause(); #endif // NETGEN_ARCH_AMD64 } } void unlock() { m = false; } }; class MyLock { MyMutex & mutex; public: MyLock (MyMutex & amutex) : mutex(amutex) { mutex.lock(); } ~MyLock () { mutex.unlock(); } }; } // namespace ngcore #endif // NETGEN_CORE_UTILS_HPP