一个支持多线程的内存池
来源:互联网 发布:js radio value 编辑:程序博客网 时间:2024/06/06 02:21
http://blog.vckbase.com/localvar/archive/2010/10/28/51946.html
代码并不复杂,不多做解释了,用的是windows api,但应该不难移植。
头文件:
#pragma once
int mp_register_usage( size_t size, size_t count );
bool mp_create();
void mp_destory();
void* mp_alloc( int objtype );
void mp_free( int objtype, void* mem );
实现文件:
#include <windows.h>
////////////////////////////////////////////////////////////////////////////////
#define MP_MAX_OBJECT_TYPE 8
struct MP_OBJECT_ENTRY
{
SLIST_HEADER lsthdr;
size_t size;
size_t count;
};
static MP_OBJECT_ENTRY s_entries[MP_MAX_OBJECT_TYPE] = { 0 };
static void* s_base = NULL;
////////////////////////////////////////////////////////////////////////////////
int mp_register_usage( size_t size, size_t count )
{
if( size == 0 || count == 0 )
return -1;
size += MEMORY_ALLOCATION_ALIGNMENT - 1;
size /= MEMORY_ALLOCATION_ALIGNMENT;
size *= MEMORY_ALLOCATION_ALIGNMENT;
for( int i = 0; i < MP_MAX_OBJECT_TYPE; ++i )
{
MP_OBJECT_ENTRY* entry = s_entries + i;
if( entry->size == size || entry->size == 0 )
{
entry->size = size;
entry->count += count;
return i;
}
}
return -1;
}
//------------------------------------------------------------------------------
bool mp_create()
{
size_t total = 0;
for( int i = 0; i < MP_MAX_OBJECT_TYPE; ++i )
total += s_entries[i].count * s_entries[i].size;
s_base = VirtualAlloc( NULL, total, MEM_COMMIT, PAGE_READWRITE );
if( s_base == NULL )
return false;
char* base = reinterpret_cast<char*>( s_base );
for( int i = 0; i < MP_MAX_OBJECT_TYPE; ++i )
{
MP_OBJECT_ENTRY* entry = s_entries + i;
InitializeSListHead( &entry->lsthdr );
char* addr = base + entry->size * entry->count;
addr -= MEMORY_ALLOCATION_ALIGNMENT;
for( size_t j = 0; j < entry->count; ++j )
{
SLIST_ENTRY* node = reinterpret_cast<SLIST_ENTRY*>( addr );
InterlockedPushEntrySList( &entry->lsthdr, node );
addr -= entry->size;
}
base += entry->count * entry->size;
}
return true;
}
//------------------------------------------------------------------------------
void mp_destory()
{
if( s_base != NULL )
{
VirtualFree( s_base, 0, MEM_RELEASE );
s_base = NULL;
}
}
//------------------------------------------------------------------------------
void* mp_alloc( int objtype )
{
MP_OBJECT_ENTRY* entry = s_entries + objtype;
SLIST_ENTRY* node = InterlockedPopEntrySList( &entry->lsthdr );
char* p = reinterpret_cast<char*>( node );
if( p != NULL )
p -= entry->size - MEMORY_ALLOCATION_ALIGNMENT;
return p;
}
//------------------------------------------------------------------------------
void mp_free( int objtype, void* mem )
{
if( mem == NULL )
return;
MP_OBJECT_ENTRY* entry = s_entries + objtype;
char* p = reinterpret_cast<char*>( mem );
p += entry->size - MEMORY_ALLOCATION_ALIGNMENT;
SLIST_ENTRY* node = reinterpret_cast<SLIST_ENTRY*>( p );
InterlockedPushEntrySList( &s_entries[objtype].lsthdr, node );
}
////////////////////////////////////////////////////////////////////////////////
应用举例:
////////////////////////////////////////////////////////////////////////////////
template<size_t size>
class CSomeObject
{
private:
static int s_objtype;
private:
char m_data[size];
public:
CSomeObject() {}
void DoSomeThing()
{
_tprintf( _T("Object Type = %d, Object Size = %d/n"), s_objtype, size );
}
~CSomeObject() {}
public:
static void RegisterMemoryUsage( size_t count )
{
s_objtype = mp_register_usage( sizeof(CSomeObject<size>), count );
}
static void* operator new( size_t size )
{
return mp_alloc( s_objtype );
}
static void operator delete( void* mem )
{
mp_free( s_objtype, mem );
}
};
template<size_t size> int CSomeObject<size>::s_objtype = 0;
////////////////////////////////////////////////////////////////////////////////
HANDLE g_stopevent = NULL;
#define TEST_OBJECT( c, s ) /
case c:/
{/
CSomeObject<s>* p = new CSomeObject<s>;/
if( p != NULL )/
{/
p->DoSomeThing();/
delete p;/
}/
}/
break;
uintptr_t __stdcall worker_thread( void* )
{
srand( GetTickCount() );
while( WaitForSingleObject( g_stopevent, 0 ) == WAIT_TIMEOUT )
{
switch( rand() % 7 )
{
TEST_OBJECT( 0, 1 )
TEST_OBJECT( 1, 9 )
TEST_OBJECT( 2, 10 )
TEST_OBJECT( 3, 20 )
TEST_OBJECT( 4, 36 )
TEST_OBJECT( 5, 100 )
TEST_OBJECT( 6, 1000 )
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
int _tmain( int argc, _TCHAR* argv[] )
{
CSomeObject<1>::RegisterMemoryUsage( 100 );
CSomeObject<9>::RegisterMemoryUsage( 2 );
CSomeObject<10>::RegisterMemoryUsage( 100 );
CSomeObject<20>::RegisterMemoryUsage( 200 );
CSomeObject<36>::RegisterMemoryUsage( 300 );
CSomeObject<100>::RegisterMemoryUsage( 205 );
CSomeObject<1000>::RegisterMemoryUsage( 128 );
mp_create();
g_stopevent = CreateEvent( NULL, TRUE, FALSE, NULL );
for( int i = 0; i < 10; ++i )
{
uintptr_t h = _beginthreadex( NULL, 0, worker_thread, NULL, 0, NULL );
CloseHandle( reinterpret_cast<HANDLE>( h ) );
}
_getch();
SetEvent( g_stopevent );
Sleep( 500 );
CloseHandle( g_stopevent );
mp_destory();
return 0;
}
////////////////////////////////////////////////////////////////////////////////
- 一个支持多线程的内存池
- 发布一个多线程安全的内存池
- 支持多线程的内存分配器__gnu_cxx::__mt_alloc
- 关于一个支持多线程下载的Servlet
- 网络专用高效内存池,支持多线程.原创,非sgi的内存池
- Live555 的一个缺陷--例子不能支持多线程(已经修改成支持多线程)
- 一个支持多线程同步的堆栈的实现
- 一个支持多线程同步循环队列的实现
- 一个支持操作内存文件操作的类
- 如何实现一个支持共享内存的Map或Set
- 支持多线程的属性
- Cache+多线程下内存失效的一个bug
- c++ 多线程写日志的一个很实用的日志类源码(支持 c++ builder)
- 一个简单的写txt格式Log的方法,支持多线程
- 支持多线程的CLOG类
- Ogre的多线程同步支持
- Java对多线程的支持
- Ogre的多线程同步支持
- 绘制gif文件
- 关于背景图片固定 不会随着页面滚动而变化,及定位注意问题
- SQL的随机抽取
- C#创建数字证书并导出为pfx,并使用pfx进行非对称加解密
- 一个唱片商店的小例子 可以自动旋转唱片 点击弹出唱片
- 一个支持多线程的内存池
- 利用mysql的inet_aton()和inet_ntoa()函数存储IP地址
- VBScript 中 数值相减计算方法
- APIDEMO PROGRESS BAR
- Linux运行级别和chkconfig用法
- TDBChart和TChart的一些用法(转)
- 【JUNOS】学习整理 OSPF 篇
- MyEclipse配置WebService六步曲
- server 2005 附加数据库问题解决办法