Added a linked list exit function for reserved elements and documented unsafe functions.

This commit is contained in:
Ulysse Cura 2026-08-03 19:14:29 +02:00
parent 60dbab0fd5
commit b7f739bbfc
4 changed files with 99 additions and 54 deletions

View File

@ -104,8 +104,8 @@ int asset_manager_exit(asset_manager_t *asset_manager)
{
assert("Asset manager cannot be NULL" && asset_manager);
if(linked_list_clear(&asset_manager->assets_header_defs)) return EXIT_FAILURE;
if(linked_list_clear(&asset_manager->assets)) return EXIT_FAILURE;
if(linked_list_exit(&asset_manager->assets_header_defs)) return EXIT_FAILURE;
if(linked_list_exit(&asset_manager->assets)) return EXIT_FAILURE;
if(fclose(asset_manager->asset_file))
{

View File

@ -76,7 +76,7 @@ inline int destroy_entity(entity_t *entity)
return EXIT_FAILURE;
}
if(linked_list_clear(&entity->components)) return EXIT_FAILURE;
if(linked_list_exit(&entity->components)) return EXIT_FAILURE;
return EXIT_SUCCESS;
}
@ -225,7 +225,7 @@ inline int entity_manager_exit(entity_manager_t *entity_manager)
{
assert("Entity manager cannot be NULL" && entity_manager);
if(linked_list_clear(&entity_manager->entities)) return EXIT_FAILURE;
if(linked_list_exit(&entity_manager->entities)) return EXIT_FAILURE;
debug_printf("Exited entity manager.");

View File

@ -103,6 +103,30 @@ typedef struct linked_list_t {
size_t target_max_size;
} linked_list_t;
/**
* @brief Create an elem to insert in a linked list. The data pointer is allocated.
* If there is an element available in reserved list then it will be used.
* The element returned is filled with garbage memory.
*
* @param linked_list Pointer to an linked list
* @param ... Arguments to pass to the allocator
*
* @return pointer to initialised elem, NULL on error.
*/
elem_t *create_elem(linked_list_t *linked_list, ...);
/**
* @brief Destroy the given element and its data.
* May move the element into the reserved list for future use depending on target size of the list.
* This function makes the given element unsafe to use.
*
* @param linked_list Pointer to a linked list
* @param elem Pointer to an element
*
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
*/
int destroy_elem(linked_list_t *linked_list, elem_t *elem);
/**
* @brief Init a linked list.
*
@ -112,6 +136,16 @@ typedef struct linked_list_t {
*/
void linked_list_init(linked_list_t *linked_list, size_t data_size, const allocator_t allocator, const deleter_t deleter);
/**
* @brief Clear the given linked list and free reserved elements, do nothing on error.
* This function makes the given linked list unsafe to use.
*
* @brief linked_list Pointer to a linked list
*
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
*/
int linked_list_exit(linked_list_t *linked_list);
/**
* @brief Pre-allocate elements for a target size.
* If you want n more elements in your list, then you want linked_list.size + n target_size.
@ -124,26 +158,14 @@ void linked_list_init(linked_list_t *linked_list, size_t data_size, const alloca
int linked_list_reserve(linked_list_t *linked_list, size_t target_size);
/**
* @brief Create an elem to insert in a linked list. The data pointer is allocated.
* If there is an element available in reserved list then it will be used.
* @brief Clear the given linked list, do nothing on error.
* May move the elements into the reserved list for future use depending on target size of the list.
*
* @param linked_list Pointer to an linked list
* @param ... Arguments to pass to the allocator
*
* @return pointer to initialised elem, NULL on error.
*/
elem_t *create_elem(linked_list_t *linked_list, ...);
/**
* @brief Destroy the given element and its data.
* May move the element into the reserved list for future use depending on target size of the list.
*
* @param linked_list Pointer to a linked list
* @param elem Pointer to an element
* @brief linked_list Pointer to a linked list
*
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
*/
int destroy_elem(linked_list_t *linked_list, elem_t *elem);
int linked_list_clear(linked_list_t *linked_list);
/**
* @brief Insert an element from the back in a linked list, do nothing on error.
@ -167,6 +189,7 @@ int linked_list_push_front(linked_list_t *linked_list, elem_t *elem);
/**
* @brief Remove and return the last element in the given linked list, do nothing on error.
* The element returned have unsafe `next` and `prev` pointers.
*
* @param linked_list Pointer to a linked list
*
@ -176,6 +199,7 @@ elem_t *linked_list_pop_back(linked_list_t *linked_list);
/**
* @brief Remove and return the first element in the given linked list, do nothing on error.
* The element returned have unsafe `next` and `prev` pointers.
*
* @param linked_list Pointer to a linked list
*
@ -183,16 +207,6 @@ elem_t *linked_list_pop_back(linked_list_t *linked_list);
*/
elem_t *linked_list_pop_front(linked_list_t *linked_list);
/**
* @brief Clear the given linked list, do nothing on error.
* May move the elements into the reserved list for future use depending on target size of the list.
*
* @brief linked_list Pointer to a linked list
*
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
*/
int linked_list_clear(linked_list_t *linked_list);
/**
* @brief Insert element at the given index in the linked list, do nothing on error.
*
@ -217,6 +231,7 @@ elem_t *linked_list_get(const linked_list_t *linked_list, size_t index);
/**
* @brief Remove the given elem in the linked list, do nothing on error.
* May move the elements into the reserved list for future use depending on target size of the list.
* This function makes the given element unsafe to use.
*
* @param linked_list Pointer to a linked list
* @param elem Element to remove

View File

@ -90,6 +90,60 @@ void linked_list_init(linked_list_t *linked_list, const size_t data_size, const
linked_list->target_max_size = 0;
}
int linked_list_exit(linked_list_t *linked_list)
{
assert("Linked list cannot be NULL" && linked_list);
elem_t *current_elem = linked_list->first;
elem_t *tmp;
while(current_elem)
{
tmp = current_elem;
current_elem = current_elem->next;
if(destroy_elem(linked_list, tmp)) return EXIT_FAILURE;
}
current_elem = linked_list->reserved;
while(current_elem)
{
tmp = current_elem;
current_elem = current_elem->next;
if(destroy_elem(linked_list, tmp)) return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int linked_list_clear(linked_list_t *linked_list)
{
assert("Linked list cannot be NULL" && linked_list);
elem_t *current_elem = linked_list->first;
elem_t *tmp;
while(current_elem)
{
tmp = current_elem;
current_elem = current_elem->next;
if(destroy_elem(linked_list, tmp)) return EXIT_FAILURE;
}
linked_list->first = NULL;
linked_list->last = NULL;
linked_list->size = 0;
return EXIT_SUCCESS;
}
int linked_list_reserve(linked_list_t *linked_list, size_t target_max_size)
{
assert("Linked list cannot be NULL" && linked_list);
@ -216,30 +270,6 @@ elem_t *linked_list_pop_front(linked_list_t *linked_list)
return elem;
}
int linked_list_clear(linked_list_t *linked_list)
{
assert("Linked list cannot be NULL" && linked_list);
elem_t *current_elem = linked_list->first;
elem_t *tmp;
while(current_elem)
{
tmp = current_elem;
current_elem = current_elem->next;
if(destroy_elem(linked_list, tmp)) return EXIT_FAILURE;
}
linked_list->first = NULL;
linked_list->last = NULL;
linked_list->size = 0;
return EXIT_SUCCESS;
}
inline bool linked_list_is_empty(const linked_list_t *linked_list)
{
assert("Linked list cannot be NULL" && linked_list);