First, the basic data structure
1 Union M_block2 {3Union m_block*Next;4Unsignedintsize;5 };6 7 structm_list8 {9Union m_block*Free ;Tenpthread_spinlock_tLock; OneUnsignedintsize; A }; - - structM_pool the { - structm_pool*Next; - }; - + structM_MPCB - { + void*Last ; A structm_pool*Pool; atpthread_spinlock_t*Lock; - structm_list*list; -Unsignedintavailable; - }; -
Second, memory pool management logic flow and structure description
Union M_block: Represents a piece of memory, when this block of memory is used, the size member is a block of memory, and when this memory block is idle, the next member points to the next piece of free memory, thus constituting the free memory linked list
struct M_list: The management node of the free memory block, each node manages a memory block node of a congenial size, which is directed by the free member to an idle memory block-linked header node, and lock is used to protect secure access to members in a multithreaded environment. A size member represents the size of the memory block managed by this memory block management node
struct M_pool: The actual memory pool linked list, the entire pool of memory thus constituted
struct M_MPCB: The memory pool management structure, as the manager of the whole memory pool, which manages the memory pool chain list composed of struct M_pool and the memory block management structure composed of struct m_list (can be array, search tree, etc.). The pool member points to the head node of the memory pool list, and the last member points to the unallocated memory start address in the memory pool represented by the pool member, avaliable represents the free space that is not yet allocated in the memory pool represented by the pool member.
When memory is requested, the memory is aligned according to the size of the request, and then the corresponding memory block management node is obtained based on the size of the alignment (how to obtain the details below), and whether the free member of the management node is null if NULL then constructs a new struct m_block struct to return, If not NULL, returns the free member and updates the
When the memory block is freed, the memory block size can be obtained by subtracting the offset from the given address, then the management node is obtained based on the size of the memory block, and then the memory block is traced to the free list header and the free member is updated
Iii. Detailed Implementation Details
1, when the application request of the memory size interval (that is, may be requested maximum memory and may be requested minimum memory difference) can be said to use the alignment unit (4 or 8) partition interval, and then each size corresponding to a struct m_list structure, the structure of these structures in an array, The array elements are obtained directly from the size and the first address of the group (the list member stored in the struct M_MPCB) when the management node needs to be obtained.
2, when the application request memory size interval is large but there are some relatively concentrated such as similar 4,8,3,9,34,23,16,19,512,890 before the comparison concentration of 40, then this part can use the first method to put the struct m_list struct in an array, The Union M_block Consortium can be constructed directly from malloc when it exceeds 40, and this method is more suitable for most cases where there is a large memory request in the occasional few cases, where the maximum memory block member must be added in the struct M_MPCB. The malloc assignment is directly applicable when the request size is greater than this value.
3, when the application request memory size interval is large, evenly distributed and application frequency equalization can consider the structure of the struct m_list structures in the form of red and black trees, struct M_MPCB in the list member points to the root node, when the need to allocate in tree species search Management node, If not found, the management node is created and added to the tree.
四、一个 Concrete Implementation
#include <pthread.h>#include<stdlib.h>#include<string.h>typedef Union block_t{unsignedintSize/**/Union block_t* NEXT;/**/}m_block_t;typedefstructlist_t{pthread_spinlock_tLock;/**/Union block_t* FREE;/**/}m_list_t;typedefstructmpool{structMpool* Next;/**/}m_mpool;typedefstructmpcb{structmpool* Pool;/**/ structlist_t* list;/**/ void* LAST;/**/unsignedintAvali;/**/unsignedintMaxblock;/**/unsignedintSize/**/pthread_spinlock_tLock;/**/}M_MPCB;#defineM_size_align (Size) (((size) + 3) & (~))#defineM_get_offset (Size) (((size) >> 2)-1)#defineM_get_pool () (&memory_pool_control_block)Static structMPCB Memory_pool_control_block;void*M_alloc (unsignedintsize) {m_block_t* block =NULL; unsignedint as=m_size_align (size); if( as> M_get_pool ()Maxblock) {Block= (m_block_t*) m_salloc (sizeof(*block) + as); } Else{block= M_new_block ( as); } Block->size = as; return(void*) (Block +1);}voidM_free (void*mem) {m_block_t* block = (m_block_t*) mem-1; if(Block->size > M_get_pool ()Maxblock) {free (block); } Else{m_list_t* List = M_get_list (block->size); Pthread_spin_lock (&list->Lock); Block->next = list->Free ; List->free =Block; Pthread_spin_unlock (&list->Lock); }}void*M_realloc (void* Mem, unsignedintnemize) {unsignedintSize = ((m_block_t*) mem-1),size; if(Nemize >size) { void* Newmem =M_alloc (nemize); memcpy (Newmem, mem, size); M_free (MEM); returnNewmem; } Else { returnMem; }}intm_mpcb_init (unsignedintMaxblock, unsignedintsize) {unsignedintASMB =m_size_align (Maxblock); unsignedintASP =m_size_align (size); m_list_t* List =M_list_init (ASMB); M_mpool* Pool =m_new_pool (ASP); M_MPCB* MPCB =M_get_pool (); MPCB->size =ASP; MPCB->pool =Pool; MPCB->list =list; MPCB->last = (void*) (pool +1); MPCB->avali =ASP; MPCB->maxblock =ASMB; Pthread_spin_init (&mpcb->Lock, pthread_process_private); return 1;}voidM_mpcb_destroy () {M_MPCB* MPCB =M_get_pool (); M_list_destroy (MPCB->list, M_get_offset (mpcb->maxblock) +1); M_pool_destroy (MPCB-pool); memset (MPCB,0,sizeof(*MPCB));}Staticm_list_t*m_list_init (unsignedintMaxblock) { intItems = M_get_offset (maxblock) +1; m_list_t* List = (m_list_t*) m_salloc (sizeof(*list) *items); inti = items-1; for(; I >=0; --i) {pthread_spin_init (&list[i].Lock, pthread_process_private); } returnlist;}Staticm_list_t*m_get_list (unsignedintblock_size) {m_list_t* List = M_get_pool ()list; intoffset =M_get_offset (block_size); return(List +offset);}Static voidM_list_destroy (m_list_t* List_head,intList_items) {m_list_t* List =List_head; inti = List_items-1; for(; I >=0; --i) {Pthread_spin_destroy (&list[i].Lock); } free (list_head);}Staticm_block_t*M_new_block (unsignedintsize) {m_list_t* List =m_get_list (size); Pthread_spin_lock (&list->Lock); m_block_t* block = list->Free ; if(NULL = =block) {Pthread_spin_unlock (&list->Lock); Block= (m_block_t*) m_palloc (sizeof(*block) +size); } Else{List->free = block->Next; Pthread_spin_unlock (&list->Lock); } returnBlock;}Staticm_mpool*M_new_pool (unsignedintpool_size) {M_mpool* Pool = (m_mpool*) m_salloc (sizeof(*pool) +pool_size); returnPool;}Static voidM_pool_destroy (M_mpool*pool_head) {M_mpool* Pool =Pool_head; M_mpool* TMP =Pool; while(NULL! =tmp) {tmp= pool->Next; Free (pool); Pool=tmp; }}Static void*M_salloc (unsignedintsize) { void* Mem =malloc (size); memset (Mem,0, size); returnMem;}Static void*M_palloc (unsignedintsize) {M_MPCB* MPCB =M_get_pool (); Pthread_spin_lock (&mpcb->Lock); unsignedintAvali = mpcb->Avali; if(Avali <size) {M_recover (MPCB-Last , Avali); M_mpool* Npool = M_new_pool (mpcb->size); Npool->next = mpcb->Pool; MPCB->pool =Npool; MPCB->avali = mpcb->size; MPCB->last = (void*) (Npool +1); } void* Mem = mpcb->Last ; MPCB->last = (void*) ((m_byte_t*) mem +size); MPCB->avali-=size; Pthread_spin_unlock (&mpcb->Lock); returnMem;}Static voidM_recover (void* Mem,intoffset) { if(Offset >sizeof(m_block_t)) {m_block_t* block = (m_block_t*) mem; Block->size = offset-sizeof(m_block_t); M_free (Block+1); }}#undefM_get_pool
This implementation is implemented for the second case.
V. Summary
This memory pool design can be used for unequal size memory requests. Specific efficiency has not been tested, the demo may not be directly through the compilation, just give a thought.