Add better push buffer system for dynamic alloc
This commit is contained in:
		
							parent
							
								
									f42fca6350
								
							
						
					
					
						commit
						00685b9ce9
					
				
							
								
								
									
										184
									
								
								dqn.h
									
									
									
									
									
								
							
							
						
						
									
										184
									
								
								dqn.h
									
									
									
									
									
								
							| @ -100,7 +100,8 @@ bool dqn_array_init(DqnArray<T> *array, size_t capacity) | |||||||
| 		if (!dqn_array_free(array)) return false; | 		if (!dqn_array_free(array)) return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	array->data     = (T *)calloc((size_t)capacity, sizeof(T)); | 	array->data = | ||||||
|  | 	    (T *)dqn_mem_alloc_internal((size_t)capacity * sizeof(T), true); | ||||||
| 	if (!array->data) return false; | 	if (!array->data) return false; | ||||||
| 
 | 
 | ||||||
| 	array->count    = 0; | 	array->count    = 0; | ||||||
| @ -117,7 +118,8 @@ bool dqn_array_grow(DqnArray<T> *array) | |||||||
| 	size_t newCapacity         = (size_t)(array->capacity * GROWTH_FACTOR); | 	size_t newCapacity         = (size_t)(array->capacity * GROWTH_FACTOR); | ||||||
| 	if (newCapacity == array->capacity) newCapacity++; | 	if (newCapacity == array->capacity) newCapacity++; | ||||||
| 
 | 
 | ||||||
