一个支持多线程的内存池

来源:互联网 发布: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;
}

////////////////////////////////////////////////////////////////////////////////

 

原创粉丝点击