Newer
Older
libj / include / j / memory.hpp
/**
 * @file memory.hpp
 * @brief J Library Memory ヘッダファイル。
 * @copyright  2001 - 2024  Nomura Kei
 * @depends
 *   j.hpp
 */
#ifndef J_MEMORY_HPP
#define J_MEMORY_HPP

#include <new>
#include <memory>
#include <thread>

#include <j.hpp>
#include <j/memory_mark.hpp>
#include <j/memory_entry.hpp>
#include <j/memory_listener.hpp>

namespace j
{

  /**
   * メモリ管理。メモリの確保、解放を行います。
   * new 演算子呼び出し時のファイル名、行番号、関数名はスレッドセーフではありません。
   */
  namespace MemoryManager
  {
    extern thread_local const char *gFile;
    extern thread_local const char *gFunc;
    extern thread_local int gLine;

    void entries(bool (*handler)(const MemoryEntry &entry, void *arg), void *arg);
    void freeif(bool (*handler)(const MemoryEntry &entry, void *arg), void *arg);

    void *malloc(std::size_t size, const char *file, const char *func, int line);
    void *aligned_alloc(std::size_t alignment, std::size_t size, const char *file, const char *func, int line);
    void *calloc(std::size_t nmemb, std::size_t size, const char *file, const char *func, int line);
    void *realloc(void *ptr, std::size_t size, const char *file, const char *func, int line);
    void free(void *ptr, const char *file, const char *func, int line);

    void *raw_malloc(std::size_t size);
    void *raw_aligned_alloc(std::size_t alignment, std::size_t size);
    void *raw_calloc(std::size_t nmemb, std::size_t size);
    void *raw_realloc(void *ptr, std::size_t size);
    void raw_free(void *ptr);

    extern DefaultMemoryListener listener;
  };

} // namespace j

#if defined(J_MEMORY_ENABLED) && (J_MEMORY_ENABLED)

// メモリ管理有効
void *operator new(std::size_t size);
void *operator new(std::size_t size, std::align_val_t al);
void *operator new(std::size_t size, const std::nothrow_t &t) noexcept;
void *operator new(std::size_t size, std::align_val_t al, const std::nothrow_t &t) noexcept;

void *operator new[](std::size_t size);
void *operator new[](std::size_t size, std::align_val_t al);
void *operator new[](std::size_t size, const std::nothrow_t &t) noexcept;
void *operator new[](std::size_t size, std::align_val_t al, const std::nothrow_t &t) noexcept;

void operator delete(void *p) noexcept;
void operator delete(void *p, std::align_val_t al) noexcept;
void operator delete(void *p, std::size_t sz) noexcept;
void operator delete(void *p, std::size_t sz, std::align_val_t al) noexcept;

void operator delete[](void *p) noexcept;
void operator delete[](void *p, std::align_val_t al) noexcept;
void operator delete[](void *p, std::size_t sz) noexcept;
void operator delete[](void *p, std::size_t sz, std::align_val_t al) noexcept;

#if !defined(J_MEMORY_RAW)
#define new (                                       \
                j::MemoryManager::gFile = __FILE__, \
                j::MemoryManager::gFunc = __func__, \
                j::MemoryManager::gLine = __LINE__, \
                false)                              \
                ? nullptr                           \
                : new

#define delete (                                       \
                   j::MemoryManager::gFile = __FILE__, \
                   j::MemoryManager::gFunc = __func__, \
                   j::MemoryManager::gLine = __LINE__, \
                   false)                              \
                   ? void()                            \
                   : delete

#define malloc(size) j::MemoryManager::malloc(size, __FILE__, __func__, __LINE__)
#define aligned_alloc(alignment, size) j::MemoryManager::aligned_alloc(alignment, size, __FILE__, __func__, __LINE__)
#define calloc(nmemb, size) j::MemoryManager::calloc(nmemb, size, __FILE__, __func__, __LINE__)
#define realloc(ptr, size) j::MemoryManager::realloc(ptr, size, __FILE__, __func__, __LINE__)
#define free(ptr) j::MemoryManager::free(ptr, __FILE__, __func__, __LINE__)
#endif // !defined(J_MEMORY_RAW)

#else
#include <cstdlib>
#endif

#endif // J_MEMORY_HPP