- 论坛徽章:
- 0
|
头文件:
- /*
- * The young Library
- * Copyright (c) 2005 by Yang Huan(杨桓)
- * Permission to use, copy, modify, distribute and sell this software for any
- * purpose is hereby granted without fee, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and this
- * permission notice appear in supporting documentation.
- * The author make no representations about the suitability of this software
- * for any purpose. It is provided "as is" without express or implied warranty.
- */
- /******************************************************************************/
- /******************************************************************************/
- #ifndef __MACRO_C_YOUNG_LIBRARY_MEMORY_FUNCTION_HEADER_FILE__
- #define __MACRO_C_YOUNG_LIBRARY_MEMORY_FUNCTION_HEADER_FILE__
- /******************************************************************************/
- #include "yc_definition.h"
- #ifdef __cplusplus
- namespace youngc { extern "C" {
- #endif
- /******************************************************************************/
- /******************************************************************************/
- /* 返回 element_size 对齐后的字节数 */
- size_t memalign( size_t element_size, bool memory_type );
- /* 获取内存池的链数 */
- size_t get_pool_lists_count( void );
- /* 获取内存池执行分配的次数 */
- size_t get_pool_alloc_count( void );
- /* 获取内存池执行归还的次数 */
- size_t get_pool_dealloc_count( void );
- /* 设置在并行系统中使用的加锁函数 */
- void set_pool_lock( void (*lock)(size_t index) );
- /* 设置在并行系统中使用的解锁函数 */
- void set_pool_unlock( void (*unlock)(size_t index) );
- /* 打印内存池 */
- void pool_print( void );
- /* 从内存池中申请至少 bytes 个字节的内存块 */
- void* pool_alloc( size_t bytes );
- /* 只将内存块回收至内存池 */
- void pool_dealloc( void* ptr, size_t bytes );
- /* 先将内存块回收至内存池,再将内存池中空闲的内存页释放 */
- void pool_free( void* ptr, size_t bytes );
- /******************************************************************************/
- /******************************************************************************/
- #ifdef __cplusplus
- } }
- #endif
- #endif
- /******************************************************************************/
- /******************************************************************************/
复制代码
实现文件:
- /*
- * The young Library
- * Copyright (c) 2005 by Yang Huan(杨桓)
- * Permission to use, copy, modify, distribute and sell this software for any
- * purpose is hereby granted without fee, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and this
- * permission notice appear in supporting documentation.
- * The author make no representations about the suitability of this software
- * for any purpose. It is provided "as is" without express or implied warranty.
- */
- /*
- * 内存池由 MEMORY_POOL_LISTS 个链表组成,每个链表分别管理不同大小的内存块,
- * 每个链表管理的内存块大小 = MEMORY_POOL_MIN + 索引 * MEMORY_POOL_ALIGN
- *
- * 内存池原理图:
- * 索引:0 1 2 3 ...... MEMORY_POOL_LISTS - 1
- * --------------------------------------------------------------------------
- * | useable | | | | ...... | |
- * --------------------------------------------------------------------------
- * | buffer |
- * -----------
- * | first |
- * -----------
- * |
- * |
- * | --------
- * ->| next |--
- * |------| |
- * | use | |
- * |------| |
- * | page | |
- * -------- |
- * |
- * ----------
- * |
- * | --------
- * ->| next | --> NULL
- * |------|
- * | use | 注:使用该字的二进制位来记录内存页中各内存块的使用状态
- * |------|
- * | page | 注:内存页大小 = 该链表处理的内存块大小 * use的位数
- * --------
- */
- /******************************************************************************/
- /******************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include "yc_memory.h"
- #ifdef __cplusplus
- namespace youngc { extern "C" {
- #endif
- /******************************************************************************/
- /******************************************************************************/
- enum YOUNG_LIBRARY_MEMORY_CONSTANT
- {
- MEMORY_ALIGN_SIZE = sizeof(int),
- MEMORY_POOL_BUFFER = 8,
- MEMORY_POOL_ALIGN = 4,
- MEMORY_POOL_MIN = 8,
- MEMORY_POOL_MAX = 128,
- MEMORY_POOL_BLOCKS = sizeof(ylib_word_t) * BYTE_BITS,
- MEMORY_POOL_LISTS = ( MEMORY_POOL_MAX - MEMORY_POOL_MIN )
- / MEMORY_POOL_ALIGN + 1
- };
- typedef struct memory_page
- {
- ylib_word_t use; /* 二进制位映射的内存块已使用则该位为1,否则为0 */
- struct memory_page* next; /* 下一个内存页 */
- } mempage_t;
- typedef struct memory_list
- {
- size_t useable; /* 未满的可供分配的内存页数 */
- mempage_t* buffer[MEMORY_POOL_BUFFER]; /* 页面缓存 */
- mempage_t* first; /* 第一个内存页 */
- } memlist_t;
- #define MEMALLOC( bytes) malloc( bytes )
- #define MEMFREE( ptr ) free( ptr )
- #define LIST_INDEX( bytes ) \
- ( (bytes) <= MEMORY_POOL_MIN ? 0 \
- : ((bytes) - MEMORY_POOL_MIN + MEMORY_POOL_ALIGN - 1) \
- / MEMORY_POOL_ALIGN )
- #define BLOCK_SIZE( index ) ( MEMORY_POOL_MIN + (index) * MEMORY_POOL_ALIGN )
- #define PAGE_SIZE( index ) ( BLOCK_SIZE(index) * MEMORY_POOL_BLOCKS )
- /******************************************************************************/
- /******************************************************************************/
- static void (*pool_lock)( size_t ) = NULL;
- static void (*pool_unlock)( size_t ) = NULL;
- static size_t pool_alloc_count = 0;
- static size_t pool_dealloc_count = 0;
- static memlist_t pool[MEMORY_POOL_LISTS] = { {0, {NULL}, NULL} };
- static unsigned char bitmap[] =
- {
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
- 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
- };
- /******************************************************************************/
- /******************************************************************************/
- size_t get_pool_lists_count( void )
- {
- return MEMORY_POOL_LISTS;
- }
- size_t get_pool_alloc_count( void )
- {
- return pool_alloc_count;
- }
- size_t get_pool_dealloc_count( void )
- {
- return pool_dealloc_count;
- }
- void set_pool_lock( void (*lock)(size_t) )
- {
- pool_lock = lock;
- }
- void set_pool_unlock( void (*unlock)(size_t) )
- {
- pool_unlock = unlock;
- }
- /******************************************************************************/
- size_t memalign( size_t element_size, bool memory_type )
- {
- size_t residue = MEMORY_ALIGN_SIZE - 1;
- size_t alignsize = element_size & ~residue;
- if( element_size & residue )
- alignsize += MEMORY_ALIGN_SIZE;
- if( memory_type == true && alignsize < sizeof(ylib_inner_t) )
- alignsize = sizeof(ylib_inner_t);
- return alignsize;
- }
- /******************************************************************************/
- void pool_print( void )
- {
- int i, j;
- mempage_t* curr;
- ylib_word_t mask;
- char *str_last, bits[MEMORY_POOL_BLOCKS + 1] = { '\0' };
- for( i = 0; i < MEMORY_POOL_LISTS; ++i )
- {
- if( !(pool[i].first) )
- continue;
- printf( "\npool[%d] chunk = %d", i, BLOCK_SIZE(i) );
- printf( "\n\tpool[%d].useable = %u", i, pool[i].useable );
- for( j = 0; j < MEMORY_POOL_BUFFER; ++j )
- printf( "\n\tpool[%d].buffer[%d] = %p", i, j, pool[i].buffer[j] );
- printf( "\n\tpool[%d].first = %p: ", i, pool[i].first );
- curr = pool[i].first;
- while( curr )
- {
- mask = 1;
- str_last = bits + MEMORY_POOL_BLOCKS;
- for( j = 0; j < MEMORY_POOL_BLOCKS; ++j, mask <<= 1 )
- *--str_last = (char)(curr->use & mask ? '1' : '0');
- printf( "\n\t" );
- printf( "next = %p | use = %s", curr->next, bits );
- curr = curr->next;
- }
- }
- }
- /******************************************************************************/
- static void* page_alloc( size_t index, mempage_t* curr )
- {
- void* ptr = NULL;
- size_t i;
- /* 先找到第一个空闲块所在的字节 */
- for( i = 0; i < sizeof(ylib_word_t); ++i )
- {
- ylib_byte_t value = (ylib_byte_t)( curr->use >> (BYTE_BITS * i) );
- if( value != YLIB_BYTE_MAX )
- {
- ylib_word_t mask = 1;
- size_t biti = bitmap[value]; /* 从映射表中查找第一个等于 0 的位 */
- mask <<= ( BYTE_BITS * i + biti ); /* 计算掩码 */
- curr->use |= mask; /* 设置使用标志 */
- ptr = (ylib_byte_t*)curr + sizeof(mempage_t)
- + (i * BYTE_BITS + biti) * BLOCK_SIZE( index );
- if( curr->use == YLIB_WORD_MAX )
- --( pool[index].useable );
- return ptr;
- } /* end if */
- } /* end for i */
- return ptr;
- }
- /******************************************************************************/
- void* pool_alloc( size_t bytes )
- {
- void* ptr = NULL;
- if( bytes > MEMORY_POOL_MAX )
- {
- ptr = MEMALLOC( bytes );
- }
- else
- {
- int i;
- mempage_t* pg = NULL;
- size_t index = LIST_INDEX( bytes );
- if( pool_lock )
- pool_lock( index );
- if( pool[index].first && pool[index].useable > 0 )
- {
- mempage_t *prev = NULL, *curr = NULL;
- /* 先查找页面缓存 */
- for( i = 0; i < MEMORY_POOL_BUFFER; ++i )
- {
- if( pool[index].buffer[i] )
- {
- ptr = page_alloc( index, pool[index].buffer[i] );
- /* 如果该页已满,则将该页自页面缓存中退出 */
- if( pool[index].buffer[i]->use == YLIB_WORD_MAX )
- pool[index].buffer[i] = NULL;
- else if( i > 0 )
- {
- /* 如果该页不在缓存首,则将该页调整至缓存首 */
- pool[index].buffer[0] = pool[index].buffer[i];
- pool[index].buffer[i] = NULL;
- }
- goto EXIT_POOL_ALLOC;
- }
- } /* 页面缓存 */
- /* 页面缓存为空,则遍历链中的所有内存页寻找空闲的内存块 */
- curr = pool[index].first;
- while( curr )
- {
- if( curr->use == YLIB_WORD_MAX ) /* 该页中没有空闲块 */
- {
- /* 进入下一页 */
- prev = curr;
- curr = curr->next;
- }
- else /* 该页中有空闲块 */
- {
- size_t count = 0;
- ptr = page_alloc( index, curr );
- /* 继续遍历链表,寻找其他未满的页面,将之放入页面缓存 */
- while( curr && count < pool[index].useable )
- {
- if( curr->use != YLIB_WORD_MAX )
- {
- /* 页面缓存还有位置则放入页面缓存 */
- if( count < MEMORY_POOL_BUFFER )
- pool[index].buffer[count] = curr;
- ++count;
- /* 如果当前页未满并且不在链首,则将之移至链首 */
- if( pool[index].first != curr )
- {
- prev->next = curr->next;
- curr->next = pool[index].first;
- pool[index].first = curr;
- curr = prev->next;
- continue;
- }
- }
- prev = curr;
- curr = curr->next;
- }
- goto EXIT_POOL_ALLOC;
- } /* end else */
- } /* end while */
- } /* end if */
- else
- {
- /* 该链下未分配内存页或无空闲块,此时需增加新的内存页 */
- pg = (mempage_t*)MEMALLOC( sizeof(mempage_t) + PAGE_SIZE(index) );
- if( pg )
- {
- pg->next = pool[index].first;
- pool[index].first = pg;
- pg->use = 1;
- ptr = (ylib_byte_t*)pg + sizeof(mempage_t);
- ++( pool[index].useable );
- pool[index].buffer[0] = pg;
- }
- }
- EXIT_POOL_ALLOC:
- if( pool_unlock )
- pool_unlock( index );
- } /* end else */
- if( ptr )
- ++pool_alloc_count;
- return ptr;
- }
- /******************************************************************************/
- void pool_dealloc( void* ptr, size_t bytes )
- {
- if( !ptr )
- return;
- if( bytes <= MEMORY_POOL_MAX )
- {
- size_t index = LIST_INDEX( bytes );
- size_t pagesize = PAGE_SIZE( index );
- mempage_t *prev = NULL, *curr = pool[index].first;
- ylib_byte_t *begin, *end, *blk = (ylib_byte_t*)ptr;
- if( pool_lock )
- pool_lock( index );
- while( curr )
- {
- begin = (ylib_byte_t*)curr + sizeof(mempage_t);
- end = begin + pagesize;
- if( blk < begin || blk >= end ) /* 判断ptr是否在当前页内 */
- {
- prev = curr;
- curr = curr->next;
- }
- else
- {
- size_t blk_size = BLOCK_SIZE( index );
- /* 检查ptr是否正确 */
- if( (blk - begin) % blk_size == 0 )
- {
- ylib_word_t mask = 1;
- size_t blk_index = (blk - begin) / blk_size;
- size_t old = curr->use;
- mask <<= blk_index;
- curr->use &= ~mask;
- /* 如果当前页不在链首,则将之移至链首 */
- if( pool[index].first != curr )
- {
- prev->next = curr->next;
- curr->next = pool[index].first;
- pool[index].first = curr;
- }
- /* 如果归还前内存页已满,则将可用页数加一 */
- if( old == YLIB_WORD_MAX )
- ++( pool[index].useable );
- ++pool_dealloc_count;
- }
- break;
- } /* end else */
- } /* end while */
- if( pool_unlock )
- pool_unlock( index );
- return;
- } /* end if */
- /* ptr不是由内存池分配 */
- MEMFREE( ptr );
- ++pool_dealloc_count;
- }
- /******************************************************************************/
- void pool_free( void* ptr, size_t bytes )
- {
- if( ptr )
- pool_dealloc( ptr, bytes );
- if( bytes <= MEMORY_POOL_MAX )
- {
- int i;
- size_t index = LIST_INDEX( bytes );
- mempage_t *erase = NULL, *prev = NULL, *curr = pool[index].first;
- if( pool_lock )
- pool_lock( index );
- while( curr )
- {
- if( curr->use != 0 ) /* 判断是否是空闲页 */
- {
- prev = curr;
- curr = curr->next;
- }
- else
- {
- /* 从页面缓存中退出 */
- for( i = 0; i < MEMORY_POOL_BUFFER; ++i )
- {
- if( pool[index].buffer[i] == curr )
- {
- pool[index].buffer[i] = NULL;
- break;
- }
- }
- if( prev )
- prev->next = curr->next; /* 空闲页不在链首 */
- else
- pool[index].first = curr->next; /* 空闲页在链首 */
- /* 将空闲页释放 */
- erase = curr;
- curr = curr->next;
- MEMFREE( erase );
- --( pool[index].useable );
- } /* end if */
- } /* end while */
- if( pool_unlock )
- pool_unlock( index );
- }
- }
- /******************************************************************************/
- /******************************************************************************/
- #ifdef __cplusplus
- } }
- #endif
- /******************************************************************************/
- /******************************************************************************/
复制代码 |
|