Newer
Older
project / modules / libscpp / include / scpp_memory.hpp
Nomura Kei on 26 Sep 2022 4 KB UPDATE
/**
 * @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