diff --git a/Makefile b/Makefile index 87b1fc5..6a87876 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,7 @@ OBJS = xver.$(OBJ) \ api.$(OBJ) \ ws.$(OBJ) \ sync.$(OBJ) \ + pool.$(OBJ) \ thread.$(OBJ) \ xcli.$(OBJ) \ xcpu.$(OBJ) \ diff --git a/examples/array.c b/examples/array.c index 0e9e9c6..32b294d 100644 --- a/examples/array.c +++ b/examples/array.c @@ -8,6 +8,7 @@ #include "xstd.h" #include "array.h" +#include "pool.h" typedef struct { int key; @@ -64,9 +65,12 @@ int ComparatorCostum(const void *pData1, const void *pData2, void *pCtx) int main() { + xpool_t pool; + XPool_Init(&pool, 1024 * 2); + /* Create the xarray_t */ xarray_t array; - XArray_Init(&array, 5, 0); + XArray_Init(&array, &pool, 5, 0); printf("Initialized the array\n"); PrintEverything(&array); @@ -156,6 +160,7 @@ int main() /* We have not destructor at C, so clean up memory by ourselves */ XArray_Destroy(&array); + XPool_Destroy(&pool); return 0; } \ No newline at end of file diff --git a/misc/generate.sh b/misc/generate.sh index f539710..62bb1f7 100755 --- a/misc/generate.sh +++ b/misc/generate.sh @@ -58,6 +58,7 @@ modules=( "net: API" "net: WS" "sys: SYNC" + "sys: POOL" "sys: THREAD" "sys: XCLI" "sys: XCPU" @@ -97,6 +98,10 @@ enable_sync() { USE_SYNC=y } +enable_pool() { + USE_POOL=y +} + enable_xsig() { USE_XSIG=y } diff --git a/src/crypt/crypt.c b/src/crypt/crypt.c index d69c851..cdc28d2 100644 --- a/src/crypt/crypt.c +++ b/src/crypt/crypt.c @@ -446,7 +446,7 @@ uint8_t* XCrypt_Multy(xcrypt_ctx_t *pCtx, const uint8_t *pInput, size_t *pLength xarray_t *pCiphersArr = xstrsplit(pCtx->pCiphers, ":"); if (pCiphersArr == NULL) { - pCiphersArr = XArray_New(XSTDNON, XFALSE); + pCiphersArr = XArray_New(NULL, XSTDNON, XFALSE); if (pCiphersArr == NULL) { XCrypt_ErrorCallback(pCtx, "Can not allocate memory for cipher array"); diff --git a/src/data/array.c b/src/data/array.c index cb2a290..3688c49 100644 --- a/src/data/array.c +++ b/src/data/array.c @@ -11,17 +11,17 @@ #include #include "array.h" -xarray_data_t *XArray_NewData(void *pData, size_t nSize, uint32_t nKey) +xarray_data_t *XArray_NewData(xarray_t *pArr, void *pData, size_t nSize, uint32_t nKey) { - xarray_data_t *pNewData = (xarray_data_t*)malloc(sizeof(xarray_data_t)); + xarray_data_t *pNewData = (xarray_data_t *)xalloc(pArr->pPool, sizeof(xarray_data_t)); if (pNewData == NULL) return NULL; if (pData != NULL && nSize > 0) { - pNewData->pData = malloc(nSize + 1); + pNewData->pData = xalloc(pArr->pPool, nSize + 1); if (pNewData->pData == NULL) { - free(pNewData); + xfree(pArr->pPool, pNewData); return NULL; } @@ -34,6 +34,7 @@ xarray_data_t *XArray_NewData(void *pData, size_t nSize, uint32_t nKey) pNewData->nSize = 0; } + pNewData->pPool = pArr->pPool; pNewData->nKey = nKey; return pNewData; } @@ -42,11 +43,10 @@ void XArray_FreeData(xarray_data_t *pArrData) { if (pArrData != NULL) { - if (pArrData->pData && - pArrData->nSize > 0) - free(pArrData->pData); + if (pArrData->pData && pArrData->nSize > 0) + xfree(pArrData->pPool, pArrData->pData); - free(pArrData); + xfree(pArrData->pPool, pArrData); } } @@ -64,7 +64,7 @@ void XArray_ClearData(xarray_t *pArr, xarray_data_t *pArrData) XArray_FreeData(pArrData); } -void* XArray_Init(xarray_t *pArr, size_t nSize, uint8_t nFixed) +void* XArray_Init(xarray_t *pArr, xpool_t *pPool, size_t nSize, uint8_t nFixed) { pArr->eStatus = XARRAY_STATUS_EMPTY; pArr->clearCb = NULL; @@ -73,10 +73,11 @@ void* XArray_Init(xarray_t *pArr, size_t nSize, uint8_t nFixed) pArr->nFixed = nFixed; pArr->nAlloc = 0; pArr->nUsed = 0; + pArr->pPool = pPool; if (nSize) { - pArr->pData = (xarray_data_t**)malloc(nSize * sizeof(xarray_data_t*)); + pArr->pData = (xarray_data_t**)xalloc(pArr->pPool, nSize * sizeof(xarray_data_t*)); if (pArr->pData == NULL) return NULL; } @@ -87,14 +88,14 @@ void* XArray_Init(xarray_t *pArr, size_t nSize, uint8_t nFixed) return pArr->pData; } -xarray_t* XArray_New(size_t nSize, uint8_t nFixed) +xarray_t* XArray_New(xpool_t *pPool, size_t nSize, uint8_t nFixed) { - xarray_t *pArr = (xarray_t*)malloc(sizeof(xarray_t)); + xarray_t *pArr = (xarray_t*)xalloc(pPool, sizeof(xarray_t)); if (pArr == NULL) return NULL; - if (XArray_Init(pArr, nSize, nFixed) == NULL && nSize) + if (XArray_Init(pArr, pPool, nSize, nFixed) == NULL && nSize) { - free(pArr); + xfree(pPool, pArr); return NULL; } @@ -121,17 +122,14 @@ void XArray_Clear(xarray_t *pArr) void XArray_Destroy(xarray_t *pArr) { XArray_Clear(pArr); - if (pArr->pData != NULL) - { - free(pArr->pData); - pArr->pData = NULL; - } + xfree(pArr->pPool, pArr->pData); + pArr->pData = NULL; pArr->nSize = 0; pArr->nFixed = 0; - if (pArr->nAlloc) - free(pArr); + if (pArr->nAlloc) + xfree(pArr->pPool, pArr); } void XArray_Free(xarray_t **ppArr) @@ -152,7 +150,9 @@ uint8_t XArray_Contains(xarray_t *pArr, size_t nIndex) size_t XArray_Realloc(xarray_t *pArr) { + if (pArr == NULL) return 0; if (pArr->nFixed) return pArr->nSize; + size_t nSize = 0, nUsed = pArr->nUsed; float fQuotient = (float)nUsed / (float)pArr->nSize; @@ -161,17 +161,22 @@ size_t XArray_Realloc(xarray_t *pArr) if (nSize) { - xarray_data_t **pData = (xarray_data_t**)malloc(sizeof(xarray_data_t*) * nSize); + xarray_data_t **pData = (xarray_data_t**)xalloc(pArr->pPool, sizeof(xarray_data_t*) * nSize); if (pData == NULL) { pArr->eStatus = XARRAY_STATUS_NO_MEMORY; return 0; } - size_t nCopySize = sizeof(xarray_data_t*) * pArr->nSize; - memcpy(pData, pArr->pData, nCopySize); + printf("Reallocating array from %lu to %lu\n", pArr->nSize, nSize); + + if (pArr->pData != NULL && pArr->nUsed) + { + size_t nCopySize = sizeof(xarray_data_t*) * pArr->nUsed; + memcpy(pData, pArr->pData, nCopySize); + xfree(pArr->pPool, pArr->pData); + } - free(pArr->pData); pArr->pData = pData; pArr->nSize = nSize; @@ -191,7 +196,7 @@ size_t XArray_CheckSpace(xarray_t *pArr) { uint8_t nAlloc = pArr->nAlloc; xarray_clear_cb_t clearCb = pArr->clearCb; - XArray_Init(pArr, XARRAY_INITIAL_SIZE, 0); + XArray_Init(pArr, pArr->pPool, XARRAY_INITIAL_SIZE, 0); pArr->clearCb = clearCb; pArr->nAlloc = nAlloc; } @@ -216,7 +221,7 @@ int XArray_Add(xarray_t *pArr, xarray_data_t *pNewData) int XArray_AddData(xarray_t *pArr, void *pData, size_t nSize) { if (pArr == NULL) return XARRAY_FAILURE; - xarray_data_t *pNewData = XArray_NewData(pData, nSize, 0); + xarray_data_t *pNewData = XArray_NewData(pArr, pData, nSize, 0); if (pNewData == NULL) { @@ -229,7 +234,7 @@ int XArray_AddData(xarray_t *pArr, void *pData, size_t nSize) int XArray_PushData(xarray_t *pArr, void *pData, size_t nSize) { - xarray_data_t *pNewData = XArray_NewData(pData, 0, 0); + xarray_data_t *pNewData = XArray_NewData(pArr, pData, 0, 0); if (pNewData == NULL) { pArr->eStatus = XARRAY_STATUS_NO_MEMORY; @@ -242,7 +247,7 @@ int XArray_PushData(xarray_t *pArr, void *pData, size_t nSize) int XArray_AddDataKey(xarray_t *pArr, void *pData, size_t nSize, uint32_t nKey) { - xarray_data_t *pNewData = XArray_NewData(pData, nSize, nKey); + xarray_data_t *pNewData = XArray_NewData(pArr, pData, nSize, nKey); if (pNewData == NULL) { @@ -324,7 +329,7 @@ xarray_data_t* XArray_Set(xarray_t *pArr, size_t nIndex, xarray_data_t *pNewData xarray_data_t* XArray_SetData(xarray_t *pArr, size_t nIndex, void *pData, size_t nSize) { - xarray_data_t *pNewData = XArray_NewData(pData, nSize, 0); + xarray_data_t *pNewData = XArray_NewData(pArr, pData, nSize, 0); if (pNewData == NULL) { pArr->eStatus = XARRAY_STATUS_NO_MEMORY; @@ -355,7 +360,7 @@ xarray_data_t* XArray_InsertData(xarray_t *pArr, size_t nIndex, void *pData, siz { if (!XArray_CheckSpace(pArr)) return NULL; - xarray_data_t *pNewData = XArray_NewData(pData, nSize, 0); + xarray_data_t *pNewData = XArray_NewData(pArr, pData, nSize, 0); if (pNewData == NULL) { pArr->eStatus = XARRAY_STATUS_NO_MEMORY; diff --git a/src/data/array.h b/src/data/array.h index 3cdb7e4..601e59e 100644 --- a/src/data/array.h +++ b/src/data/array.h @@ -17,6 +17,7 @@ extern "C" { #include #include +#include "pool.h" #define XARRAY_SUCCESS 0 #define XARRAY_FAILURE -1 @@ -32,6 +33,7 @@ typedef enum { } xarray_status_t; typedef struct XArrayData { + xpool_t *pPool; void* pData; size_t nSize; uint32_t nKey; @@ -44,18 +46,19 @@ typedef struct XArray_ { xarray_data_t** pData; xarray_clear_cb_t clearCb; xarray_status_t eStatus; + xpool_t *pPool; uint8_t nFixed; uint8_t nAlloc; size_t nSize; size_t nUsed; } xarray_t; -xarray_data_t *XArray_NewData(void *pData, size_t nSize, uint32_t nKey); +xarray_data_t *XArray_NewData(xarray_t *pArr, void *pData, size_t nSize, uint32_t nKey); void XArray_FreeData(xarray_data_t *pArrData); void XArray_ClearData(xarray_t *pArr, xarray_data_t *pArrData); -xarray_t* XArray_New(size_t nSize, uint8_t nFixed); -void* XArray_Init(xarray_t *pArr, size_t nSize, uint8_t nFixed); +xarray_t* XArray_New(xpool_t *pPool, size_t nSize, uint8_t nFixed); +void* XArray_Init(xarray_t *pArr, xpool_t *pPool, size_t nSize, uint8_t nFixed); size_t XArray_Realloc(xarray_t *pArr); void XArray_Destroy(xarray_t *pArr); void XArray_Clear(xarray_t *pArr); diff --git a/src/data/xjson.c b/src/data/xjson.c index 82e0a1f..47000b2 100644 --- a/src/data/xjson.c +++ b/src/data/xjson.c @@ -397,7 +397,7 @@ xjson_obj_t* XJSON_NewObject(const char *pName, uint8_t nAllowUpdate) xjson_obj_t* XJSON_NewArray(const char *pName, uint8_t nAllowUpdate) { - xarray_t *pArray = XArray_New(XOBJ_INITIAL_SIZE, 0); + xarray_t *pArray = XArray_New(NULL, XOBJ_INITIAL_SIZE, 0); if (pArray == NULL) return NULL; pArray->clearCb = XJSON_ArrayClearCb; @@ -909,7 +909,7 @@ xarray_t* XJSON_GetObjects(xjson_obj_t *pObj) if (!XJSON_CheckObject(pObj, XJSON_TYPE_OBJECT)) return NULL; xmap_t *pMap = (xmap_t*)pObj->pData; - xarray_t *pArray = XArray_New(XSTDNON, XFALSE); + xarray_t *pArray = XArray_New(NULL, XSTDNON, XFALSE); XASSERT(pArray, NULL); if (XMap_Iterate(pMap, XJSON_CollectIt, pArray) != XMAP_OK) diff --git a/src/data/xstr.c b/src/data/xstr.c index 2c279fa..390817c 100644 --- a/src/data/xstr.c +++ b/src/data/xstr.c @@ -872,7 +872,7 @@ xarray_t* xstrsplit(const char *pString, const char *pDlmt) size_t nDlmtLen = strlen(pDlmt); if (!nDlmtLen) return NULL; - xarray_t *pArray = XArray_New(XSTDNON, XFALSE); + xarray_t *pArray = XArray_New(NULL, XSTDNON, XFALSE); if (pArray == NULL) return NULL; char sToken[XSTR_MAX]; @@ -1496,7 +1496,7 @@ xarray_t* XString_SplitStr(xstring_t *pString, const char *pDlmt) xstring_t *pToken = XString_New(XSTR_MIN, 0); if (pToken == NULL) return NULL; - xarray_t *pArray = XArray_New(2, 0); + xarray_t *pArray = XArray_New(NULL, 2, 0); if (pArray == NULL) { XString_Clear(pToken); diff --git a/src/sys/pool.c b/src/sys/pool.c new file mode 100644 index 0000000..8527b63 --- /dev/null +++ b/src/sys/pool.c @@ -0,0 +1,149 @@ +/*! + * @file libxutils/src/sys/pPool.c + * + * This source is part of "libxutils" project + * 2015-2024 Sun Dro (s.kalatoz@gmail.com) + * + * @brief Implementation of the memory pPool functionality + */ + +#include "pool.h" + +XSTATUS XPool_Init(xpool_t *pPool, size_t nSize) +{ + // Align to 8 bytes + nSize = (nSize + 7) & ~7; + + pPool->pData = (uint8_t *)malloc(nSize); + if (!pPool->pData) return XSTDERR; + + pPool->bAlloc = XFALSE; + pPool->nOffset = 0; + pPool->nUsed = 0; + pPool->nSize = nSize; + pPool->pNext = NULL; + + return XSTDOK; +} + +xpool_t* XPool_Create(size_t nSize) +{ + xpool_t *pPool = (xpool_t *)malloc(sizeof(xpool_t)); + if (pPool == NULL) return NULL; + + if (XPool_Init(pPool, nSize) != XSTDOK) + { + free(pPool); + return NULL; + } + + pPool->bAlloc = XTRUE; + return pPool; +} + +void XPool_Destroy(xpool_t *pPool) +{ + XASSERT_VOID(pPool); + + if (pPool->pData) + { + free(pPool->pData); + pPool->pData = NULL; + } + + pPool->nOffset = 0; + pPool->nUsed = 0; + pPool->nSize = 0; + + if (pPool->pNext) + { + XPool_Destroy(pPool->pNext); + pPool->pNext = NULL; + } + + if (pPool->bAlloc) free(pPool); +} + +void XPool_Reset(xpool_t *pPool) +{ + XASSERT_VOID(pPool); + pPool->nOffset = 0; + pPool->nUsed = 0; + XPool_Reset(pPool->pNext); +} + +void *XPool_Alloc(xpool_t *pPool, size_t nSize) +{ + XASSERT(pPool, NULL); + XASSERT(nSize, NULL); + + // Find space in current pool + if (pPool->nOffset + nSize > pPool->nSize) + { + // Create new pool if next is not found + if (pPool->pNext == NULL) + { + size_t nNewSize = nSize > pPool->nSize ? + nSize : pPool->nSize; + + pPool->pNext = XPool_Create(nNewSize); + if (pPool->pNext == NULL) return NULL; + } + + // Try to allocate memory in new pool + return XPool_Alloc(pPool->pNext, nSize); + } + + void *pRet = pPool->pData + pPool->nOffset; + pPool->nOffset += nSize; + pPool->nUsed += nSize; + + return pRet; +} + +void XPool_Free(xpool_t *pPool, void *pData, size_t nSize) +{ + XASSERT_VOID(pPool); + XASSERT_VOID(pData); + + xpool_t *pCur = pPool; + while (pCur != NULL) + { + if (pCur->pData != NULL && + (uint8_t *)pData >= pCur->pData && + (uint8_t *)pData < pCur->pData + pCur->nSize) + { + size_t nOffset = (uint8_t *)pData - pCur->pData; + uint8_t *pTail = pCur->pData + nOffset + nSize; + size_t nTailSize = pCur->nSize - nOffset - nSize; + + memmove(pCur->pData, pTail, nTailSize); + pCur->nOffset -= nSize; + pCur->nUsed -= nSize; + + return; + } + + pCur = pCur->pNext; + } +} + +void* xalloc(xpool_t *pPool, size_t nSize) +{ + XASSERT(nSize, NULL); + if (!pPool) return malloc(nSize); + return XPool_Alloc(pPool, nSize); +} + +void xfree(xpool_t *pPool, void *pData) +{ + XASSERT_VOID(pData); + if (!pPool) free(pData); +} + +void xfreen(xpool_t *pPool, void *pData, size_t nSize) +{ + XASSERT_VOID(pData); + if (nSize == 0) xfree(pPool, pData); + else XPool_Free(pPool, pData, nSize); +} \ No newline at end of file diff --git a/src/sys/pool.h b/src/sys/pool.h new file mode 100644 index 0000000..c5b146d --- /dev/null +++ b/src/sys/pool.h @@ -0,0 +1,45 @@ +/*! + * @file libxutils/src/sys/pool.h + * + * This source is part of "libxutils" project + * 2015-2024 Sun Dro (s.kalatoz@gmail.com) + * + * @brief Implementation of the memory pool functionality + */ + +#ifndef __XUTILS_POOL_H__ +#define __XUTILS_POOL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xstd.h" + +typedef struct XPool { + struct XPool *pNext; + uint8_t *pData; + size_t nOffset; + size_t nUsed; + size_t nSize; + xbool_t bAlloc; +} xpool_t; + +void* xalloc(xpool_t *pPool, size_t nSize); +void xfree(xpool_t *pPool, void *pData); +void xfreen(xpool_t *pPool, void *pData, size_t nSize); + +XSTATUS XPool_Init(xpool_t *pPool, size_t nSize); +xpool_t* XPool_Create(size_t nSize); + +void XPool_Destroy(xpool_t *pPool); +void XPool_Reset(xpool_t *pPool); + +void *XPool_Alloc(xpool_t *pPool, size_t nSize); +void XPool_Free(xpool_t *pPool, void *pData, size_t nSize); + +#ifdef __cplusplus +} +#endif + +#endif /* __XUTILS_POOL_H__ */ diff --git a/src/sys/xcli.c b/src/sys/xcli.c index e31a047..998a1f0 100644 --- a/src/sys/xcli.c +++ b/src/sys/xcli.c @@ -87,7 +87,7 @@ XSTATUS XCLI_GetWindowSize(xcli_size_t *pCli) void XWindow_Init(xcli_win_t *pWin) { - XArray_Init(&pWin->lineArray, 0, 0); + XArray_Init(&pWin->lineArray, NULL, 0, 0); pWin->eType = XCLI_RENDER_FRAME; pWin->frameSize.nWinColumns = 0; pWin->frameSize.nWinRows = 0; diff --git a/src/sys/xfs.c b/src/sys/xfs.c index 7b976f3..d096e27 100644 --- a/src/sys/xfs.c +++ b/src/sys/xfs.c @@ -1194,7 +1194,7 @@ void XFile_SearchInit(xfile_search_t *pSrcCtx, const char *pFileName) pSrcCtx->nLinkCount = -1; pSrcCtx->nFileSize = -1; - XArray_Init(&pSrcCtx->fileArray, XSTDNON, XFALSE); + XArray_Init(&pSrcCtx->fileArray, NULL, XSTDNON, XFALSE); pSrcCtx->fileArray.clearCb = XFile_ArrayClearCb; } diff --git a/src/sys/xtop.c b/src/sys/xtop.c index 2d0d0fe..7c959b7 100644 --- a/src/sys/xtop.c +++ b/src/sys/xtop.c @@ -86,7 +86,7 @@ int XTop_GetCPUStats(xtop_stats_t *pStats, xcpu_stats_t *pCpuStats) int i, nCPUCores = XSYNC_ATOMIC_GET(&pStats->cpuStats.nCoreCount); if (nCPUCores <= 0) return 0; - if (XArray_Init(&pCpuStats->cores, 1, 0) == NULL) return -1; + if (XArray_Init(&pCpuStats->cores, NULL, 1, 0) == NULL) return -1; pCpuStats->cores.clearCb = XTop_ClearCb; XTop_CopyCPUUsage(&pCpuStats->usage, &pStats->cpuStats.usage); @@ -120,7 +120,7 @@ int XTop_GetNetworkStats(xtop_stats_t *pStats, xarray_t *pIfaces) XSync_Lock(&pStats->netLock); if (!pStats->netIfaces.nUsed || - !XArray_Init(pIfaces, 1, 0)) + !XArray_Init(pIfaces, NULL, 1, 0)) { XSync_Unlock(&pStats->netLock); return 0; @@ -455,7 +455,7 @@ int XTop_UpdateStats(void* pData) int XTop_InitCPUStats(xcpu_stats_t *pStats) { - if (XArray_Init(&pStats->cores, 1, 0) == NULL) return 0; + if (XArray_Init(&pStats->cores, NULL, 1, 0) == NULL) return 0; pStats->cores.clearCb = XTop_ClearCb; memset(&pStats->usage, 0, sizeof(xproc_info_t)); @@ -469,7 +469,7 @@ int XTop_InitCPUStats(xcpu_stats_t *pStats) int XTop_InitStats(xtop_stats_t *pStats) { - if (XArray_Init(&pStats->netIfaces, 1, 0) == NULL) return XSTDERR; + if (XArray_Init(&pStats->netIfaces, NULL, 1, 0) == NULL) return XSTDERR; pStats->netIfaces.clearCb = XTop_ClearCb; if (!XTop_InitCPUStats(&pStats->cpuStats)) diff --git a/src/xver.h b/src/xver.h index 9f2f8c9..0183144 100644 --- a/src/xver.h +++ b/src/xver.h @@ -12,7 +12,7 @@ #define XUTILS_VERSION_MAX 2 #define XUTILS_VERSION_MIN 5 -#define XUTILS_BUILD_NUMBER 55 +#define XUTILS_BUILD_NUMBER 56 #ifdef __cplusplus extern "C" { diff --git a/xutils.conf b/xutils.conf index 551d505..410bf7c 100644 --- a/xutils.conf +++ b/xutils.conf @@ -25,6 +25,7 @@ USE_SOCK=y USE_API=y USE_WS=y USE_SYNC=y +USE_POOL=y USE_THREAD=y USE_XCLI=y USE_XCPU=y