#pragma once // Copyright 2020 TooYoungTooSimp , All rights reserved. #define _CRT_SECURE_NO_WARNINGS #ifndef _UTILITIES_H_ #define _UTILITIES_H_ #include #include #include #include #include #include #include #include #include static void __strconcat_impl(std::string &res) {} template static void __strconcat_impl(std::string &res, const T &arg, const TArgs &... args) { res.append(arg); __strconcat_impl(res, args...); } template static std::string strconcat(TArgs... args) { std::string res; __strconcat_impl(res, args...); return res; } class spin_lock { private: std::atomic flag = false; public: spin_lock() = default; spin_lock(const spin_lock &) = delete; spin_lock &operator=(const spin_lock &) = delete; void lock() { bool target = false; while (!flag.compare_exchange_strong(target, true)) target = false; } void unlock() { flag.store(false); } }; #ifdef _WIN32 // clang-format off #define WIN32_LEAN_AND_MEAN #include #include #include #pragma comment(lib, "Advapi32.lib") #pragma comment(lib, "user32.lib") // clang-format on static size_t __get_working_set_size() { PROCESS_MEMORY_COUNTERS ProcessMemoryCounters; GetProcessMemoryInfo(GetCurrentProcess(), &ProcessMemoryCounters, sizeof(PROCESS_MEMORY_COUNTERS)); return ProcessMemoryCounters.WorkingSetSize; } class MemoryMonitor { private: static spin_lock lock; static int64_t global_counter; static std::map M; int64_t max_usage; int64_t counter; _CRT_ALLOC_HOOK _orig_alloc_hook; static size_t __get_block_size(void *ptr) { return *((size_t *)ptr - 4 + (sizeof(size_t) >> 2)); } static int __crt_alloc_hook(int allocType, void *ptr, size_t size, int blockType, long requestNumber, const unsigned char *filename, int lineNumber); public: MemoryMonitor() { std::lock_guard guard(lock); if (M.empty()) { _orig_alloc_hook = _CrtGetAllocHook(); _CrtSetAllocHook(__crt_alloc_hook); } M[this] = &max_usage; reset(); } ~MemoryMonitor() { std::lock_guard guard(lock); M.erase(this); if (M.empty()) _CrtSetAllocHook(_orig_alloc_hook); } void reset() { max_usage = counter = global_counter; } int64_t save() { return max_usage - counter; } }; static unsigned int __get_random_seed() { unsigned int r = 0; HCRYPTPROV hCryptProv; CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0); CryptGenRandom(hCryptProv, sizeof(unsigned int), (BYTE *)&r); CryptReleaseContext(hCryptProv, 0); return r; } static void __error_then_exit(const char *msg) { MessageBoxA(NULL, msg, "Error", MB_OK | MB_ICONERROR); exit(1); } #else unsigned int __get_random_seed() { unsigned int r = 0; FILE *fd = fopen("/dev/random", "rb"); fread(&r, sizeof(unsigned int), 1, fd); fclose(fd); return r; } void __error_then_exit(const char *msg) { fputs(msg, stderr); getchar(), getchar(); exit(1); } #endif class Random { private: std::mt19937 *rd; public: Random() { rd = new std::mt19937(__get_random_seed()); } ~Random() { delete rd; } unsigned int next() { return (*rd)(); } unsigned int next(unsigned int mn, unsigned int mx) { return next() % (mx - mn) + mn; } }; class FileHandleExitOnFail { private: FILE *fp; public: FileHandleExitOnFail(FILE *_fp) : fp(_fp) {} FileHandleExitOnFail(const char *filename, const char *mode) { fp = fopen(filename, mode); if (!fp) { auto msg = strconcat("Failed to open ", filename); __error_then_exit(msg.c_str()); } } ~FileHandleExitOnFail() { fclose(fp); } operator FILE *() const { return fp; } }; class Timer { public: using fmilliseconds = std::chrono::duration; void start() { t1 = std::chrono::steady_clock::now(); } void stop() { t2 = std::chrono::steady_clock::now(); } std::chrono::steady_clock::duration::rep difference() { return (t2 - t1).count(); } double diff_in_ms() { return std::chrono::duration_cast(t2 - t1).count(); } private: std::chrono::time_point t1, t2; }; template class Array2DView { private: T *arr; size_t w; public: Array2DView(size_t _w, T *ptr = nullptr) : arr(ptr), w(_w) {} Array2DView &operator=(T *ptr) { arr = ptr; } void resize(size_t _w) { w = _w; } T *operator[](size_t idx) { return arr + idx * w; } T *data() const { return arr; } }; #endif