/** * @file scpp_memory.hpp * @bried メモリ管理モジュールヘッダファイル * @author Nomura Kei * @copyright 2003 - 2022 Nomura Kei */ #ifndef SCPP_MEMORY_HPP #define SCPP_MEMORY_HPP #include <new> #include <string> #include <thread> #include <scpp_compiler.hpp> namespace scpp { #include <sc_memory.h> typedef sc_memory MemoryInfo; /** * メモリが確保、解放、あるいはメモリ確保/解放時にエラーが発生した際のリスナインタフェース。 * ユーザーは、本リスナを実装し、MemoryManager::setHander メソッドにて登録することで、 * メモリの確保、解放、エラー発生時の通知を受信することが可能です。 * * 本リスナは、MemoryManager にて管理しているメモリに対してのみ有効です。 */ class MemoryListener { public: MemoryListener(); MemoryListener(const MemoryListener& l) = delete; MemoryListener& operator=(const MemoryListener& l) = delete; virtual ~MemoryListener(); virtual void notifyAlloc(const MemoryInfo& info, const std::string& msg) = 0; virtual void notifyFree( const MemoryInfo& info, const std::string& msg) = 0; virtual void notifyError(const MemoryInfo& info, const std::string& msg) = 0; }; /** * メモリ確保、解放、メモリ確保/解放時にエラーが発生した際のデフォルトのリスナです。 */ class DefaultMemoryListener : public MemoryListener { public: DefaultMemoryListener(); DefaultMemoryListener(const DefaultMemoryListener& l) = delete; DefaultMemoryListener& operator=(const DefaultMemoryListener& l) = delete; virtual ~DefaultMemoryListener(); virtual void notifyAlloc(const MemoryInfo& info, const std::string& msg) = 0; virtual void notifyFree( const MemoryInfo& info, const std::string& msg) = 0; virtual void notifyError(const MemoryInfo& info, const std::string& msg) = 0; }; /** * メモリ管理。 * メモリ確保、解放を行います。 * ハンドラを登録することで、メモリ確保、解放、エラー発生時の通知を受信することができます。 */ namespace MemoryManager { extern thread_local const char* file; extern thread_local int line; extern thread_local const char* func; void setListener(MemoryListener& handler); void entries(void (*handler)(const MemoryInfo& info)); void freeif(bool (*handler)(const MemoryInfo& info)); } #if defined(SC_MEMORY_MANAGE) || defined(SCPP_MEMORY_MANAGE) #if (IS_SUPPORTED_CPP20) // C++20 #define NODISCARD [[nodiscard]] #else // C++20 以外 #define NODISCARD #endif // ----- C++11 ----- NODISCARD void* operator new(std::size_t size); NODISCARD void* operator new[](std::size_t size); NODISCARD void* operator new(std::size_t size, const std::nothrow_t& t) noexcept; NODISCARD void* operator new[](std::size_t size, const std::nothrow_t& t) noexcept; void operator delete(void* ptr) noexcept; void operator delete(void* ptr, const std::nothrow_t& t) noexcept; void operator delete[](void* ptr, const std::nothrow_t& t) noexcept; // 以下、実質メモリ管理しないため除外 // NODISCARD void* operator new(std::size_t size, void* ptr) noexcept; // NODISCARD void* operator new[](std::size_t size, void* ptr) noexcept; // void operator delete(void* ptr, void*) noexcept; #if IS_SUPPORTED_CPP14 // ----- C++14 ----- void operator delete(void* ptr, std::size_t size) noexcept; #endif #if IS_SUPPORTED_CPP17 // ----- C++17 ----- // 現状未サポート [実装 // NODISCARD void* operator new(std::size_t size, std::align_val_t alignment); // NODISCARD void* operator new[](std::size_t size, std::align_val_t alignment); // NODISCARD void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t& t) noexcept; // NODISCARD void* operator new[](std::size_t size, std::align_val_t alignment, const std::nothrow_t& t) noexcept; // void operator delete(void* ptr, std::align_val_t alignment) noexcept; // void operator delete(void* ptr, size_t size, std::align_val_t alignment) noexcept; // void operator delete(void* ptr, size_t size, std::align_val_t alignment, const std::nothrow_t& t) noexcept; #endif // IS_SUPPORTED_CPP17 // ----- C++20 ----- // C++11, C++17 の new に [[nodiscard]] が付与されている // => マクロで対応済み // new の差し替え。 // 先頭 #define new \ ((scpp::MemoryManager::file = __FILE__, \ scpp::MemoryManager::line = __LINE__, \ scpp::MemoryManager::func = __func__, \ 0) && 0) ? 0 : new #endif // defined(SC_MEMORY_MANAGE) || defined(SCPP_MEMORY_MANAGE) } // namespace scpp #endif // SCPP_MEMORY_HPP