efl/src/lib/eina/eina_freeq.h

281 lines
8.4 KiB
C

#ifndef EINA_FREEQ_H_
#define EINA_FREEQ_H_
#include <stdlib.h>
#include "eina_config.h"
#include "eina_types.h"
/**
* @addtogroup Eina_FreeQ_Group Free Queue Group
* @ingroup Eina
*
* @brief This provides a mechanism to defer actual freeing of memory
* data at some time in the future. The main free queue will be driven
* by the EFL main loop and ensure data is eventually freed.
*
* For debugging and tuning you may set the following envrionment variables:
*
* EINA_FREEQ_BYPASS=1
*
* Set this environment variable to immediately bypass the free queue and
* have all items submitted free with their free function immediately.
* Note that you can override this by setting count or mem max by
* eina_freeq_count_max_set() or eina_freeq_mem_max_set() which will
* disable bypass for that specific free queue. once bypass is disabled
* it cannot be re-enabled.
*
* EINA_FREEQ_FILL_MAX=N
*
* This sets the maximum number of bytes to N an item in the free queue may
* be in size for the free queue to fill it with debugging values like
* 0x55 in every byte, to ensure you can see what memory has been freed
* or not when debugging in tools like gdb.
*
* EINA_FREEQ_TOTAL_MAX=N
*
* This sets the maximum number of items allowed to N on a free queue by
* default before it starts emptying the free queue out tomake room.
*
* EINA_FREEQ_MEM_MAX=N
*
* This sets the maximum total number of Kb (Kilobytes) of memory allowed
* on a free queue by default to N Kb worth of data.
*
* @{
*
* @since 1.19
*
* @typedef Eina_FreeQ
*
* A queue of pointers to free in the future. You may create custom free
* queues of your own to defer freeing, use the main free queue where the
* mainloop will free thnigs as it iterates, or eina will free everything
* on shut down.
*
*/
typedef struct _Eina_FreeQ Eina_FreeQ;
/**
* @brief Create a new free queue to defer freeing of data with
*
* @return A new free queue
* @since 1.19
*/
EAPI Eina_FreeQ *
eina_freeq_new(void);
/**
* @brief Free a free queue and anything that is queued in it.
*
* @param fq The free queue to free and clear.
*
* @since 1.19
*/
EAPI void
eina_freeq_free(Eina_FreeQ *fq);
/**
* @brief Set the main free queue driven by the EFL mainloop.
*
* @param fq The free queue to set as the main loop one.
*
* @since 1.19
*/
EAPI void
eina_freeq_main_set(Eina_FreeQ *fq);
/**
* @brief Get the main loop free queue.
*
* @return The main loop free queue.
*
* @since 1.19
*/
EAPI Eina_FreeQ *
eina_freeq_main_get(void);
/**
* @brief Set the maximum number of free pointers this queue is allowed
*
* @param fq The free queue to alter
* @param count The maximum number of items allowed (must be >= 0)
*
* This will alter the maximum number of pointers allowed in the given free
* queue. If more items are added to the free queue than are allowed,
* excess items will be freed to make room for the new items. If count is
* changed, then excess items may be cleaned out at the time this API is
* called.
*
* @since 1.19
*/
EAPI void
eina_freeq_count_max_set(Eina_FreeQ *fq, int count);
/**
* @brief Get the maximum number of free pointers this queue is allowed
*
* @param fq The free queue to query
* @return The maximum number of free items allowed
*
* @since 1.19
*/
EAPI int
eina_freeq_count_max_get(Eina_FreeQ *fq);
/**
* @brief Set the maximum amount of memory allowed
*
* @param fq The free queue to alter
* @param mem The maximum memory in bytes
*
* This will alter the maximum amount of memory allowed for pointers stored
* in the free queue. The size used is the size give, so items given that
* are 0 sized will not contribute to this limit. If items with a total
* memory footprint are added to the free queue, items will be cleaned out
* until the total is below this limit. Changing the limit may involve
* cleaning out excess items from the free queue until the total amount of
* memory used by items in the queue is below or at the limit.
*
* @since 1.19
*/
EAPI void
eina_freeq_mem_max_set(Eina_FreeQ *fq, size_t mem);
/**
* @brief Get the maximum amount of memory allowed
*
* @param fq The free queue to query
* @return The maximum amount of memory in bytes
*
* @since 1.19
*/
EAPI size_t
eina_freeq_mem_max_get(Eina_FreeQ *fq);
/**
* @brief Clear out all queued items to be freed by freeing them
*
* @param fq The free queue to clear
*
* This will free and thus remove all queued items from the free queue when
* this function is called. When it returns the free queue should be
* empty.
*
* @since 1.19
*/
EAPI void
eina_freeq_clear(Eina_FreeQ *fq);
/**
* @brief Reduce the number of items in the free queue by up to @p count
*
* @param fq The free queue to reduce in item count
* @param count The number of items to try and free
*
* This will attempt to free up to @p count items from the given free queue
* and thus reduce the amount of memory it is holding on to. This function
* will return once it has removed @p count items or there are no more items
* to remove from the queue.
*
* @since 1.19
*/
EAPI void
eina_freeq_reduce(Eina_FreeQ *fq, int count);
/**
* @brief Return if there are any items pending a free in the free queue
*
* @param fq The free queue to query
* @raturn EINA_TRUE if there are items to free, EINA_FALSE otherwise
*
* @since 1.19
*/
EAPI Eina_Bool
eina_freeq_ptr_pending(Eina_FreeQ *fq);
/**
* @brief Add a pointer with free function and size to the free queue
*
* @param fq The free queue to add the pointer to
* @param ptr The pointer to free
* @param free_func The function used to free the pointer with
* @param size The size of the data the pointer points to
*
* This adds the given @p ptr pointer to the queue to be freed later on.
* The function @p free_func will be used, or if this is NULL, it is assumed
* the libc free() function will be used then instead. The @p size parameter
* determines the size of the data pointed to, but if this is 0 then no
* assumptions are made about size and the pointer is considered opaque. A
* zero sized pointer will not contribute to the total memory usage of
* items in the queue as well. If @p size is supplied it must be correct
* as the memory may be written to for debugging purposes or otherwise
* inspected or checksummed. Once a pointer is added to the free queue
* with this API the memory should be considered freed as if the real
* @p free_func was called immediately (and it may actually be called
* immediately if certain environment variables are set). A free queue exists
* to move the cost of freeing to another point in time when it is more
* convenient to do so as well as provide some robustness for badly
* written code that may access memory after freeing. Note that when using
* tools like valgrind, eina detects this and will also immediately free
* the data so valgrind's own memory checkers can detect use after free
* as normal.
*
* @since 1.19
*/
EAPI void
eina_freeq_ptr_add(Eina_FreeQ *fq, void *ptr, void (*free_func) (void *ptr), size_t size);
/**
* @brief Add a pointer to the main free queue
*
* @param ptr The pointer to free
* @param free_func The function used to free the pointer with
* @param size The size of the data the pointer points to
*
* This is the same as eina_freeq_ptr_add() but the main free queue is
* fetched by eina_freeq_main_get().
*
* @since 1.19
*/
static inline void
eina_freeq_ptr_main_add(void *ptr, void (*free_func) (void *ptr), size_t size)
{
eina_freeq_ptr_add(eina_freeq_main_get(), ptr, free_func, size);
}
/**
* @brief Convenience macro for well known structures and types
*
* @param ptr The pointer to free
*
* This is the same as eina_freeq_ptr_main_add() but the free function is
* assumed to be the libc free() function, and size is provided by
* sizeof(*ptr), so it will not work on void pointers or will be inaccurate
* for pointers to arrays. For arrays please use EINA_FREEQ_ARRAY_FREE()
*
* @since 1.19
*/
#define EINA_FREEQ_FREE(ptr) eina_freeq_ptr_main_add(ptr, NULL, sizeof(*(ptr)))
/**
* @brief Convenience macro for well known structures and types
*
* @param ptr The pointer to free
*
* This is the same as eina_freeq_ptr_main_add() but the free function is
* assumed to be the libc free() function, and size is provided by
* sizeof(*ptr), so it will not work on void pointers. Total size is multiplied
* by the count @p n so it should work well for arrays of types.
*
* @since 1.19
*/
#define EINA_FREEQ_N_FREE(ptr, n) eina_freeq_ptr_main_add(ptr, NULL, sizeof(*(ptr)) * n)
/**
* @}
*/
#endif