| 	T *newMem = (T *)realloc(array->data, (size_t)(newCapacity * sizeof(T))); | 	T *newMem = (T *)dqn_mem_realloc_internal( | ||||||
|  | 	    array->data, (size_t)(newCapacity * sizeof(T))); | ||||||
| 	if (newMem) | 	if (newMem) | ||||||
| 	{ | 	{ | ||||||
| 		array->data     = newMem; | 		array->data     = newMem; | ||||||
| @ -480,25 +482,37 @@ DQN_FILE_SCOPE i32  dqn_rnd_pcg_range(DqnRandPCGState *pcg, i32 min, i32 max); | |||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // PushBuffer Header
 | // PushBuffer Header
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| typedef struct PushBuffer | typedef struct DqnPushBufferBlock | ||||||
| { | { | ||||||
| 	u8     *memory; | 	u8     *memory; | ||||||
| 	size_t  used; | 	size_t  used; | ||||||
| 	size_t  size; | 	size_t  size; | ||||||
| 	i32 tempBufferCount; |  | ||||||
| } PushBuffer; |  | ||||||
| 
 | 
 | ||||||
| typedef struct TempBuffer | 	DqnPushBufferBlock *prevBlock; | ||||||
|  | } DqnPushBufferBlock; | ||||||
|  | 
 | ||||||
|  | typedef struct DqnPushBuffer | ||||||
| { | { | ||||||
| 	PushBuffer *buffer; | 	DqnPushBufferBlock *block; | ||||||
|  | 
 | ||||||
|  | 	i32 tempBufferCount; | ||||||
|  | 	u32 alignment; | ||||||
|  | } DqnPushBuffer; | ||||||
|  | 
 | ||||||
|  | typedef struct DqnTempBuffer | ||||||
|  | { | ||||||
|  | 	DqnPushBuffer      *buffer; | ||||||
|  | 	DqnPushBufferBlock *startingBlock; | ||||||
| 	size_t used; | 	size_t used; | ||||||
| } TempBuffer; |  | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE bool  push_buffer_init    (PushBuffer *buffer, void *memory, size_t size); | } DqnTempBuffer; | ||||||
| DQN_FILE_SCOPE void *push_buffer_allocate(PushBuffer *buffer, size_t size); |  | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE TempBuffer push_buffer_begin_temp_region(PushBuffer *buffer); | DQN_FILE_SCOPE bool  dqn_push_buffer_init    (DqnPushBuffer *buffer, size_t size, u32 alignment); | ||||||
| DQN_FILE_SCOPE void       push_buffer_end_temp_region  (TempBuffer tempBuffer); | DQN_FILE_SCOPE void *dqn_push_buffer_allocate(DqnPushBuffer *buffer, size_t size); | ||||||
|  | DQN_FILE_SCOPE void  dqn_push_buffer_free_last_buffer(DqnPushBuffer *buffer); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnTempBuffer dqn_push_buffer_begin_temp_region(DqnPushBuffer *buffer); | ||||||
|  | DQN_FILE_SCOPE void          dqn_push_buffer_end_temp_region  (DqnTempBuffer tempBuffer); | ||||||
| 
 | 
 | ||||||
| #endif  /* DQN_H */ | #endif  /* DQN_H */ | ||||||
| 
 | 
 | ||||||
| @ -1036,6 +1050,41 @@ STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char comma, char peri | |||||||
| // NOTE: DQN_INI_IMPLEMENTATION modified to be included when DQN_IMPLEMENTATION defined
 | // NOTE: DQN_INI_IMPLEMENTATION modified to be included when DQN_IMPLEMENTATION defined
 | ||||||
| // #define DQN_INI_IMPLEMENTATION
 | // #define DQN_INI_IMPLEMENTATION
 | ||||||
| #define DQN_INI_STRLEN(s) dqn_strlen(s) | #define DQN_INI_STRLEN(s) dqn_strlen(s) | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Memory
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // NOTE: All memory allocations in dqn.h go through these functions. So they can
 | ||||||
|  | // be rerouted fairly easily especially for platform specific mallocs.
 | ||||||
|  | FILE_SCOPE void *dqn_mem_alloc_internal(size_t size, bool zeroClear) | ||||||
|  | { | ||||||
|  | 	void *result = NULL; | ||||||
|  | 
 | ||||||
|  | 	if (zeroClear) | ||||||
|  | 	{ | ||||||
|  | 		result = calloc(1, size); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		result = malloc(size); | ||||||
|  | 	} | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FILE_SCOPE void *dqn_mem_realloc_internal(void *memory, size_t newSize) | ||||||
|  | { | ||||||
|  | 	void *result = realloc(memory, newSize); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FILE_SCOPE void dqn_mem_free_internal(void *memory) | ||||||
|  | { | ||||||
|  | 	if (memory) | ||||||
|  | 	{ | ||||||
|  | 		free(memory); | ||||||
|  | 		memory = NULL; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // Math
 | // Math
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| @ -1159,7 +1208,7 @@ DQN_FILE_SCOPE inline f32 dqn_v2_length(DqnV2 a, DqnV2 b) | |||||||
| DQN_FILE_SCOPE inline DqnV2 dqn_v2_normalise(DqnV2 a) | DQN_FILE_SCOPE inline DqnV2 dqn_v2_normalise(DqnV2 a) | ||||||
| { | { | ||||||
| 	f32 magnitude = dqn_v2_length(dqn_v2(0, 0), a); | 	f32 magnitude = dqn_v2_length(dqn_v2(0, 0), a); | ||||||
| 	DqnV2 result = dqn_v2(a.x, a.y); | 	DqnV2 result  = dqn_v2(a.x, a.y); | ||||||
| 	result        = dqn_v2_scale(a, 1 / magnitude); | 	result        = dqn_v2_scale(a, 1 / magnitude); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| @ -2155,25 +2204,26 @@ DQN_FILE_SCOPE char **dqn_dir_read(char *dir, u32 *numFiles) | |||||||
| 			return NULL; | 			return NULL; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 
 | 		char **list = (char **)dqn_mem_alloc_internal( | ||||||
| 		char **list = (char **)calloc(1, sizeof(*list) * (currNumFiles)); | 		    sizeof(*list) * (currNumFiles), true); | ||||||
| 		if (!list) | 		if (!list) | ||||||
| 		{ | 		{ | ||||||
| 			DQN_WIN32_ERROR_BOX("calloc() failed.", NULL); | 			DQN_WIN32_ERROR_BOX("dqn_mem_alloc_internal() failed.", NULL); | ||||||
| 			return NULL; | 			return NULL; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		for (u32 i = 0; i < currNumFiles; i++) | 		for (u32 i = 0; i < currNumFiles; i++) | ||||||
| 		{ | 		{ | ||||||
| 			list[i] = (char *)calloc(1, sizeof(**list) * MAX_PATH); | 			list[i] = | ||||||
|  | 			    (char *)dqn_mem_alloc_internal(sizeof(**list) * MAX_PATH, true); | ||||||
| 			if (!list[i]) | 			if (!list[i]) | ||||||
| 			{ | 			{ | ||||||
| 				for (u32 j = 0; j < i; j++) | 				for (u32 j = 0; j < i; j++) | ||||||
| 				{ | 				{ | ||||||
| 					free(list[j]); | 					dqn_mem_free_internal(list[j]); | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				DQN_WIN32_ERROR_BOX("calloc() failed.", NULL); | 				DQN_WIN32_ERROR_BOX("dqn_mem_alloc_internal() failed.", NULL); | ||||||
| 				return NULL; | 				return NULL; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -2200,11 +2250,11 @@ DQN_FILE_SCOPE inline void dqn_dir_read_free(char **fileList, u32 numFiles) | |||||||
| 	{ | 	{ | ||||||
| 		for (u32 i = 0; i < numFiles; i++) | 		for (u32 i = 0; i < numFiles; i++) | ||||||
| 		{ | 		{ | ||||||
| 			if (fileList[i]) free(fileList[i]); | 			if (fileList[i]) dqn_mem_free_internal(fileList[i]); | ||||||
| 			fileList[i] = NULL; | 			fileList[i] = NULL; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		free(fileList); | 		dqn_mem_free_internal(fileList); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -2324,47 +2374,99 @@ DQN_FILE_SCOPE i32 dqn_rnd_pcg_range(DqnRandPCGState *pcg, i32 min, i32 max) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // PushBuffer Header
 | // DqnPushBuffer Header
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| DQN_FILE_SCOPE bool push_buffer_init(PushBuffer *buffer, void *memory, size_t size) | FILE_SCOPE size_t inline dqn_size_alignment_internal(u32 alignment, size_t size) | ||||||
| { | { | ||||||
| 	if (!buffer || !memory || size <= 0) return false; | 	size_t result = ((size + (alignment-1)) & ~(alignment-1)); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FILE_SCOPE DqnPushBufferBlock * | ||||||
|  | dqn_push_buffer_alloc_block_internal(u32 alignment, size_t size) | ||||||
|  | { | ||||||
|  | 	size_t alignedSize = dqn_size_alignment_internal(alignment, size); | ||||||
|  | 	size_t totalSize   = alignedSize + sizeof(DqnPushBufferBlock); | ||||||
|  | 
 | ||||||
|  | 	DqnPushBufferBlock *result = (DqnPushBufferBlock *)dqn_mem_alloc_internal(totalSize, true); | ||||||
|  | 	if (!result) return NULL; | ||||||
|  | 
 | ||||||
|  | 	result->memory = (u8 *)result + sizeof(*result); | ||||||
|  | 	result->size   = alignedSize; | ||||||
|  | 	result->used   = 0; | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE bool dqn_push_buffer_init(DqnPushBuffer *buffer, size_t size, u32 alignment) | ||||||
|  | { | ||||||
|  | 	if (!buffer || size <= 0) return false; | ||||||
|  | 
 | ||||||
|  | 	buffer->block = dqn_push_buffer_alloc_block_internal(alignment, size); | ||||||
|  | 	if (!buffer->block) return false; | ||||||
| 
 | 
 | ||||||
| 	buffer->memory          = (u8 *)memory; |  | ||||||
| 	buffer->size            = size; |  | ||||||
| 	buffer->used            = 0; |  | ||||||
| 	buffer->tempBufferCount = 0; | 	buffer->tempBufferCount = 0; | ||||||
|  | 	buffer->alignment       = alignment; | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE inline void *push_buffer_allocate(PushBuffer *buffer, size_t size) | DQN_FILE_SCOPE void *dqn_push_buffer_allocate(DqnPushBuffer *buffer, size_t size) | ||||||
| { | { | ||||||
| 	DQN_ASSERT((buffer->used + size) <= buffer->size); | 	size_t alignedSize = dqn_size_alignment_internal(buffer->alignment, size); | ||||||
| 	void *result  = buffer->memory + buffer->used; | 	if ((buffer->block->used + alignedSize) > buffer->block->size) | ||||||
| 	buffer->used += size; | 	{ | ||||||
|  | 		size_t newBlockSize = DQN_MAX(alignedSize, buffer->block->size); | ||||||
|  | 		DqnPushBufferBlock *newBlock = dqn_push_buffer_alloc_block_internal( | ||||||
|  | 		    buffer->alignment, newBlockSize); | ||||||
|  | 		if (!newBlock) return NULL; | ||||||
|  | 
 | ||||||
|  | 		newBlock->prevBlock = buffer->block; | ||||||
|  | 		buffer->block       = newBlock; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	u8 *currPointer        = buffer->block->memory + buffer->block->used; | ||||||
|  | 	u8 *alignedResult      = (u8 *)dqn_size_alignment_internal(buffer->alignment, (size_t)currPointer); | ||||||
|  | 	size_t alignmentOffset = (size_t)(alignedResult - currPointer); | ||||||
|  | 
 | ||||||
|  | 	void *result = alignedResult; | ||||||
|  | 	buffer->block->used += (alignedSize + alignmentOffset); | ||||||
| 
 | 
 | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE TempBuffer push_buffer_begin_temp_region(PushBuffer *buffer) | DQN_FILE_SCOPE void dqn_push_buffer_free_last_buffer(DqnPushBuffer *buffer) | ||||||
| { | { | ||||||
| 	TempBuffer result = {}; | 	DqnPushBufferBlock *prevBlock = buffer->block->prevBlock; | ||||||
| 	result.buffer      = buffer; | 	dqn_mem_free_internal(buffer->block); | ||||||
| 	result.used        = buffer->used; | 	buffer->block = prevBlock; | ||||||
|  | 
 | ||||||
|  | 	// No more blocks, then last block has been freed
 | ||||||
|  | 	if (!buffer->block) DQN_ASSERT(buffer->tempBufferCount == 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnTempBuffer dqn_push_buffer_begin_temp_region(DqnPushBuffer *buffer) | ||||||
|  | { | ||||||
|  | 	DqnTempBuffer result = {}; | ||||||
|  | 	result.buffer        = buffer; | ||||||
|  | 	result.startingBlock = buffer->block; | ||||||
|  | 	result.used          = buffer->block->used; | ||||||
| 
 | 
 | ||||||
| 	buffer->tempBufferCount++; | 	buffer->tempBufferCount++; | ||||||
| 
 |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE void push_buffer_end_temp_region(TempBuffer tempBuffer) | DQN_FILE_SCOPE void dqn_push_buffer_end_temp_region(DqnTempBuffer tempBuffer) | ||||||
| { | { | ||||||
| 	PushBuffer *buffer = tempBuffer.buffer; | 	DqnPushBuffer *buffer = tempBuffer.buffer; | ||||||
| 	DQN_ASSERT(buffer->used > tempBuffer.used) | 	while (buffer->block != tempBuffer.startingBlock) | ||||||
|  | 		dqn_push_buffer_free_last_buffer(buffer); | ||||||
| 
 | 
 | ||||||
| 	buffer->used = tempBuffer.used; | 	if (buffer->block) | ||||||
|  | 	{ | ||||||
|  | 		DQN_ASSERT(buffer->block->used >= tempBuffer.used); | ||||||
|  | 		buffer->block->used = tempBuffer.used; | ||||||
|  | 		DQN_ASSERT(buffer->tempBufferCount >= 0); | ||||||
|  | 	} | ||||||
| 	buffer->tempBufferCount--; | 	buffer->tempBufferCount--; | ||||||
| 	DQN_ASSERT(buffer->tempBufferCount >= 0); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | |||||||
| @ -815,22 +815,115 @@ void dqn_file_test() | |||||||
| 
 | 
 | ||||||
| void dqn_push_buffer_test() | void dqn_push_buffer_test() | ||||||
| { | { | ||||||
| 	size_t blockSize = DQN_KILOBYTE(1); | 	size_t allocSize  = DQN_KILOBYTE(1); | ||||||
| 	void *block = calloc(1, blockSize); | 	DqnPushBuffer buffer = {}; | ||||||
| 	PushBuffer buffer = {}; | 	const u32 ALIGNMENT  = 4; | ||||||
| 	push_buffer_init(&buffer, block, blockSize); | 	dqn_push_buffer_init(&buffer, allocSize, ALIGNMENT); | ||||||
|  | 	DQN_ASSERT(buffer.block && buffer.block->memory); | ||||||
|  | 	DQN_ASSERT(buffer.block->size == allocSize); | ||||||
|  | 	DQN_ASSERT(buffer.block->used == 0); | ||||||
|  | 	DQN_ASSERT(buffer.alignment == ALIGNMENT); | ||||||
| 
 | 
 | ||||||
| 	DQN_ASSERT(buffer.memory == block); | 	// Alocate A
 | ||||||
| 	DQN_ASSERT(buffer.size == blockSize); | 	size_t sizeA = (size_t)(allocSize * 0.5f); | ||||||
| 	DQN_ASSERT(buffer.used == 0); | 	void *resultA = dqn_push_buffer_allocate(&buffer, sizeA); | ||||||
|  | 	u64 resultAddrA = *((u64 *)resultA); | ||||||
|  | 	DQN_ASSERT(resultAddrA % ALIGNMENT == 0); | ||||||
|  | 	DQN_ASSERT(buffer.block && buffer.block->memory); | ||||||
|  | 	DQN_ASSERT(buffer.block->size == allocSize); | ||||||
|  | 	DQN_ASSERT(buffer.block->used >= sizeA + 0 && | ||||||
|  | 	           buffer.block->used <= sizeA + 3); | ||||||
|  | 	DQN_ASSERT(buffer.alignment == ALIGNMENT); | ||||||
|  | 	DQN_ASSERT(resultA); | ||||||
|  | 	u8 *ptrA = (u8 *)resultA; | ||||||
|  | 	for (u32 i  = 0; i < sizeA; i++) | ||||||
|  | 		ptrA[i] = 1; | ||||||
| 
 | 
 | ||||||
| 	void *result = push_buffer_allocate(&buffer, (size_t)(blockSize * 0.5f)); | 	DqnPushBufferBlock *blockA = buffer.block; | ||||||
| 	DQN_ASSERT(buffer.memory == block); | 	// Alocate B
 | ||||||
| 	DQN_ASSERT(buffer.size == blockSize); | 	size_t sizeB  = (size_t)(allocSize * 2.0f); | ||||||
| 	DQN_ASSERT(buffer.used == (size_t)(blockSize * 0.5f)); | 	void *resultB = dqn_push_buffer_allocate(&buffer, sizeB); | ||||||
| 	DQN_ASSERT(result); | 	u64 resultAddrB = *((u64 *)resultB); | ||||||
|  | 	DQN_ASSERT(resultAddrB % ALIGNMENT == 0); | ||||||
|  | 	DQN_ASSERT(buffer.block && buffer.block->memory); | ||||||
|  | 	DQN_ASSERT(buffer.block->size == DQN_KILOBYTE(2)); | ||||||
| 
 | 
 | ||||||
| 	free(block); | 	// Since we alignment the pointers we return they can be within 0-3 bytes of
 | ||||||
|  | 	// what we expect and since this is in a new block as well used will reflect
 | ||||||
|  | 	// just this allocation.
 | ||||||
|  | 	DQN_ASSERT(buffer.block->used >= sizeB + 0 && | ||||||
|  | 	           buffer.block->used <= sizeB + 3); | ||||||
|  | 	DQN_ASSERT(resultB); | ||||||
|  | 	u8 *ptrB = (u8 *)resultB; | ||||||
|  | 	for (u32 i  = 0; i < sizeB; i++) | ||||||
|  | 		ptrB[i] = 2; | ||||||
|  | 
 | ||||||
|  | 	// Check that a new block was created since there wasn't enough space
 | ||||||
|  | 	DQN_ASSERT(buffer.block->prevBlock == blockA); | ||||||
|  | 	DQN_ASSERT(buffer.block != blockA); | ||||||
|  | 	DQN_ASSERT(buffer.alignment == ALIGNMENT); | ||||||
|  | 	DQN_ASSERT(blockA->used == sizeA); | ||||||
|  | 	DqnPushBufferBlock *blockB = buffer.block; | ||||||
|  | 
 | ||||||
|  | 	// Check temp regions work
 | ||||||
|  | 	DqnTempBuffer tempBuffer = dqn_push_buffer_begin_temp_region(&buffer); | ||||||
|  | 	size_t sizeC          = 1024 + 1; | ||||||
|  | 	void *resultC = dqn_push_buffer_allocate(tempBuffer.buffer, sizeC); | ||||||
|  | 	u64 resultAddrC = *((u64 *)resultC); | ||||||
|  | 	DQN_ASSERT(resultAddrC % ALIGNMENT == 0); | ||||||
|  | 	DQN_ASSERT(buffer.block != blockB && buffer.block != blockA); | ||||||
|  | 	DQN_ASSERT(buffer.block->used >= sizeC + 0 && | ||||||
|  | 	           buffer.block->used <= sizeC + 3); | ||||||
|  | 	DQN_ASSERT(buffer.tempBufferCount == 1); | ||||||
|  | 	DQN_ASSERT(buffer.alignment == ALIGNMENT); | ||||||
|  | 
 | ||||||
|  | 	// NOTE: Allocation should be aligned to 4 byte boundary
 | ||||||
|  | 	DQN_ASSERT(tempBuffer.buffer->block->size == 2048); | ||||||
|  | 	u8 *ptrC = (u8 *)resultC; | ||||||
|  | 	for (u32 i  = 0; i < sizeC; i++) | ||||||
|  | 		ptrC[i] = 3; | ||||||
|  | 
 | ||||||
|  | 	// Check that a new block was created since there wasn't enough space
 | ||||||
|  | 	DQN_ASSERT(buffer.block->prevBlock == blockB); | ||||||
|  | 	DQN_ASSERT(buffer.block != blockB); | ||||||
|  | 	DQN_ASSERT(buffer.alignment == ALIGNMENT); | ||||||
|  | 
 | ||||||
|  | 	for (u32 i  = 0; i < sizeA; i++) | ||||||
|  | 		DQN_ASSERT(ptrA[i] == 1); | ||||||
|  | 	for (u32 i  = 0; i < sizeB; i++) | ||||||
|  | 		DQN_ASSERT(ptrB[i] == 2); | ||||||
|  | 	for (u32 i  = 0; i < sizeC; i++) | ||||||
|  | 		DQN_ASSERT(ptrC[i] == 3); | ||||||
|  | 
 | ||||||
|  | 	// End temp region which should revert back to 2 linked buffers, A and B
 | ||||||
|  | 	dqn_push_buffer_end_temp_region(tempBuffer); | ||||||
|  | 	DQN_ASSERT(buffer.block && buffer.block->memory); | ||||||
|  | 	DQN_ASSERT(buffer.block->size == sizeB); | ||||||
|  | 	DQN_ASSERT(buffer.block->used >= sizeB + 0 && | ||||||
|  | 	           buffer.block->used <= sizeB + 3); | ||||||
|  | 	DQN_ASSERT(buffer.tempBufferCount == 0); | ||||||
|  | 	DQN_ASSERT(resultB); | ||||||
|  | 
 | ||||||
|  | 	DQN_ASSERT(buffer.block->prevBlock == blockA); | ||||||
|  | 	DQN_ASSERT(buffer.block != blockA); | ||||||
|  | 	DQN_ASSERT(blockA->used == sizeA); | ||||||
|  | 	DQN_ASSERT(buffer.alignment == ALIGNMENT); | ||||||
|  | 
 | ||||||
|  | 	// Release the last linked buffer from the push buffer
 | ||||||
|  | 	dqn_push_buffer_free_last_buffer(&buffer); | ||||||
|  | 
 | ||||||
|  | 	// Which should return back to the 1st allocation
 | ||||||
|  | 	DQN_ASSERT(buffer.block == blockA); | ||||||
|  | 	DQN_ASSERT(buffer.block->memory); | ||||||
|  | 	DQN_ASSERT(buffer.block->size == allocSize); | ||||||
|  | 	DQN_ASSERT(buffer.block->used == sizeA); | ||||||
|  | 	DQN_ASSERT(buffer.alignment == ALIGNMENT); | ||||||
|  | 
 | ||||||
|  | 	// Free once more to release buffer A memory
 | ||||||
|  | 	dqn_push_buffer_free_last_buffer(&buffer); | ||||||
|  | 	DQN_ASSERT(!buffer.block); | ||||||
|  | 	DQN_ASSERT(buffer.alignment == ALIGNMENT); | ||||||
|  | 	DQN_ASSERT(buffer.tempBufferCount == 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int main(void) | int main(void) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user