⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rvpool.c

📁 h.248协议源码
💻 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 + -