// // Created by EmsiaetKadosh on 25-1-14. // #pragma once #define __CARLBEKS_DEBUG__ #define __CARLBEKS_MEMORY__ 1 #pragma warning(disable: 4819) #include #include #include #include #include #include #include #include #include using wchar = wchar_t; using QWORD = unsigned long long int; using String = std::wstring; using Thread = std::thread; template, typename Alloc = std::allocator>> using Map = std::map; template> using List = std::list; template using Function = std::function; #define Success() { return 0; } #define Failed() { return 1; } #define Error() { return -1; } #define _WINSOCKAPI_ /* 防止winsock.h被引入。winsock.h和winsock2.h冲突。 */ #if false #include #endif #define NOMINMAX #include #include #include #include #include #include #include #include #include #define WM_APP_LBUTTONUP (WM_APP + 1) #define WM_APP_MBUTTONDOWN (WM_APP + 2) #pragma comment(lib, "Msimg32.lib") #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "dwmapi.lib") #pragma comment(lib, "Uxtheme.lib") #pragma comment(lib, "winmm.lib") template concept Copyable = requires(const T& t) { T(t); }; template concept NewCopyable = requires(const T& t) { delete new T(t); }; template concept Moveable = requires(T&& t) { T(std::move(t)); }; template concept NewMoveable = requires(T&& t) { delete new T(std::move(t)); }; template concept NonreferenceType = !std::is_reference_v; template concept NonpointerType = !std::is_pointer_v; template concept ReferenceType = std::is_reference_v; template concept PointerType = std::is_pointer_v; template concept TypeName = NonreferenceType && NonpointerType; inline std::wfstream& MainLogFile = *new std::wfstream(L"log.txt", std::ios::out | std::ios::trunc); struct MemoryManager { struct MemoryInfo { std::size_t size; const String msg; }; Map allocated; } inline memoryManager; void requireNonnull(const void* value) noexcept(false); inline String ptrtow(QWORD value); #if defined __CARLBEKS_DEBUG__ || defined __CARLBEKS_MEMORY__ void printAllocate(void* value, std::size_t size, const String&); void printDeallocate(void* value, std::size_t size, const String&); extern String atow(const char* chars); template T* _allocatedFor(T* value, const String& msg = L"", std::size_t size = sizeof(T)) { requireNonnull(value); const auto& k = memoryManager.allocated.emplace(value, MemoryManager::MemoryInfo{ size, L"[" + atow(typeid(T).name()) + L"] " + msg }).first; #if __CARLBEKS_MEMORY__ > 1 printAllocate(value, k->second.size, k->second.msg); #endif return value; } template T* _deallocating(T* value) { #if __CARLBEKS_MEMORY__ > 1 const MemoryManager::MemoryInfo* info = nullptr; if (memoryManager.allocated.contains(value)) info = &memoryManager.allocated.at(value); printDeallocate(value, info ? info->size : 0, info ? info->msg : L"???"); #endif if (value) memoryManager.allocated.erase(value); return value; } #if __CARLBEKS_MEMORY__ > 3 #define allocatedFor(val, ...) _allocatedFor(val, L"\n From " __FUNCSIG__ "\n At " __FILE__ ":" _STL_STRINGIZE(__LINE__) __VA_OPT__(,) __VA_ARGS__) #else #define allocatedFor(val, ...) _allocatedFor(val, L"" __VA_OPT__(,) __VA_ARGS__) #endif #define deallocating(val) _deallocating(val) #else #define allocatedFor(val, ...) val #define deallocating(val) val #endif template class ObjectHolder { Base* value; bool hasValue; char padding[7]{}; public: /** * 用于延迟初始化。 */ ObjectHolder() : value(nullptr), hasValue(false) {} // ReSharper disable once CppNonExplicitConvertingConstructor ObjectHolder(Base* value) : value(value), hasValue(false) {} // ReSharper disable once CppNonExplicitConvertingConstructor template requires (std::is_base_of_v || std::is_same_v) && TypeName ObjectHolder(const T& value) : value(allocatedFor(new T(value))), hasValue(true) {} // ReSharper disable once CppNonExplicitConvertingConstructor template requires (std::is_base_of_v || std::is_same_v) && TypeName ObjectHolder(T&& value) : value(allocatedFor(new T(std::forward(value)))), hasValue(true) {} ObjectHolder(const ObjectHolder& other) noexcept: value(other.value), hasValue(false) {} ObjectHolder(ObjectHolder&& other) noexcept: value(other.value), hasValue(other.hasValue) { other.value = nullptr; other.hasValue = false; } template requires std::is_base_of_v && TypeName void set(const T& value); template requires std::is_base_of_v && TypeName void set(T&& value); ~ObjectHolder() { if (hasValue) delete deallocating(value); value = nullptr; } [[nodiscard]] Base* operator->() noexcept(false) { requireNonnull(value); return value; } [[nodiscard]] const Base* operator->() const noexcept(false) { requireNonnull(value); return value; } [[nodiscard]] Base& operator*() noexcept(false) { requireNonnull(value); return *value; } [[nodiscard]] const Base& operator*() const noexcept(false) { requireNonnull(value); return *value; } [[nodiscard]] Base& get() noexcept(false) { requireNonnull(value); return *value; } [[nodiscard]] const Base& get() const noexcept(false) { requireNonnull(value); return *value; } // ReSharper disable once CppNonExplicitConversionOperator Base* ptr() const noexcept { return value; } operator bool() const noexcept { return value; } bool operator!() const noexcept { return value == nullptr; } bool isManager() const noexcept { return hasValue; } }; template class SynchronizedHolder { mutable Base* newValue = nullptr; mutable Base* value = nullptr; mutable bool isOk = false; public: SynchronizedHolder() = default; ~SynchronizedHolder() { if (newValue == value) { if (value) delete deallocating(value); } else { if (newValue) delete deallocating(newValue); if (value) delete deallocating(value); } newValue = nullptr; value = nullptr; } template requires std::is_base_of_v && TypeName void setNew(const Base& other) noexcept { isOk = false; if (newValue && newValue != value) deleteNew(); newValue = allocatedFor(new T(other)); } template requires std::is_base_of_v && TypeName void setNew(T&& val) noexcept { isOk = false; if (newValue && newValue != value) deleteNew(); newValue = allocatedFor(new T(std::forward(val))); } void ok() const noexcept { isOk = true; } Base& get() const noexcept(false) { requireNonnull(value); return *value; } Base& getNew() const noexcept(false) { requireNonnull(newValue); // 用于抛错 return *newValue; } Base* ptr() const noexcept { return value; } Base* ptrNew() const noexcept { return newValue; } Base* ptrs() const noexcept { return newValue ? newValue : value; } void async() const noexcept { if (newValue == value) return; if (!isOk) return; Base* nuv = newValue; newValue = nullptr; if (nuv) { if (value && value != nuv) deleteOld(); value = nuv; } } private: void deleteOld() const noexcept { delete deallocating(value); value = nullptr; } void deleteNew() const noexcept { delete deallocating(newValue); newValue = nullptr; } };