rvobjpool.c
来自「基于h323协议的软phone」· C语言 代码 · 共 831 行 · 第 1/2 页
C
831 行
item = RvObjListGetNext(&objpool->freelist, NULL, RV_OBJLIST_REMOVE);
if((item == NULL) && (objpool->autoexpand == RV_TRUE)) {
/* No items and we're allowed to make more so make them and try again */
RvObjPoolNewPage(objpool);
item = RvObjListGetNext(&objpool->freelist, NULL, RV_OBJLIST_REMOVE);
}
/* If we're keeping page references, increment item count */
if((item != NULL) && (objpool->allowsalvage == RV_OBJPOOL_SALVAGE_ALLOWED)) {
pageref = (RvObjPoolPage **)((RvInt8 *)item - RV_OBJPOOL_ITEM_OVERHEAD);
(*pageref)->freecount--;
}
return item;
}
/* Returns RV_TRUE if successful */
RvBool RvObjPoolReleaseItem(RvObjPool *objpool, void *item)
{
RvObjPoolPage **pageref;
RvSize_t total, minlevel;
#if defined(RV_NULLCHECK)
if((objpool == NULL) || (item == NULL))
return RV_FALSE;
#endif
#if defined(RV_OTHERCHECK)
if(objpool->allowsalvage == RV_OBJPOOL_SALVAGE_ALLOWED) {
pageref = (RvObjPoolPage **)((RvInt8 *)item - RV_OBJPOOL_ITEM_OVERHEAD);
if((*pageref)->pool != objpool)
return RV_FALSE; /* Object being returned to wrong pool */
}
#endif
/* Put item at front of free list (so it gets reused first) */
if(RvObjListInsertAfter(&objpool->freelist, NULL, item) == NULL)
return RV_FALSE;
if(objpool->allowsalvage == RV_OBJPOOL_SALVAGE_ALLOWED) {
/* Page reference only exists if pages can be removed */
pageref = (RvObjPoolPage **)((RvInt8 *)item - RV_OBJPOOL_ITEM_OVERHEAD);
(*pageref)->freecount++;
if((objpool->autoreduct == RV_TRUE) && ((*pageref)->freecount == (*pageref)->maxelements)) {
/* The page is no longer in use so we may want to delete the page */
if(objpool->reductlevel > 0) {
/* Calculate free level */
total = RvObjPoolTotalItems(objpool) - objpool->pageitems;
minlevel = (objpool->reductlevel * (total / 100)) +
((objpool->reductlevel * (total % 100)) / 100);
if(RvObjPoolFreeItems(objpool) > (minlevel + objpool->pageitems))
RvObjPoolRemovePage(*pageref);
} else RvObjPoolRemovePage(*pageref); /* reductlevel = 0 means always delete */
}
}
return RV_TRUE;
}
/* Create new page and add it to a pool */
static RvObjPoolPage *RvObjPoolNewPage(RvObjPool *objpool)
{
RvObjPoolPage *page, **pageref;
RvSize_t count;
void *item, *useritem;
#if defined(RV_NULLCHECK)
if(objpool == NULL)
return NULL;
#endif
if(((RvObjListSize(&objpool->pagelist) + 1) * objpool->pageitems) > objpool->maxitems)
return RV_FALSE; /* adding a page would go above maximum */
page = (RvObjPoolPage *)objpool->callbacks.pagealloc(objpool->pagesize, objpool->callbacks.pageallocdata);
if(page == NULL)
return NULL; /* can't get a new page */
/* Create each item in page */
item = (void *)((RvInt8 *)page + RV_OBJPOOL_PAGE_OVERHEAD);
for(count = 0; count < objpool->pageitems; count++) {
if(objpool->allowsalvage == RV_OBJPOOL_SALVAGE_ALLOWED) {
/* Add page reference before actual item */
pageref = (RvObjPoolPage **)item;
*pageref = page;
useritem = (void *)((RvInt8 *)item + RV_OBJPOOL_ITEM_OVERHEAD);
} else useritem = item;
/* Call user construct if there is one */
if(objpool->callbacks.objconstruct != NULL) {
if(objpool->callbacks.objconstruct(useritem, objpool->callbacks.objconstructdata) == NULL) {
/* User can't construct object, we need to undo things */
while(count > 0) {
count--;
item = (void *)((RvInt8 *)item - objpool->blocksize);
if(objpool->allowsalvage == RV_OBJPOOL_SALVAGE_ALLOWED) {
useritem = (void *)((RvInt8 *)item - RV_OBJPOOL_ITEM_OVERHEAD);
} else useritem = item;
RvObjListRemoveItem(&objpool->freelist, useritem);
if(objpool->callbacks.objdestruct != NULL)
objpool->callbacks.objdestruct(useritem, objpool->callbacks.objdestructdata);
}
objpool->callbacks.pagefree((void *)page, objpool->callbacks.pagefreedata);
return NULL; /* Page is undone, bail out */
}
}
/* Add new item to end of pool's free list */
RvObjListInsertBefore(&objpool->freelist, NULL, useritem);
item = (void *)((RvInt8 *)item + objpool->blocksize);
}
/* Set up page info */
page->pool = objpool;
page->maxelements = objpool->pageitems;
page->freecount = objpool->pageitems;
RvObjListInsertBefore(&objpool->pagelist, NULL, (void *)page); /* Put page at end of list */
return page;
}
/* Remove a page from its object pool, returns RV_TRUE if successful. */
static RvBool RvObjPoolRemovePage(RvObjPoolPage *page)
{
RvObjPool *objpool;
RvSize_t count;
void *item, *useritem;
#if defined(RV_NULLCHECK)
if(page == NULL)
return RV_FALSE;
#endif
objpool = page->pool;
if(((RvObjListSize(&objpool->pagelist) - 1) * objpool->pageitems) < objpool->minitems)
return RV_FALSE; /* removing a page would go below minimum */
RvObjListRemoveItem(&objpool->pagelist, (void *)page);
/* Remove each item in page */
item = (void *)((RvInt8 *)page + RV_OBJPOOL_PAGE_OVERHEAD);
for(count = 0; count < objpool->pageitems; count++) {
if(objpool->allowsalvage == RV_OBJPOOL_SALVAGE_ALLOWED) {
/* skip page reference before actual item */
useritem = (void *)((RvInt8 *)item + RV_OBJPOOL_ITEM_OVERHEAD);
} else useritem = item;
RvObjListRemoveItem(&objpool->freelist, useritem); /* remove from freelist */
/* Call user destruct if there is one */
if(objpool->callbacks.objdestruct != NULL)
objpool->callbacks.objdestruct(useritem, objpool->callbacks.objdestructdata);
item = (void *)((RvInt8 *)item + objpool->blocksize);
}
/* free up page and we're done */
objpool->callbacks.pagefree(page, objpool->callbacks.pagefreedata);
return RV_TRUE;
}
#if defined(RV_TEST_CODE)
#include "rvstdio.h"
#include <stdlib.h>
typedef struct {
RvInt32 dummy1;
RvInt64 dummy2;
RvObjPoolElement poolElem;
RvChar dummy3[80];
RvSize_t index;
} RvObjPoolTestStruct;
static volatile int callbackprint = 0;
static volatile RvSize_t counter = 0;
/* Set GETMEMORY & FREEMEMORY to function that will allocate memory pages */
#if (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS) /* Shouldn't use this here but its a test */
#define FREEMEMORY(_x) NU_Deallocate_Memory((_x))
#define GETMEMORY(_x) NU_getmemory((_x))
#include <nucleus.h>
extern NU_MEMORY_POOL System_Memory;
static void *NU_getmemory(RvSize_t n)
{
int status;
void *ptr;
status = NU_Allocate_Memory(&System_Memory, &ptr, n, NU_NO_SUSPEND);
if(status != NU_SUCCESS) return NULL;
return ptr;
}
#elif (RV_OS_TYPE == RV_OS_TYPE_OSE) /* Shouldn't use this here but its a test */
#define GETMEMORY(_x) heap_alloc_shared((_x), (__FILE__), (__LINE__))
#define FREEMEMORY(_x) heap_free_shared((_x))
#include "ose.h"
#include "heapapi.h"
#else
#define GETMEMORY(_x) malloc((_x))
#define FREEMEMORY(_x) free((_x))
#endif
static void *RvObjPoolTestObjConstruct(void *item, void *data)
{
RvObjPoolTestStruct *testitem;
testitem = (RvObjPoolTestStruct *)item;
memset(item, 0x5A, sizeof(RvObjPoolTestStruct));
testitem->index = counter;
counter++;
if(callbackprint != 0)
RvPrintf("ObjConstruct item = %p, data = %p, index = %u\n", testitem, data, testitem->index);
return item;
}
static void RvObjPoolTestObjDestruct(void *item, void *data)
{
RvObjPoolTestStruct *testitem;
testitem = (RvObjPoolTestStruct *)item;
if(callbackprint != 0)
RvPrintf("ObjDestruct item = %p, data = %p, index = %u\n", testitem, data, testitem->index);
counter--;
memset(item, 0xA0, sizeof(RvObjPoolTestStruct));
}
static void *RvObjPoolTestPageAlloc(RvSize_t size, void *data)
{
void *result;
result = (void *)GETMEMORY(size);
if(callbackprint != 0)
RvPrintf("PageAlloc size = %d, data = %p, result = %p\n", size, data, result);
return result;
}
static void RvObjPoolTestPageFree(void *ptr, void *data)
{
if(callbackprint != 0)
RvPrintf("PageFree ptr = %p, data = %p\n", ptr, data);
FREEMEMORY(ptr);
}
static void RvObjPoolTestPool(RvInt pooltype, RvBool salvage, RvSize_t maxitems, RvSize_t minitems, RvSize_t freelevel, RvSize_t pageitems, RvSize_t pagesize)
{
RvObjPoolTestStruct testitem, *poolitem;
RvObjPoolFuncs callbacks;
RvObjPool objpool, *poolresult;
RvBool boolresult;
RvSize_t uiresult;
int i, arraysize;
void **objarray;
RvPrintf("++++Testing pool++++\n");
RvPrintf("Type=");
switch(pooltype) {
case RV_OBJPOOL_TYPE_FIXED: RvPrintf("FIXED");
break;
case RV_OBJPOOL_TYPE_EXPANDING: RvPrintf("EXPANDING");
break;
case RV_OBJPOOL_TYPE_DYNAMIC: RvPrintf("DYNAMIC");
break;
}
RvPrintf(", salvage=");
switch(salvage) {
case RV_OBJPOOL_SALVAGE_ALLOWED: RvPrintf("allowed");
break;
case RV_OBJPOOL_SALVAGE_NEVER: RvPrintf("never");
break;
}
RvPrintf(", max=%u, min=%u, freelevel=%u\n", maxitems, minitems, freelevel);
RvPrintf("items/page=%u, pagesize=%u, item size=%u\n", pageitems, pagesize, sizeof(testitem));
callbackprint = 1;
RvPrintf("RvObjPoolConstruct : ");
callbacks.objconstruct = RvObjPoolTestObjConstruct;
callbacks.objdestruct = RvObjPoolTestObjDestruct;
callbacks.pagealloc = RvObjPoolTestPageAlloc;
callbacks.pagefree = RvObjPoolTestPageFree;
callbacks.objconstructdata = (void *)1;
callbacks.objdestructdata = (void *)2;
callbacks.pageallocdata = (void *)3;
callbacks.pagefreedata = (void *)4;
poolresult = RvObjPoolConstruct(&objpool, &testitem, &testitem.poolElem, &callbacks, sizeof(testitem), pageitems, pagesize, pooltype, salvage, maxitems, minitems, freelevel);
if(poolresult == NULL) {
RvPrintf("ERROR\n");
RvPrintf("++++Pool Test Aborted++++\n");
return;
} else RvPrintf("OK\n");
RvPrintf("RvObjPoolItemsPerPage = %u\n", RvObjPoolItemsPerPage(&objpool));
RvPrintf("RvObjPoolItemsBlockSize = %u\n", RvObjPoolItemBlockSize(&objpool));
RvPrintf("RvObjPoolPageSize = %u\n", RvObjPoolPageSize(&objpool));
RvPrintf("RvObjPoolSalvage = %u\n", RvObjPoolSalvage(&objpool));
RvPrintf("Getting an item...\n");
poolitem = (RvObjPoolTestStruct *)RvObjPoolGetItem(&objpool);
RvPrintf("RvObjPoolGetItem: ");
if(poolitem != NULL) {
RvPrintf("%p\n", poolitem);
} else RvPrintf("ERROR!\n");
RvPrintf("RvObjPoolTotalItems = %u\n", RvObjPoolTotalItems(&objpool));
RvPrintf("RvObjPoolFreeItems = %u\n", RvObjPoolFreeItems(&objpool));
RvPrintf("RvObjPoolTotalPages = %u\n", RvObjPoolTotalPages(&objpool));
RvPrintf("Releasing an item...\n");
boolresult = RvObjPoolReleaseItem(&objpool, poolitem);
RvPrintf("RvObjPoolReleaseItem: ");
if(boolresult == RV_TRUE) {
RvPrintf("OK.\n");
} else RvPrintf("ERROR!\n");
RvPrintf("RvObjPoolTotalItems = %u\n", RvObjPoolTotalItems(&objpool));
RvPrintf("RvObjPoolFreeItems = %u\n", RvObjPoolFreeItems(&objpool));
RvPrintf("RvObjPoolTotalPages = %u\n", RvObjPoolTotalPages(&objpool));
RvPrintf("Adding pages...\n");
uiresult = RvObjPoolAddPages(&objpool, 2);
RvPrintf("RvObjPoolAddPages (2): ");
if(uiresult == 2) {
RvPrintf("OK.\n");
} else RvPrintf("ERROR!\n");
RvPrintf("Adding items...\n");
uiresult = RvObjPoolAddItems(&objpool, ((RvObjPoolItemsPerPage(&objpool) * 3) / 2));
RvPrintf("RvObjPoolAddItems (%u): ", ((RvObjPoolItemsPerPage(&objpool) * 3) / 2));
if(uiresult == (RvObjPoolItemsPerPage(&objpool) * 2)) {
RvPrintf("OK.\n");
} else RvPrintf("ERROR!\n");
RvPrintf("RvObjPoolTotalItems = %u\n", RvObjPoolTotalItems(&objpool));
RvPrintf("RvObjPoolFreeItems = %u\n", RvObjPoolFreeItems(&objpool));
RvPrintf("RvObjPoolTotalPages = %u\n", RvObjPoolTotalPages(&objpool));
arraysize = (RvObjPoolItemsPerPage(&objpool) * 4) + 3;
objarray = (void **)GETMEMORY((RvSize_t)arraysize * sizeof(void *));
RvPrintf("Getting %d items...\n", arraysize);
for(i = 0; i < arraysize; i++) {
objarray[i] = RvObjPoolGetItem(&objpool);
if(objarray[i] == NULL) RvPrintf("ERROR! Bad get: %d\n", i);
}
RvPrintf("RvObjPoolTotalItems = %u\n", RvObjPoolTotalItems(&objpool));
RvPrintf("RvObjPoolFreeItems = %u\n", RvObjPoolFreeItems(&objpool));
RvPrintf("RvObjPoolTotalPages = %u\n", RvObjPoolTotalPages(&objpool));
RvPrintf("RvObjPoolSalvage = %u\n", RvObjPoolSalvage(&objpool));
RvPrintf("Releasing %d items...\n", (arraysize / 2));
for(i = 0; i < (arraysize / 2); i++) {
if(RvObjPoolReleaseItem(&objpool, objarray[i]) == RV_FALSE)
RvPrintf("ERROR! Bad release: %d\n", i);
objarray[i] = NULL;
}
RvPrintf("RvObjPoolTotalItems = %u\n", RvObjPoolTotalItems(&objpool));
RvPrintf("RvObjPoolFreeItems = %u\n", RvObjPoolFreeItems(&objpool));
RvPrintf("RvObjPoolTotalPages = %u\n", RvObjPoolTotalPages(&objpool));
RvPrintf("Salvaging free pages...\n");
RvPrintf("RvObjPoolSalvage = %u\n", RvObjPoolSalvage(&objpool));
RvPrintf("RvObjPoolTotalItems = %u\n", RvObjPoolTotalItems(&objpool));
RvPrintf("RvObjPoolFreeItems = %u\n", RvObjPoolFreeItems(&objpool));
RvPrintf("RvObjPoolTotalPages = %u\n", RvObjPoolTotalPages(&objpool));
if(RvObjPoolFreeItems(&objpool) != RvObjPoolTotalItems(&objpool)) {
RvPrintf("Trying to Destruct Pool: ");
boolresult = RvObjPoolDestruct(&objpool);
if(boolresult == RV_TRUE) {
RvPrintf("ERROR! Destruct should have failed.\n");
} else RvPrintf("OK. Didn't destroy pool with outstanding items.\n");
}
RvPrintf("Releasing rest of items...\n");
for(i = 0; i < arraysize; i++) {
if(objarray[i] != NULL) {
if(RvObjPoolReleaseItem(&objpool, objarray[i]) == RV_FALSE)
RvPrintf("ERROR! Bad release: %d\n", i);
}
}
RvPrintf("RvObjPoolTotalItems = %u\n", RvObjPoolTotalItems(&objpool));
RvPrintf("RvObjPoolFreeItems = %u\n", RvObjPoolFreeItems(&objpool));
RvPrintf("RvObjPoolTotalPages = %u\n", RvObjPoolTotalPages(&objpool));
RvPrintf("Destructing pool: ");
boolresult = RvObjPoolDestruct(&objpool);
if(boolresult == RV_TRUE) {
RvPrintf("OK\n");
} else RvPrintf("ERROR!\n");
callbackprint = 0;
FREEMEMORY(objarray);
RvPrintf("++++Pool test completed++++\n");
}
void RvObjPoolTest(void)
{
RvPrintf("Starting test of Rvobjpool.\n");
/* type, salvage, max, min, freelevel, items/page, pagesize */
RvObjPoolTestPool(RV_OBJPOOL_TYPE_FIXED, RV_OBJPOOL_SALVAGE_ALLOWED, 0, 0, 0, 15, 0);
RvObjPoolTestPool(RV_OBJPOOL_TYPE_FIXED, RV_OBJPOOL_SALVAGE_NEVER, 0, 0, 0, 0, 1500);
RvObjPoolTestPool(RV_OBJPOOL_TYPE_FIXED, RV_OBJPOOL_SALVAGE_ALLOWED, 40, 5, 0, 15, 0);
RvPrintf("Testing bas Min/Max. Should fail.\n");
RvObjPoolTestPool(RV_OBJPOOL_TYPE_FIXED, RV_OBJPOOL_SALVAGE_ALLOWED, 5, 40, 0, 15, 0);
RvPrintf("Testing Page size too small. Should fail.\n");
RvObjPoolTestPool(RV_OBJPOOL_TYPE_FIXED, RV_OBJPOOL_SALVAGE_NEVER, 0, 0, 0, 0, 100);
RvObjPoolTestPool(RV_OBJPOOL_TYPE_EXPANDING, RV_OBJPOOL_SALVAGE_ALLOWED, 0, 0, 0, 17, 0);
RvObjPoolTestPool(RV_OBJPOOL_TYPE_EXPANDING, RV_OBJPOOL_SALVAGE_NEVER, 0, 0, 0, 0, 1200);
RvObjPoolTestPool(RV_OBJPOOL_TYPE_EXPANDING, RV_OBJPOOL_SALVAGE_ALLOWED, 40, 0, 0, 17, 0);
RvObjPoolTestPool(RV_OBJPOOL_TYPE_DYNAMIC, RV_OBJPOOL_SALVAGE_ALLOWED, 0, 0, 0, 13, 0);
RvObjPoolTestPool(RV_OBJPOOL_TYPE_DYNAMIC, RV_OBJPOOL_SALVAGE_ALLOWED, 0, 0, 25, 13, 2000);
RvObjPoolTestPool(RV_OBJPOOL_TYPE_DYNAMIC, RV_OBJPOOL_SALVAGE_ALLOWED, 0, 15, 0, 13, 0);
}
#endif /* RV_TEST_CODE */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?