Library: Added logging and memory modules. The logging module provides a flexible interface for adding and removing logging streams (think stdout, stderr, a file) and supports ANSI colouring and including the date and time of each log call. Its header also provides several definitions for assertions, each corresponding to a specific log level and some other side effects such as debug_break(), returning, exiting or doing nothing. The memory module wraps (_)aligned_alloc and free functions and includes memory tagging by class and location and the ability to fetch a formatted string containing this information. This can allow you to narrow down where memory leaks and double frees occur to particular sections within a module. Memory can be aligned to any, 32, 64 or 4096 byte boundaries using this module.
87 lines
3.7 KiB
C++
87 lines
3.7 KiB
C++
#pragma once
|
|
#include "basalt_defines.h"
|
|
|
|
typedef u16 MEMORY_TAG;
|
|
typedef enum MEMORY_TAGS {
|
|
MEMORY_TAG_BITWIDTH_CLASS = 5,
|
|
MEMORY_TAG_BITWIDTH_ZONE = 4,
|
|
MEMORY_TAG_BITWIDTH_ALIGN = 2,
|
|
MEMORY_TAG_SHIFT_CLASS = 0,
|
|
MEMORY_TAG_SHIFT_ZONE = MEMORY_TAG_SHIFT_CLASS + MEMORY_TAG_BITWIDTH_CLASS,
|
|
MEMORY_TAG_SHIFT_ALIGN = MEMORY_TAG_SHIFT_ZONE + MEMORY_TAG_BITWIDTH_ZONE,
|
|
MEMORY_TAG_MASK_CLASS = ((1 << MEMORY_TAG_BITWIDTH_CLASS) - 1) << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_MASK_ZONE = ((1 << MEMORY_TAG_BITWIDTH_ZONE) - 1) << MEMORY_TAG_SHIFT_ZONE,
|
|
MEMORY_TAG_MASK_ALIGN = ((1 << MEMORY_TAG_BITWIDTH_ALIGN) - 1) << MEMORY_TAG_SHIFT_ALIGN,
|
|
|
|
MEMORY_TAG_CLASS_UNKNOWN = 0 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_ARRAY = 1 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_DYNARRAY = 2 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_STRING = 3 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_CIRCULAR_BUFFER = 4 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_DICT = 5 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_BINTREE = 6 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_OCTTREE = 7 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_TEXTURE = 9 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_JOB = 9 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_TRANSFORM = 10 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_RENDER_OBJECT = 11 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_MATERIAL = 12 << MEMORY_TAG_SHIFT_CLASS,
|
|
MEMORY_TAG_CLASS_MAX_BUILTIN = (MEMORY_TAG_CLASS_MATERIAL >> MEMORY_TAG_SHIFT_CLASS) + 1,
|
|
MEMORY_TAG_CLASS_MAX = (1 << MEMORY_TAG_BITWIDTH_CLASS) - 1,
|
|
|
|
MEMORY_TAG_ZONE_UNKNOWN = 0 << MEMORY_TAG_SHIFT_ZONE,
|
|
MEMORY_TAG_ZONE_SCENE = 1 << MEMORY_TAG_SHIFT_ZONE,
|
|
MEMORY_TAG_ZONE_APPLICATION = 2 << MEMORY_TAG_SHIFT_ZONE,
|
|
MEMORY_TAG_ZONE_RENDERER = 3 << MEMORY_TAG_SHIFT_ZONE,
|
|
MEMORY_TAG_ZONE_ENGINE = 4 << MEMORY_TAG_SHIFT_ZONE,
|
|
MEMORY_TAG_ZONE_EVENT = 5 << MEMORY_TAG_SHIFT_ZONE,
|
|
MEMORY_TAG_ZONE_DEBUG = 6 << MEMORY_TAG_SHIFT_ZONE,
|
|
MEMORY_TAG_ZONE_AUDIO = 7 << MEMORY_TAG_SHIFT_ZONE,
|
|
MEMORY_TAG_ZONE_MAX_BUILTIN = (MEMORY_TAG_ZONE_AUDIO >> MEMORY_TAG_SHIFT_ZONE) + 1,
|
|
MEMORY_TAG_ZONE_MAX = (1 << MEMORY_TAG_BITWIDTH_ZONE) - 1,
|
|
|
|
MEMORY_TAG_ALIGN_ANY = 0 << MEMORY_TAG_SHIFT_ALIGN,
|
|
MEMORY_TAG_ALIGN_32 = 1 << MEMORY_TAG_SHIFT_ALIGN,
|
|
MEMORY_TAG_ALIGN_64 = 2 << MEMORY_TAG_SHIFT_ALIGN,
|
|
MEMORY_TAG_ALIGN_PAGE = 3 << MEMORY_TAG_SHIFT_ALIGN,
|
|
MEMORY_TAG_ALIGN_MAX_BUILTIN = (MEMORY_TAG_ALIGN_PAGE >> MEMORY_TAG_SHIFT_ALIGN) + 1,
|
|
MEMORY_TAG_ALIGN_MAX = (1 << MEMORY_TAG_BITWIDTH_ALIGN) - 1,
|
|
} MEMORY_TAGS;
|
|
|
|
namespace basalt
|
|
{
|
|
namespace mem
|
|
{
|
|
void initialize_memory(void);
|
|
void terminate_memory (void);
|
|
|
|
template <typename T>
|
|
T* allocT(u64 num_elements, MEMORY_TAG tag);
|
|
void* alloc(u64 num_bytes, MEMORY_TAG tag);
|
|
void dealloc(void* ptr, u64 num_bytes, MEMORY_TAG tag);
|
|
template <typename T>
|
|
T* setzeroT(T* dst, u64 num_elements);
|
|
void* setzero(void* dst, u64 num_bytes);
|
|
|
|
void changetag(u64 nbytes, MEMORY_TAG prev, MEMORY_TAG next);
|
|
|
|
i64 get_total_memory_usage(void);
|
|
i64 get_memory_usage_for_class(MEMORY_TAG memory_class, i64 out_per_zone[MEMORY_TAG_CLASS_MAX]);
|
|
i64 get_memory_usage_for_zone(MEMORY_TAG memory_zone, i64 out_per_class[MEMORY_TAG_ZONE_MAX]);
|
|
|
|
// Must be freed by user via dealloc with the tags;
|
|
// MEMORY_TAG_CLASS_STRING | MEMORY_TAG_ZONE_DEBUG | MEMORY_TAG_ALIGN_ANY
|
|
char* get_memory_usage_string(void);
|
|
|
|
i64 get_memory_tag_class_name(MEMORY_TAG memory_class, char* out_buf, u64 out_buf_size);
|
|
i64 get_memory_tag_zone_name(MEMORY_TAG zone_class, char* out_buf, u64 out_buf_size);
|
|
|
|
template<typename T>
|
|
T* allocT(u64 num_elements, MEMORY_TAG tag)
|
|
{ return alloc(num_elements*sizeof(T), tag); }
|
|
template<typename T>
|
|
T* setzeroT(T * dst, u64 num_elements)
|
|
{ return setzero(dst, num_elements*sizeof(T)); }
|
|
}
|
|
}
|