dqn: Cleanup more documentation

This commit is contained in:
doyle 2023-07-06 21:13:52 +10:00
parent 55dbc25110
commit 2bbc49242e
6 changed files with 227 additions and 208 deletions

View File

@ -15,7 +15,7 @@
// possibly ever need (e.g. 16GB) and let the array commit physical pages on
// demand. On 64 bit operating systems you are given 48 bits of addressable
// space giving you 256 TB of reservable memory. This gives you practically
// an unlimited array capacity that avoids reallocs and only consumes memory
// an unlimited array capacity that avoids reallocs and only consumes memory
// that is actually occupied by the array.
//
// Each page that is committed into the array will be at page/allocation
@ -28,24 +28,26 @@
//
// In addition to no realloc on expansion or shrinking.
//
// NOTE: API
// TODO(doyle): Add an API for shrinking the array by decomitting pages back to
// the OS.
//
// NOTE: API
// @proc Dqn_VArray_InitByteSize, Dqn_VArray_Init
// @desc Initialise an array with the requested byte size or item capacity
// respectively. The returned array may have a higher capacity than the
// requested amount since requested memory from the OS may have a certain
// alignment requirement (e.g. on Windows reserve/commit are 64k/4k aligned).
//
// @proc Dqn_VArray_IsValid
// @desc Verify if the array has been initialised
//
// @proc Dqn_VArray_Make, Dqn_VArray_Add
// @desc Allocate items into the array
// 'Make' creates the `count` number of requested items
// 'Add' adds the array of items into the array
// @return The array of items allocated. Null pointer if the array is invalid
// or the array has insufficient space for the requested items.
//
// @proc Dqn_VArray_EraseRange
// @desc Erase the next `count` items at `begin_index` in the array. `count`
// can be positive or negative which dictates the if we erase forward from the
@ -56,10 +58,10 @@
// @param erase The erase method, stable erase will shift all elements after
// the erase ranged into the range. Unstable erase will copy the tail elements
// into the range to delete.
//
// @proc Dqn_VArray_Clear
// @desc Set the size of the array to 0
//
// @proc Dqn_VArray_Reserve
// @desc Ensure that the requested number of items are backed by physical
// pages from the OS. Calling this pre-emptively will minimise syscalls into
@ -67,17 +69,13 @@
// in bytes to the allocation granularity of OS allocation APIs hence the
// reserved space may be greater than the requested amount (e.g. this is 4k
// on Windows).
//
// TODO(doyle)
//
// Add an API for shrinking the array by decomitting pages back to the OS.
template <typename T> struct Dqn_VArray
{
Dqn_ArenaBlock *block; ///< Block of memory from the allocator for this array
T *data; ///< Pointer to the start of the array items in the block of memory
Dqn_usize size; ///< Number of items currently in the array
Dqn_usize max; ///< Maximum number of items this array can store
Dqn_ArenaBlock *block; // Block of memory from the allocator for this array
T *data; // Pointer to the start of the array items in the block of memory
Dqn_usize size; // Number of items currently in the array
Dqn_usize max; // Maximum number of items this array can store
T *begin() { return data; }
T *end () { return data + size; }
@ -91,14 +89,19 @@ enum Dqn_VArrayErase
Dqn_VArrayErase_Stable,
};
DQN_API template <typename T> Dqn_VArray<T> Dqn_VArray_InitByteSize(Dqn_Arena *arena, Dqn_usize byte_size);
DQN_API template <typename T> Dqn_VArray<T> Dqn_VArray_Init (Dqn_Arena *arena, Dqn_usize max);
DQN_API template <typename T> bool Dqn_VArray_IsValid (Dqn_VArray<T> const *array);
DQN_API template <typename T> T * Dqn_VArray_Make (Dqn_VArray<T> *array, Dqn_usize count, Dqn_ZeroMem zero_mem);
DQN_API template <typename T> T * Dqn_VArray_Add (Dqn_VArray<T> *array, T const *items, Dqn_usize count);
DQN_API template <typename T> void Dqn_VArray_EraseRange (Dqn_VArray<T> *array, Dqn_usize begin_index, Dqn_isize count, Dqn_VArrayErase erase);
DQN_API template <typename T> void Dqn_VArray_Clear (Dqn_VArray<T> *array);
DQN_API template <typename T> void Dqn_VArray_Reserve (Dqn_VArray<T> *array, Dqn_usize count);
// NOTE: Setup =====================================================================================
DQN_API template <typename T> Dqn_VArray<T> Dqn_VArray_InitByteSize(Dqn_Arena *arena, Dqn_usize byte_size);
DQN_API template <typename T> Dqn_VArray<T> Dqn_VArray_Init (Dqn_Arena *arena, Dqn_usize max);
DQN_API template <typename T> bool Dqn_VArray_IsValid (Dqn_VArray<T> const *array);
DQN_API template <typename T> void Dqn_VArray_Reserve (Dqn_VArray<T> *array, Dqn_usize count);
// NOTE: Insert ====================================================================================
DQN_API template <typename T> T * Dqn_VArray_Make (Dqn_VArray<T> *array, Dqn_usize count, Dqn_ZeroMem zero_mem);
DQN_API template <typename T> T * Dqn_VArray_Add (Dqn_VArray<T> *array, T const *items, Dqn_usize count);
// NOTE: Modify ====================================================================================
DQN_API template <typename T> void Dqn_VArray_EraseRange (Dqn_VArray<T> *array, Dqn_usize begin_index, Dqn_isize count, Dqn_VArrayErase erase);
DQN_API template <typename T> void Dqn_VArray_Clear (Dqn_VArray<T> *array);
#endif // !defined(DQN_NO_VARRAY)
#if !defined(DQN_NO_DSMAP)
@ -149,27 +152,27 @@ DQN_API template <typename T> void Dqn_VArray_Reserve (Dqn_VArray<
//
// - Functions that return a pointer or boolean will always return null or false
// if the passed in map is invalid e.g. `DSMap_IsValid()` returns false.
//
// @proc Dqn_DSMap_Init
// @param size[in] The number of slots in the table. This size must be a
// power-of-two or otherwise an assert will be triggered.
// @return The hash table. On memory allocation failure, the table will be
// zero initialised whereby calling Dqn_DSMap_IsValid() will return false.
//
// @proc Dqn_DSMap_Deinit
// @desc Free the memory allocated by the table
//
// @proc Dqn_DSMap_IsValid
// @desc Verify that the table is in a valid state (e.g. initialised
// correctly).
//
// @proc Dqn_DSMap_Hash
// @desc Hash the input key using the custom hash function if it's set on the
// map, otherwise uses the default hashing function (32bit Murmur3).
//
// @proc Dqn_DSMap_HashToSlotIndex
// @desc Calculate the index into the map's `slots` array from the given hash.
//
// @proc Dqn_DSMap_FindSlot, Dqn_DSMap_Find
// @desc Find the slot in the map's `slots` array corresponding to the given
// key and hash. If the map does not contain the key, a null pointer is
@ -177,7 +180,7 @@ DQN_API template <typename T> void Dqn_VArray_Reserve (Dqn_VArray<
//
// `Find` returns the value.
// `FindSlot` returns the map's hash table slot.
//
// @proc Dqn_DSMap_MakeSlot, Dqn_DSMap_Make, Dqn_DSMap_Set, Dqn_DSMap_SetSlot
// @desc Same as `DSMap_Find*` except if the key does not exist in the table,
// a hash-table slot will be made.
@ -194,20 +197,20 @@ DQN_API template <typename T> void Dqn_VArray_Reserve (Dqn_VArray<
// @param found[out] Pass a pointer to a bool. The bool will be set to true
// if the item already existed in the map before, or false if the item was
// just created by this call.
//
// @proc Dqn_DSMap_Resize
// @desc Resize the table and move all elements to the new map.
// the elements currently set in the
// @param size[in] New size of the table, must be a power of two.
// @return False if memory allocation fails, or the requested size is smaller
// than the current number of elements in the map to resize. True otherwise.
//
// @proc Dqn_DSMap_Erase
// @desc Remove the key-value pair from the table. If by erasing the key-value
// pair from the table puts the table under 25% load, the table will be shrunk
// by 1/2 the current size after erasing. The table will not shrink below the
// initial size that the table was initialised as.
//
// @proc Dqn_DSMap_KeyCStringLit, Dqn_DSMap_KeyU64, Dqn_DSMap_KeyBuffer,
// Dqn_DSMap_KeyString8 Dqn_DSMap_KeyString8Copy
// @desc Create a hash-table key given
@ -221,7 +224,7 @@ DQN_API template <typename T> void Dqn_VArray_Reserve (Dqn_VArray<
// If the key points to an array of bytes, the lifetime of those bytes *must*
// remain valid throughout the lifetime of the map as the pointers are value
// copied into the hash table!
//
// @proc Dqn_DSMap_KeyU64NoHash
// @desc Create a hash-table key given the uint64. This u64 is *not* hashed to
// map values into the table. This is useful if you already have a source of
@ -234,9 +237,9 @@ DQN_API template <typename T> void Dqn_VArray_Reserve (Dqn_VArray<
enum Dqn_DSMapKeyType
{
Dqn_DSMapKeyType_Invalid,
Dqn_DSMapKeyType_U64, ///< Use a U64 key that is `hash(u64) % size` to map into the table
Dqn_DSMapKeyType_U64NoHash, ///< Use a U64 key that is `u64 % size` to map into the table
Dqn_DSMapKeyType_Buffer, ///< Use a buffer key that is `hash(buffer) % size` to map into the table
Dqn_DSMapKeyType_U64, // Use a U64 key that is `hash(u64) % size` to map into the table
Dqn_DSMapKeyType_U64NoHash, // Use a U64 key that is `u64 % size` to map into the table
Dqn_DSMapKeyType_Buffer, // Use a buffer key that is `hash(buffer) % size` to map into the table
};
struct Dqn_DSMapKey
@ -261,14 +264,14 @@ template <typename T> struct Dqn_DSMapSlot
using Dqn_DSMapHashFunction = uint32_t(Dqn_DSMapKey key, uint32_t seed);
template <typename T> struct Dqn_DSMap
{
uint32_t *hash_to_slot; ///< Mapping from hash to a index in the slots array
Dqn_DSMapSlot<T> *slots; ///< Values of the array stored contiguously, non-sorted order
uint32_t size; ///< Total capacity of the map and is a power of two
uint32_t occupied; ///< Number of slots used in the hash table
Dqn_Allocator allocator; ///< Backing allocator for the hash table
uint32_t initial_size; ///< Initial map size, map cannot shrink on erase below this size
Dqn_DSMapHashFunction *hash_function; ///< Custom hashing function to use if field is set
uint32_t hash_seed; ///< Seed for the hashing function, when 0, DQN_DS_MAP_DEFAULT_HASH_SEED is used
uint32_t *hash_to_slot; // Mapping from hash to a index in the slots array
Dqn_DSMapSlot<T> *slots; // Values of the array stored contiguously, non-sorted order
uint32_t size; // Total capacity of the map and is a power of two
uint32_t occupied; // Number of slots used in the hash table
Dqn_Allocator allocator; // Backing allocator for the hash table
uint32_t initial_size; // Initial map size, map cannot shrink on erase below this size
Dqn_DSMapHashFunction *hash_function; // Custom hashing function to use if field is set
uint32_t hash_seed; // Seed for the hashing function, when 0, DQN_DS_MAP_DEFAULT_HASH_SEED is used
};
// NOTE: Setup =====================================================================================
@ -305,8 +308,8 @@ DQN_API bool operator== (Dqn_DS
// NOTE: [$FARR] Dqn_FArray ========================================================================
template <typename T, Dqn_usize N> struct Dqn_FArray
{
T data[N]; ///< Pointer to the start of the array items in the block of memory
Dqn_usize size; ///< Number of items currently in the array
T data[N]; // Pointer to the start of the array items in the block of memory
Dqn_usize size; // Number of items currently in the array
T *begin() { return data; }
T *end () { return data + size; }
@ -320,35 +323,40 @@ enum Dqn_FArrayErase
Dqn_FArrayErase_Stable,
};
// NOTE: Setup =====================================================================================
DQN_API template <typename T, Dqn_usize N> Dqn_FArray<T, N> Dqn_FArray_Init (T const *array, Dqn_usize count);
DQN_API template <typename T, Dqn_usize N> bool Dqn_FArray_IsValid (Dqn_FArray<T, N> const *array);
// NOTE: Insert ====================================================================================
DQN_API template <typename T, Dqn_usize N> T * Dqn_FArray_Make (Dqn_FArray<T, N> *array, Dqn_usize count, Dqn_ZeroMem zero_mem);
DQN_API template <typename T, Dqn_usize N> T * Dqn_FArray_Add (Dqn_FArray<T, N> *array, T const *items, Dqn_usize count);
// NOTE: Modify ====================================================================================
DQN_API template <typename T, Dqn_usize N> void Dqn_FArray_EraseRange(Dqn_FArray<T, N> *array, Dqn_usize begin_index, Dqn_isize count, Dqn_FArrayErase erase);
DQN_API template <typename T, Dqn_usize N> void Dqn_FArray_Clear (Dqn_FArray<T, N> *array);
#endif // !defined(DQN_NO_FARRAY)
#if !defined(DQN_NO_LIST)
// NOTE: [$LIST] Dqn_List ==========================================================================
// NOTE: API
//
// NOTE: API
// @proc Dqn_List_At
// @param at_chunk[out] (Optional) The chunk that the index belongs to will
// be set in this parameter if given
// @return The element, or null pointer if it is not a valid index.
//
// @proc Dqn_List_Iterate
// @desc Produce an iterator for the data in the list
//
// @param[in] start_index The index to start iterating from
//
// @begincode
// Dqn_List<int> list = {};
// for (Dqn_ListIterator<int> it = {}; Dqn_List_Iterate(&list, &it, 0);)
// {
// int *item = it.data;
// }
// @endcode
#if 0
Dqn_List<int> list = {};
for (Dqn_ListIterator<int> it = {}; Dqn_List_Iterate(&list, &it, 0);)
{
int *item = it.data;
}
#endif
template <typename T> struct Dqn_ListChunk
{
@ -361,10 +369,10 @@ template <typename T> struct Dqn_ListChunk
template <typename T> struct Dqn_ListIterator
{
Dqn_b32 init; // (Internal): True if Dqn_List_Iterate has been called at-least once on this iterator
Dqn_ListChunk<T> *chunk; // (Internal): The chunk that the iterator is reading from
Dqn_usize chunk_data_index; // (Internal): The index in the chunk the iterator is referencing
T *data; // (Read): Pointer to the data the iterator is referencing. Nullptr if invalid.
Dqn_b32 init; // True if Dqn_List_Iterate has been called at-least once on this iterator
Dqn_ListChunk<T> *chunk; // The chunk that the iterator is reading from
Dqn_usize chunk_data_index; // The index in the chunk the iterator is referencing
T *data; // Pointer to the data the iterator is referencing. Nullptr if invalid.
};
template <typename T> struct Dqn_List
@ -1064,4 +1072,3 @@ template <typename T> DQN_API T *Dqn_List_At(Dqn_List<T> *list, Dqn_usize index,
return result;
}
#endif // !defined(DQN_NO_LIST)

View File

@ -234,11 +234,9 @@ int main()
DQN_DEFER { printf("Three ..\n"); };
printf("One ..\n");
printf("Two ..\n");
// One ..
// Two ..
// Three ..
return 0;
}
#endif
@ -278,16 +276,16 @@ typedef int32_t Dqn_b32;
#define DQN_ISIZE_MIN INTPTR_MIN
// NOTE [$GSTR] Global Structs =====================================================================
struct Dqn_String8 ///< Pointer and length style UTF8 strings
struct Dqn_String8
{
char *data; ///< The UTF8 bytes of the string
Dqn_usize size; ///< The number of bytes in the string
char *data; // The bytes of the string
Dqn_usize size; // The number of bytes in the string
#if defined(__cplusplus)
char const *begin() const { return data; } ///< Const begin iterator for range-for loops
char const *end () const { return data + size; } ///< Const end iterator for range-for loops
char *begin() { return data; } ///< Begin iterator for range-for loops
char *end () { return data + size; } ///< End iterator for range-for loops
char const *begin() const { return data; } // Const begin iterator for range-for loops
char const *end () const { return data + size; } // Const end iterator for range-for loops
char *begin() { return data; } // Begin iterator for range-for loops
char *end () { return data + size; } // End iterator for range-for loops
#endif
};
@ -401,22 +399,22 @@ Dqn_CPUIDRegisters Dqn_CPUID(int function_id);
//
// @proc Dqn_TicketMutex_Begin, End
// @desc Lock and unlock the mutex respectively
//
// @proc Dqn_TicketMutex_MakeTicket
// @desc Allocate the next available ticket from the mutex for locking using
// Dqn_TicketMutex_BeginTicket().
// @param[in] mutex The mutex
// @code
// Dqn_TicketMutex mutex = {};
// unsigned int ticket = Dqn_TicketMutex_MakeTicket(&mutex);
// Dqn_TicketMutex_BeginTicket(&mutex, ticket); // Blocking call until we attain the lock
// Dqn_TicketMutex_End(&mutex);
// @endcode
//
#if 0
Dqn_TicketMutex mutex = {};
unsigned int ticket = Dqn_TicketMutex_MakeTicket(&mutex);
Dqn_TicketMutex_BeginTicket(&mutex, ticket); // Blocking call until we attain the lock
Dqn_TicketMutex_End(&mutex);
#endif
// @proc Dqn_TicketMutex_BeginTicket
// @desc Lock the mutex using the given ticket if possible, otherwise block
// waiting until the mutex can be locked.
//
// @proc Dqn_TicketMutex_CanLock
// @desc Determine if the mutex can be locked using the given ticket number
@ -433,10 +431,10 @@ void Dqn_TicketMutex_BeginTicket(Dqn_TicketMutex const *mutex, Dqn_uint tick
bool Dqn_TicketMutex_CanLock (Dqn_TicketMutex const *mutex, Dqn_uint ticket);
// NOTE: [$CALL] Dqn_CallSite ======================================================================
typedef struct Dqn_CallSite {
struct Dqn_CallSite
{
Dqn_String8 file;
Dqn_String8 function;
unsigned int line;
} Dqn_CalSite;
};
#define DQN_CALL_SITE Dqn_CallSite{DQN_STRING8(__FILE__), DQN_STRING8(__func__), __LINE__}

View File

@ -6,20 +6,22 @@
// =================================================================================================
// NOTE: [$FNV1] Dqn_FNV1A =========================================================================
#ifndef DQN_FNV1A32_SEED
// NOTE: API =======================================================================================
#if 0
char buffer1[128] = {random bytes};
char buffer2[128] = {random bytes};
uint64_t hash = Dqn_FNV1A64_Hash(buffer1, sizeof(buffer1));
hash = Dqn_FNV1A64_Iterate(buffer2, sizeof(buffer2), hash); // subsequent hashing
#endif
#if !defined(DQN_FNV1A32_SEED)
#define DQN_FNV1A32_SEED 2166136261U
#endif
#ifndef DQN_FNV1A64_SEED
#if !defined(DQN_FNV1A64_SEED)
#define DQN_FNV1A64_SEED 14695981039346656037ULL
#endif
/// @begincode
/// char buffer1[128] = {random bytes};
/// char buffer2[128] = {random bytes};
/// uint64_t hash = Dqn_FNV1A64_Hash(buffer1, sizeof(buffer1));
/// hash = Dqn_FNV1A64_Iterate(buffer2, sizeof(buffer2), hash); // subsequent hashing
/// @endcode
DQN_API uint32_t Dqn_FNV1A32_Hash (void const *bytes, Dqn_usize size);
DQN_API uint64_t Dqn_FNV1A64_Hash (void const *bytes, Dqn_usize size);
DQN_API uint32_t Dqn_FNV1A32_Iterate(void const *bytes, Dqn_usize size, uint32_t hash);

View File

@ -1,5 +1,5 @@
#if !defined(DQN_NO_MATH)
// NOTE: [$MATH] Math ==============================================================================
#if !defined(DQN_NO_V2)
// NOTE: [$VEC2] Vector2 ===========================================================================
DQN_API Dqn_V2I Dqn_V2ToV2I(Dqn_V2 a)
{
Dqn_V2I result = Dqn_V2I(DQN_CAST(int32_t)a.x, DQN_CAST(int32_t)a.y);
@ -51,9 +51,10 @@ DQN_API Dqn_V2 Dqn_V2Perpendicular(Dqn_V2 a)
Dqn_V2 result = Dqn_V2(-a.y, a.x);
return result;
}
#endif // !defined(DQN_NO_V2)
// NOTE: Dqn_V3 Implementation
// -------------------------------------------------------------------------------------------------
#if !defined(DQN_NO_V3)
// NOTE: [$VEC3] Vector3 ===========================================================================
DQN_API Dqn_f32 Dqn_V3LengthSq(Dqn_V3 a)
{
Dqn_f32 result = DQN_SQUARED(a.x) + DQN_SQUARED(a.y) + DQN_SQUARED(a.z);
@ -73,17 +74,19 @@ DQN_API Dqn_V3 Dqn_V3Normalise(Dqn_V3 a)
Dqn_V3 result = a / length;
return result;
}
#endif // !defined(DQN_NO_V3)
// NOTE: Dqn_V4 Implementation
// -------------------------------------------------------------------------------------------------
#if !defined(DQN_NO_V4)
// NOTE: [$VEC4] Vector4 ===========================================================================
DQN_API Dqn_f32 Dqn_V4Dot(Dqn_V4 a, Dqn_V4 b)
{
Dqn_f32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w);
return result;
}
#endif // !defined(DQN_NO_V4)
// NOTE: Dqn_M4 Implementation
// -------------------------------------------------------------------------------------------------
#if !defined(DQN_NO_M4)
// NOTE: [$MAT4] Dqn_M4 ============================================================================
DQN_API Dqn_M4 Dqn_M4_Identity()
{
Dqn_M4 result =
@ -331,9 +334,10 @@ DQN_API Dqn_FString8<256> Dqn_M4_ColumnMajorString(Dqn_M4 mat)
return result;
}
#endif
#endif // !defined(DQN_M4)
// NOTE: Dqn_Rect
// -------------------------------------------------------------------------------------------------
#if !defined(DQN_NO_RECT)
// NOTE: [$RECT] Dqn_Rect ==========================================================================
DQN_API Dqn_Rect Dqn_Rect_InitFromPosAndSize(Dqn_V2 pos, Dqn_V2 size)
{
Dqn_Rect result = {};
@ -428,9 +432,9 @@ DQN_API Dqn_V2I Dqn_RectI32_Size(Dqn_RectI32 rect)
Dqn_V2I result = rect.max - rect.min;
return result;
}
#endif // !defined(DQN_NO_RECT)
// NOTE: Math Utils
// -------------------------------------------------------------------------------------------------
// NOTE: [$MATH] Other =============================================================================
DQN_API Dqn_V2 Dqn_Lerp_V2(Dqn_V2 a, Dqn_f32 t, Dqn_V2 b)
{
Dqn_V2 result = {};
@ -444,5 +448,3 @@ DQN_API Dqn_f32 Dqn_Lerp_F32(Dqn_f32 a, Dqn_f32 t, Dqn_f32 b)
Dqn_f32 result = a + ((b - a) * t);
return result;
}
#endif // !defined(DQN_NO_MATH)

View File

@ -1,11 +1,16 @@
// NOTE: Table Of Contents =========================================================================
// Index | Disable #define | Description
// =================================================================================================
// [$MATH] Math | DQN_NO_MATH | v2i, V2, V3, V4, Mat4, Rect, RectI32, Lerp
// [$VEC2] Dqn_V2, V2i | DQN_NO_V2 |
// [$VEC3] Dqn_V3, V3i | DQN_NO_V3 |
// [$VEC4] Dqn_V4, V4i | DQN_NO_V4 |
// [$MAT4] Dqn_M4 | DQN_NO_M4 |
// [$RECT] Dqn_Rect | DQN_NO_RECT |
// [$MATH] Other | |
// =================================================================================================
#if !defined(DQN_NO_MATH)
// NOTE: [$MATH] Math ==============================================================================
#if !defined(DQN_NO_V2)
// NOTE: [$VEC2] Vector2 ===========================================================================
struct Dqn_V2I
{
int32_t x, y;
@ -71,6 +76,18 @@ struct Dqn_V2
Dqn_V2 &operator+=(Dqn_V2 other) { *this = *this + other; return *this; }
};
DQN_API Dqn_V2I Dqn_V2ToV2I(Dqn_V2 a);
DQN_API Dqn_V2 Dqn_V2Min(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_V2 Dqn_V2Max(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_V2 Dqn_V2Abs(Dqn_V2 a);
DQN_API Dqn_f32 Dqn_V2Dot(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_f32 Dqn_V2LengthSq(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_V2 Dqn_V2Normalise(Dqn_V2 a);
DQN_API Dqn_V2 Dqn_V2Perpendicular(Dqn_V2 a);
#endif // !defined(DQN_NO_V2)
#if !defined(DQN_NO_V3)
// NOTE: [$VEC3] Vector3 ===========================================================================
struct Dqn_V3
{
Dqn_f32 x, y, z;
@ -106,6 +123,18 @@ struct Dqn_V3
Dqn_V3 &operator+=(Dqn_V3 other) { *this = *this + other; return *this; }
};
DQN_API Dqn_f32 Dqn_V3LengthSq(Dqn_V3 a);
DQN_API Dqn_f32 Dqn_V3Length(Dqn_V3 a);
DQN_API Dqn_V3 Dqn_V3Normalise(Dqn_V3 a);
#endif // !defined(DQN_NO_V3)
#if !defined(DQN_NO_V4)
// NOTE: [$VEC4] Vector4 ===========================================================================
#if defined(DQN_NO_V3)
#error "Dqn_Rect requires Dqn_V3 hence DQN_NO_V3 must *not* be defined"
#endif
union Dqn_V4
{
struct { Dqn_f32 x, y, z, w; };
@ -139,26 +168,16 @@ union Dqn_V4
Dqn_V4 &operator-=(Dqn_V4 other) { *this = *this - other; return *this; }
Dqn_V4 &operator+=(Dqn_V4 other) { *this = *this + other; return *this; }
};
#endif // !defined(DQN_NO_V4)
#if !defined(DQN_NO_M4)
// NOTE: [$MAT4] Dqn_M4 ============================================================================
// NOTE: Column major matrix
struct Dqn_M4
{
Dqn_f32 columns[4][4];
};
DQN_API Dqn_V2I Dqn_V2ToV2I(Dqn_V2 a);
DQN_API Dqn_V2 Dqn_V2Min(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_V2 Dqn_V2Max(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_V2 Dqn_V2Abs(Dqn_V2 a);
DQN_API Dqn_f32 Dqn_V2Dot(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_f32 Dqn_V2LengthSq(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_V2 Dqn_V2Normalise(Dqn_V2 a);
DQN_API Dqn_V2 Dqn_V2Perpendicular(Dqn_V2 a);
DQN_API Dqn_f32 Dqn_V3LengthSq(Dqn_V3 a);
DQN_API Dqn_f32 Dqn_V3Length(Dqn_V3 a);
DQN_API Dqn_V3 Dqn_V3Normalise(Dqn_V3 a);
DQN_API Dqn_f32 Dqn_V4Dot(Dqn_V4 a, Dqn_V4 b);
DQN_API Dqn_M4 Dqn_M4_Identity();
@ -182,6 +201,13 @@ DQN_API Dqn_M4 Dqn_M4_DivF(Dqn_M4 lhs, Dqn_f32 rhs);
#if !defined(DQN_NO_FSTRING8)
DQN_API Dqn_FString8<256> Dqn_M4_ColumnMajorString(Dqn_M4 mat);
#endif
#endif // !defined(DQN_M4)
// NOTE: [$RECT] Dqn_Rect ==========================================================================
#if !defined(DQN_NO_RECT)
#if defined(DQN_NO_V2)
#error "Dqn_Rect requires Dqn_V2 hence DQN_NO_V2 must *not* be defined"
#endif
struct Dqn_Rect
{
@ -212,8 +238,9 @@ DQN_API Dqn_Rect Dqn_Rect_Intersection(Dqn_Rect a, Dqn_Rect b);
DQN_API Dqn_Rect Dqn_Rect_Union(Dqn_Rect a, Dqn_Rect b);
DQN_API Dqn_Rect Dqn_Rect_FromRectI32(Dqn_RectI32 a);
DQN_API Dqn_V2I Dqn_RectI32_Size(Dqn_RectI32 rect);
#endif // !defined(DQN_NO_RECT)
// NOTE: [$MATH] Other =============================================================================
DQN_API Dqn_V2 Dqn_Lerp_V2(Dqn_V2 a, Dqn_f32 t, Dqn_V2 b);
DQN_API Dqn_f32 Dqn_Lerp_F32(Dqn_f32 a, Dqn_f32 t, Dqn_f32 b);
#endif // !defined(DQN_NO_MATH)

View File

@ -29,54 +29,36 @@
#define DQN_LEAK_TRACE_UNUSED
#endif
typedef struct Dqn_LeakTrace {
void *ptr; ///< The pointer we are tracking
Dqn_usize size; ///< Size of the allocation
Dqn_CallSite call_site; ///< Call site where the allocation was allocated
bool freed; ///< True if this pointer has been freed
Dqn_usize freed_size; ///< Size of the allocation that has been freed
Dqn_CallSite freed_call_site; ///< Call site where the allocation was freed
} Dqn_LeakTrace;
struct Dqn_LeakTrace
{
void *ptr; // The pointer we are tracking
Dqn_usize size; // Size of the allocation
Dqn_CallSite call_site; // Call site where the allocation was allocated
bool freed; // True if this pointer has been freed
Dqn_usize freed_size; // Size of the allocation that has been freed
Dqn_CallSite freed_call_site; // Call site where the allocation was freed
};
/// Allocate memory
/// @param size The number of bytes to allocate
/// @param zero_mem Flag to indicate if the allocated memory should be zero-ed out
/// @param user_context The user assigned pointer in the allocator
typedef void *Dqn_Allocator_AllocProc(DQN_LEAK_TRACE_FUNCTION size_t size, uint8_t align, Dqn_ZeroMem zero_mem, void *user_context);
typedef void Dqn_Allocator_DeallocProc(DQN_LEAK_TRACE_FUNCTION void *ptr, size_t size, void *user_context);
/// Deallocate memory
/// @param ptr The pointer to deallocate memory for
/// @param size The number of bytes to deallocate
/// @param user_context The user assigned pointer in the allocator
typedef void Dqn_Allocator_DeallocProc(DQN_LEAK_TRACE_FUNCTION void *ptr, size_t size, void *user_context);
struct Dqn_Allocator
{
void *user_context; // User assigned pointer that is passed into the allocator functions
Dqn_Allocator_AllocProc *alloc; // Memory allocating routine
Dqn_Allocator_DeallocProc *dealloc; // Memory deallocating routine
};
typedef struct Dqn_Allocator {
void *user_context; ///< User assigned pointer that is passed into the allocator functions
Dqn_Allocator_AllocProc *alloc; ///< Memory allocating routine
Dqn_Allocator_DeallocProc *dealloc; ///< Memory deallocating routine
} Dqn_Allocator;
/// Allocate bytes from the given allocator
/// @param[in] allocator The allocator to allocate bytes from
/// @param[in] size The amount of bytes to allocator
/// @param[in] zero_mem Flag to indicate if the allocated must be zero-ed out
// NOTE: Macros ==================================================================================
#define Dqn_Allocator_Alloc(allocator, size, align, zero_mem) Dqn_Allocator_Alloc_(DQN_LEAK_TRACE allocator, size, align, zero_mem)
void *Dqn_Allocator_Alloc_(DQN_LEAK_TRACE_FUNCTION Dqn_Allocator allocator, size_t size, uint8_t align, Dqn_ZeroMem zero_mem);
/// Deallocate the memory from the pointer using the allocator
///
/// The pointer must originally have been allocated from the passed in
/// allocator. The size must also match the size that was originally allocated.
///
/// @param[in] allocator The allocator to allocate bytes from
/// @param[in] ptr The pointer to deallocate
/// @param[in] size The amount of bytes to deallocate.
#define Dqn_Allocator_Dealloc(allocator, ptr, size) Dqn_Allocator_Dealloc_(DQN_LEAK_TRACE allocator, ptr, size)
void Dqn_Allocator_Dealloc_(DQN_LEAK_TRACE_FUNCTION Dqn_Allocator allocator, void *ptr, size_t size);
#define Dqn_Allocator_NewArray(allocator, Type, count, zero_mem) (Type *)Dqn_Allocator_Alloc_(DQN_LEAK_TRACE allocator, sizeof(Type) * count, alignof(Type), zero_mem)
#define Dqn_Allocator_New(allocator, Type, zero_mem) (Type *)Dqn_Allocator_Alloc_(DQN_LEAK_TRACE allocator, sizeof(Type), alignof(Type), zero_mem)
// NOTE: Internal ==================================================================================
void *Dqn_Allocator_Alloc_ (DQN_LEAK_TRACE_FUNCTION Dqn_Allocator allocator, size_t size, uint8_t align, Dqn_ZeroMem zero_mem);
void Dqn_Allocator_Dealloc_(DQN_LEAK_TRACE_FUNCTION Dqn_Allocator allocator, void *ptr, size_t size);
// NOTE: [$VMEM] Dqn_VMem ==========================================================================
enum Dqn_VMemCommit
{
@ -86,21 +68,23 @@ enum Dqn_VMemCommit
enum Dqn_VMemPage
{
/// Exception on read/write with a page. This flag overrides the read/write access.
// Exception on read/write with a page. This flag overrides the read/write
// access.
Dqn_VMemPage_NoAccess = 1 << 0,
/// Only read permitted on the page.
// Only read permitted on the page.
Dqn_VMemPage_Read = 1 << 1,
/// Only write permitted on the page. On Windows this is not supported and will be promoted to
/// read+write permissions.
// Only write permitted on the page. On Windows this is not supported and
// will be promoted to read+write permissions.
Dqn_VMemPage_Write = 1 << 2,
Dqn_VMemPage_ReadWrite = Dqn_VMemPage_Read | Dqn_VMemPage_Write,
/// Modifier used in conjunction with previous flags. Raises exception on first access to the
/// page, then, the underlying protection flags are active. This is supported on Windows, on
/// other OS's using this flag will set the OS equivalent of Dqn_VMemPage_NoAccess.
// Modifier used in conjunction with previous flags. Raises exception on
// first access to the page, then, the underlying protection flags are
// active. This is supported on Windows, on other OS's using this flag will
// set the OS equivalent of Dqn_VMemPage_NoAccess.
Dqn_VMemPage_Guard = 1 << 3,
};
@ -149,7 +133,6 @@ DQN_API int Dqn_VMem_Protect (void *ptr, Dqn_usize size, uint32_t page_flags);
// 64GB) since the arena only commits as much as needed.
//
// NOTE: API
//
// @proc Dqn_Arena_Grow
// @desc Grow the arena's capacity by allocating a block of memory with the
// requested size. The requested size is rounded up to the nearest 64k
@ -160,7 +143,7 @@ DQN_API int Dqn_VMem_Protect (void *ptr, Dqn_usize size, uint32_t page_flags);
// pages from the OS.
// @param flags[in] Bit flags from 'Dqn_ArenaBlockFlags', set to 0 if none
// @return The block of memory that
//
// @proc Dqn_Arena_Allocate, Dqn_Arena_New, Dqn_Arena_NewArray,
// Dqn_Arena_NewArrayWithBlock,
// @desc Allocate byte/objects
@ -169,37 +152,37 @@ DQN_API int Dqn_VMem_Protect (void *ptr, Dqn_usize size, uint32_t page_flags);
// `NewArray` allocates an array of objects
// `NewArrayWithBlock` allocates an array of objects from the given memory 'block'
// @return A pointer to the allocated bytes/object. Null pointer on failure
//
// @proc Dqn_Arena_Copy, Dqn_Arena_CopyZ
// @desc Allocate a copy of an object's bytes. The 'Z' variant adds
// a null-terminating byte at the end of the stream.
// @return A pointer to the allocated object. Null pointer on failure.
//
// @proc Dqn_Arena_Reset
// @desc Set the arena's current block to the first block in the linked list
// of blocks and mark all blocks free.
// @param[in] zero_mem When yes, the memory is cleared using DQN_MEMSET with the
// value of DQN_MEMSET_BYTE
//
// @proc Dqn_Arena_Free
// @desc Free the arena returning all memory back to the OS
// @param[in] zero_mem: When true, the memory is cleared using DQN_MEMSET with
// the value of DQN_MEMSET_BYTE
//
// @proc Dqn_Arena_BeginTempMemory
// @desc Begin an allocation scope where all allocations between begin and end
// calls will be reverted. Useful for short-lived or highly defined lifetime
// allocations. An allocation scope is invalidated if the arena is freed
// between the begin and end call.
//
// @proc Dqn_Arena_EndTempMemory
// @desc End an allocation scope previously begun by calling begin scope.
//
// @proc Dqn_Arena_StatString
// @desc Dump the stats of the given arena to a string
// @param[in] arena The arena to dump stats for
// @return A stack allocated string containing the stats of the arena
//
// @proc Dqn_Arena_LogStats
// @desc Dump the stats of the given arena to the memory log-stream.
// @param[in] arena The arena to dump stats for
@ -211,29 +194,29 @@ enum Dqn_ArenaBlockFlags
struct Dqn_ArenaStat
{
Dqn_usize capacity; ///< Total allocating capacity of the arena in bytes
Dqn_usize used; ///< Total amount of bytes used in the arena
Dqn_usize wasted; ///< Orphaned space in blocks due to allocations requiring more space than available in the active block
uint32_t blocks; ///< Number of memory blocks in the arena
Dqn_usize syscalls; ///< Number of memory allocation syscalls into the OS
Dqn_usize capacity; // Total allocating capacity of the arena in bytes
Dqn_usize used; // Total amount of bytes used in the arena
Dqn_usize wasted; // Orphaned space in blocks due to allocations requiring more space than available in the active block
uint32_t blocks; // Number of memory blocks in the arena
Dqn_usize syscalls; // Number of memory allocation syscalls into the OS
Dqn_usize capacity_hwm; ///< High-water mark for 'capacity'
Dqn_usize used_hwm; ///< High-water mark for 'used'
Dqn_usize wasted_hwm; ///< High-water mark for 'wasted'
uint32_t blocks_hwm; ///< High-water mark for 'blocks'
Dqn_usize capacity_hwm; // High-water mark for 'capacity'
Dqn_usize used_hwm; // High-water mark for 'used'
Dqn_usize wasted_hwm; // High-water mark for 'wasted'
uint32_t blocks_hwm; // High-water mark for 'blocks'
};
struct Dqn_ArenaBlock
{
struct Dqn_Arena *arena; ///< Arena that owns this block
void *memory; ///< Backing memory of the block
Dqn_usize size; ///< Size of the block
Dqn_usize used; ///< Number of bytes used up in the block. Always less than the commit amount.
Dqn_usize hwm_used;///< High-water mark for 'used' bytes in this block
Dqn_usize commit; ///< Number of bytes in the block physically backed by pages
Dqn_ArenaBlock *prev; ///< Previous linked block
Dqn_ArenaBlock *next; ///< Next linked block
uint8_t flags; ///< Bit field for 'Dqn_ArenaBlockFlags'
struct Dqn_Arena *arena; // Arena that owns this block
void *memory; // Backing memory of the block
Dqn_usize size; // Size of the block
Dqn_usize used; // Number of bytes used up in the block. Always less than the commit amount.
Dqn_usize hwm_used;// High-water mark for 'used' bytes in this block
Dqn_usize commit; // Number of bytes in the block physically backed by pages
Dqn_ArenaBlock *prev; // Previous linked block
Dqn_ArenaBlock *next; // Next linked block
uint8_t flags; // Bit field for 'Dqn_ArenaBlockFlags'
};
struct Dqn_ArenaStatString
@ -246,21 +229,21 @@ struct Dqn_Arena
{
bool use_after_free_guard;
uint32_t temp_memory_count;
Dqn_String8 label; ///< Optional label to describe the arena
Dqn_ArenaBlock *head; ///< Active block the arena is allocating from
Dqn_ArenaBlock *curr; ///< Active block the arena is allocating from
Dqn_ArenaBlock *tail; ///< Last block in the linked list of blocks
Dqn_ArenaStat stats; ///< Current arena stats, reset when reset usage is invoked.
Dqn_String8 label; // Optional label to describe the arena
Dqn_ArenaBlock *head; // Active block the arena is allocating from
Dqn_ArenaBlock *curr; // Active block the arena is allocating from
Dqn_ArenaBlock *tail; // Last block in the linked list of blocks
Dqn_ArenaStat stats; // Current arena stats, reset when reset usage is invoked.
};
struct Dqn_ArenaTempMemory
{
Dqn_Arena *arena; ///< Arena the scope is for
Dqn_ArenaBlock *head; ///< Head block of the arena at the beginning of the scope
Dqn_ArenaBlock *curr; ///< Current block of the arena at the beginning of the scope
Dqn_ArenaBlock *tail; ///< Tail block of the arena at the beginning of the scope
Dqn_usize curr_used; ///< Current used amount of the current block
Dqn_ArenaStat stats; ///< Stats of the arena at the beginning of the scope
Dqn_Arena *arena; // Arena the scope is for
Dqn_ArenaBlock *head; // Head block of the arena at the beginning of the scope
Dqn_ArenaBlock *curr; // Current block of the arena at the beginning of the scope
Dqn_ArenaBlock *tail; // Tail block of the arena at the beginning of the scope
Dqn_usize curr_used; // Current used amount of the current block
Dqn_ArenaStat stats; // Stats of the arena at the beginning of the scope
};
// Automatically begin and end a temporary memory scope on object construction
@ -279,10 +262,10 @@ struct Dqn_ArenaTempMemoryScope_
enum Dqn_ArenaCommit
{
/// Commit the pages to ensure the block has the requested commit amount.
/// No-op if the block has sufficient commit space already.
// Commit the pages to ensure the block has the requested commit amount.
// No-op if the block has sufficient commit space already.
Dqn_ArenaCommit_EnsureSpace,
Dqn_ArenaCommit_GetNewPages, ///< Grow the block by the requested commit amount
Dqn_ArenaCommit_GetNewPages, // Grow the block by the requested commit amount
};
// NOTE: Allocation ================================================================================
@ -326,7 +309,7 @@ struct Dqn_ArenaCatalogItem
struct Dqn_ArenaCatalog
{
Dqn_TicketMutex ticket_mutex; ///< Mutex for adding to the linked list of arenas
Dqn_TicketMutex ticket_mutex; // Mutex for adding to the linked list of arenas
Dqn_Arena *arena;
Dqn_ArenaCatalogItem sentinel;
uint16_t arena_count;