📄 rvpool.c
字号:
#if (0)
******************************************************************************
Filename :
Description :
******************************************************************************
Copyright (c) 2000 RADVision Inc.
************************************************************************
NOTICE:
This document contains information that is proprietary to RADVision LTD.
No part of this publication may be reproduced in any form whatsoever
without written prior approval by RADVision LTD..
RADVision LTD. reserves the right to revise this publication and make
changes without obligation to notify any person of such revisions or
changes.
******************************************************************************
$Revision:$
$Date:$
$Author: S. Cipolli$
******************************************************************************
#endif
#include <stdio.h>
#include <assert.h>
#include "rvutil.h"
#include "rvpool.h"
#if defined(RV_POOL_NONE)
#include "rvmem.h"
#endif
/* If in debug mode, then turn on statistics collection */
#if defined(RV_DEBUG_ON)
#define RV_POOL_STATS
#endif
static size_t rvPoolCalcBlockSize(size_t blockSize) {
size_t bs = rvAlign(blockSize + RV_POOL_ALLOCBLOCKSIZE);
if (bs < sizeof(RvBlock))
bs = sizeof(RvBlock);
return bs;
}
/* Policy for determining the default page */
#define RV_POOL_DEFAULTBLOCKS 16 /* Default # blocks / page */
#define RV_POOL_MINPAGESIZE 256 /* Minimum page size */
#define RV_POOL_MAXPAGESIZE (32 * 1024) /* Maximum page size */
size_t rvPoolPageSize(size_t blockSize) {
/* Policy: Allocate pages of at least RV_POOL_MINPAGESIZE bytes */
/* and no more than RV_POOL_MAXPAGESIZE, except if the block size */
/* is greater than RV_POOL_MAXPAGESIZE then allocate block size */
/* pages. The default number of blocks per page is */
/* RV_POOL_DEFAULTBLOCKS. */
size_t bs = rvPoolCalcBlockSize(blockSize);
size_t pageSize;
/* first check if one fits, if so, try DEFAULTBLOCKS amount */
pageSize = bs + RV_POOL_ALLOCBLOCKSIZE + sizeof(RvPage);
if (pageSize < RV_POOL_MAXPAGESIZE) {
pageSize = bs * RV_POOL_DEFAULTBLOCKS + RV_POOL_ALLOCBLOCKSIZE + sizeof(RvPage);
if (pageSize < RV_POOL_MINPAGESIZE)
pageSize = RV_POOL_MINPAGESIZE;
else if (pageSize > RV_POOL_MAXPAGESIZE)
pageSize = RV_POOL_MAXPAGESIZE;
}
return pageSize;
}
static void rvPoolInitializePage(RvPool* p, RvPage* page,
size_t size) {
RvBlock* tmp = p->blocks;
RvBlock* ptr = p->blocks = (RvBlock*)((char*)page + sizeof(RvPage));
size_t i;
/* Initialize all the blocks to point at the next adjacent block, */
/* except the last block in the page. The last block in the page */
/* should point at p->blocks and p->blocks should point at */
/* the first block in the page. */
for (i = 0; i < p->blocksPerPage - 1; ++i) {
#if defined(RV_DEBUG_ON)
/* Fill in overrun guard band */
ptr->guard = 0xC0DEC0DE;
#endif
ptr->next = (RvBlock*)((char*)ptr + p->realBlockSize);
ptr = ptr->next;
}
#if defined(RV_DEBUG_ON)
ptr->guard = 0xC0DEC0DE;
#endif
ptr->next = tmp;
#if defined(RV_DEBUG_ON)
/* Fill end of page with RvAllocBlock header (for overrun detection)*/
((RvAllocBlock*)((char*)ptr + p->realBlockSize))->guard = 0xC0DEC0DE;
#endif
#if defined(RV_POOL_STATS)
p->numOfBlocks += p->blocksPerPage;
#endif
}
static void rvPoolAddPage(RvPool* p) {
RvPage* tmp = p->pages;
RvPage* page;
/* Allocate the new page and initialize it */
if ((page = (RvPage*)rvAllocAllocate(p->alloc, p->pageSize)) != NULL) {
rvPoolInitializePage(p, page, p->pageSize);
page->next = tmp;
p->pages = page;
}
}
static void rvPoolRemovePage(RvPool* p) {
if (p->pages) {
RvPage* page = p->pages;
p->pages = p->pages->next;
rvAllocDeallocate(p->alloc, p->pageSize, page);
}
}
RvPool* rvPoolConstructEx1(RvPool* p, size_t blockSize, size_t pageSize,
void (*constructor)(void* ptr, void* data),
void (*destructor)(void* ptr, void* data), void* data, RvAlloc* alloc) {
rvMutexConstruct(&p->mutex);
p->blockSize = blockSize;
p->realBlockSize = rvPoolCalcBlockSize(blockSize);
p->constructor = constructor;
p->destructor = destructor;
p->data = data;
p->alloc = alloc;
p->pageSize = pageSize;
p->blocksPerPage = (p->pageSize - RV_POOL_ALLOCBLOCKSIZE - sizeof(RvPage)) / p->realBlockSize;
p->blocks = NULL;
p->pages = NULL;
p->numOfBlocks = 0;
p->numOfAllocBlocks = 0;
return p;
}
RvPool* rvPoolConstructEx2(RvPool* p, size_t blockSize, size_t blocksPerPage,
void (*constructor)(void* ptr, void* data),
void (*destructor)(void* ptr, void* data), void* data, RvAlloc* alloc) {
size_t bs = rvPoolCalcBlockSize(blockSize);
size_t pageSize = (bs * blocksPerPage) + RV_POOL_ALLOCBLOCKSIZE + sizeof(RvPage);
return rvPoolConstructEx1(p, blockSize, pageSize, constructor,
destructor, data, alloc);
}
void rvPoolDestruct(RvPool* p) {
while (p->pages != NULL)
rvPoolRemovePage(p);
rvMutexDestruct(&p->mutex);
}
void rvPoolReserve(RvPool* p, size_t blocks) {
if (blocks != 0) {
size_t pages = ((blocks - 1) / p->blocksPerPage) + 1;
size_t i;
for (i = 0; i < pages; ++i)
rvPoolAddPage(p);
}
}
void* rvPoolAllocate(RvPool* p) {
RvBlock* ptr;
#if defined(RV_POOL_NONE)
ptr = rvMemAlloc(p->realBlockSize);
if (p->constructor)
p->constructor(ptr, p->data);
return ptr;
#endif
rvMutexLock(&p->mutex);
/* If no free blocks exist */
if(p->blocks == NULL) {
rvPoolAddPage(p);
if(p->blocks == NULL) {
rvMutexUnlock(&p->mutex);
return NULL;
}
}
/* Allocate a block */
ptr = p->blocks;
p->blocks = p->blocks->next;
#if defined (RV_DEBUG_ON)
ptr = (RvBlock*)((char *)ptr + RV_POOL_ALLOCBLOCKSIZE);
#endif
#if defined(RV_POOL_STATS)
++(p->numOfAllocBlocks);
#endif
rvMutexUnlock(&p->mutex);
if (p->constructor)
p->constructor(ptr, p->data);
return ptr;
}
void rvPoolDeallocate(RvPool* p, void* ptr) {
RvBlock* tmp;
#if defined(RV_POOL_NONE)
if (p->destructor)
p->destructor(ptr, p->data);
rvMemFree(ptr);
return;
#endif
if(ptr == NULL)
return;
if (p->destructor)
p->destructor(ptr, p->data);
rvMutexLock(&p->mutex);
tmp = p->blocks;
#if defined(RV_DEBUG_ON)
ptr = (char*)ptr - RV_POOL_ALLOCBLOCKSIZE;
/* Detect over-run of this block or under-run of next block */
assert(((RvAllocBlock*)((char*)ptr + p->realBlockSize))->guard == 0xC0DEC0DE);
/* Detect under-run of this block or over-run of previous block */
assert(((RvAllocBlock*)ptr)->guard == 0xC0DEC0DE);
#endif
/* Return block to free block list */
p->blocks = (RvBlock*)ptr;
p->blocks->next = tmp;
#if defined(RV_POOL_STATS)
--(p->numOfAllocBlocks);
#endif
rvMutexUnlock(&p->mutex);
}
void rvPoolGetStats(RvPool* p, size_t* numOfBlocks, size_t* numOfAllocBlocks) {
rvMutexLock(&p->mutex);
*numOfBlocks = p->numOfBlocks;
*numOfAllocBlocks = p->numOfAllocBlocks;
rvMutexUnlock(&p->mutex);
}
#if defined(RV_DEBUG_ON)
#if defined(RV_IO_ANSI)
#include <stdio.h>
#endif
static void rvPoolDumpPage(RvPool* p, RvPage* page) {
size_t i;
unsigned int* ptr = (unsigned int*)page;
#if defined(RV_IO_ANSI)
printf("\n<<<<<<<<<<<<<<<<<<<<<<<<Page>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
for (i = 0; i < p->pageSize / sizeof(ptr); ++i) {
if (i % 8 == 0)
printf("\n%X:", (unsigned)ptr);
else
printf(" ");
printf("%08X", *ptr);
++ptr;
}
#endif
}
void rvPoolDump(RvPool* p) {
RvPage* page;
rvMutexLock(&p->mutex);
page = p->pages;
while (page) {
rvPoolDumpPage(p, page);
page = page->next;
}
rvMutexUnlock(&p->mutex);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -