首页 > 代码库 > 重复造轮子系列--内存池(C语言)

重复造轮子系列--内存池(C语言)

mem_pool.h

 1 #ifndef MEM_POOL_H_
 2 #define MEM_POOL_H_
 3 
 4 typedef struct MemBlock {
 5     struct MemBlock* next;
 6     int size;
 7     void *ptr;
 8 } MemBlock;
 9 
10 typedef unsigned char byte;
11 
12 // 8 16 32 64 128 256 512 1024 2048 4096 
13 // 1 2  4  8  16  32  64  128  256  512
14 // 0 1  2  3  4   5   6   7    8    9
15 
16 #define MEM_POOL_MAX 10
17 #define MEM_BLOCK 8
18 #define MEM_BLOCK_BASE 8192
19 #define MEM_BLOCK_TYPE_NUM 10
20 #define MEM_BLOCK_FREE -1
21 
22 int       mem_pool_index(size_t size);
23 void      mem_pool_init();
24 void      mem_pool_free();
25 int       mem_block_num(size_t size);
26 MemBlock* mem_block_head_get(size_t size);
27 void*     mem_get(size_t size);
28 int       mem_free(void **ptr);
29 
30 #define mem_ret(ptr) mem_free((void **)&ptr)
31 
32 //////////////////////////////////////////////////////////////////////////
33 
34 typedef struct MemBlockDlist {
35     struct MemBlockDlist* prev;
36     struct MemBlockDlist* next;
37     int size;
38     void *ptr;
39 } MemBlockDlist;
40 
41 void  mem_pool_dlist_init();
42 void  mem_pool_dlist_free();
43 void* mem_realloc(size_t size);
44 void  mem_release(void** ptr);
45 
46 #define mem_alloc(s) mem_realloc(s)
47 #define mem_relex(p) mem_release((void **)&p)
48 
49 #endif

mem_pool.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <math.h>
  4 #include "mem_pool.h"
  5 
  6 static byte*     g_pool_mem[MEM_POOL_MAX] = {0};
  7 static MemBlock* g_pool[MEM_POOL_MAX]     = {0};
  8 
  9 int mem_pool_index(size_t size) {
 10     if (size > 0 && size <= MEM_BLOCK) return 0;
 11 
 12     size_t s = 1;
 13     size_t t = size;
 14     size_t i;
 15 
 16     i = log((float)t)/log(2.0); 17     s = s<<i;
 18     return s == size ? i-3 : i-2;
 19 }
 20 
 21 MemBlock* mem_block_head(size_t index) {
 22     if (index < 0 || index >= MEM_POOL_MAX) 
 23         return NULL;
 24     
 25     return g_pool[index];
 26 }
 27 
 28 MemBlock* mem_block_head_get(size_t size) {
 29     if (size > MEM_BLOCK_BASE/2 || size <= 0) {
 30         printf("size=%d too big to mem pool. using malloc plz\n", size);
 31         return NULL;
 32     }
 33     return mem_block_head(mem_pool_index(size));
 34 }
 35 
 36 int mem_block_num(size_t size) {
 37     return MEM_BLOCK_BASE/size;
 38 }
 39 
 40 static MemBlock* mem_block_alloc(byte* buf, int block_size, int block_num) {
 41     MemBlock *head, *curr, *next;
 42     int i;
 43 
 44     head = (MemBlock *)buf;
 45     head->size = MEM_BLOCK_FREE;
 46     head->ptr  = (byte*)head + sizeof(MemBlock);
 47     head->next = NULL;
 48 
 49     curr = head;
 50     for (i=1; i<block_num; i++) {
 51         next = (MemBlock*)((byte*)curr + block_size);
 52         next->size = MEM_BLOCK_FREE;
 53         next->ptr = (byte*)next + sizeof(MemBlock);
 54         curr->next = next;
 55         next->next = NULL;
 56         curr = next;
 57     }
 58     return head;
 59 }
 60 
 61 void mem_pool_init() {
 62     size_t l, i, s, n, b;
 63     for (l=0; l<MEM_BLOCK_TYPE_NUM; l++) {
 64         i = (size_t)pow(2.0, (double)l);
 65         b = i * MEM_BLOCK;
 66         s = b + sizeof(MemBlock);
 67         n = mem_block_num(b);
 68 
 69         g_pool_mem[l] = (byte *)malloc(s * n);
 70         if (NULL == g_pool_mem[l]) {
 71             break;
 72         }
 73         g_pool[l] = mem_block_alloc(g_pool_mem[l], s, n);
 74     }
 75     return;
 76 }
 77 
 78 void mem_pool_free() {
 79     for (int i=0; i<MEM_BLOCK_TYPE_NUM; i++) {
 80         if (NULL != g_pool_mem[i]) {
 81             free(g_pool_mem[i]);
 82             g_pool_mem[i] = NULL;
 83             g_pool[i] = NULL;
 84         }
 85     }
 86     return;
 87 }
 88 
 89 void* mem_get(size_t size) {
 90     MemBlock* head = mem_block_head_get(size);
 91     if (NULL == head) return NULL;
 92 
 93     do {
 94         if (head->size == MEM_BLOCK_FREE) {
 95             head->size = size;
 96             return head->ptr;
 97         } else {
 98             head = head->next;
 99         }
100     } while (head->next);
101 
102     return NULL;
103 }
104 
105 int mem_free(void **ptr) {
106     if (NULL == ptr || NULL == *ptr) return 0;
107     
108     MemBlock *block = (MemBlock *)((byte*)(*ptr) - sizeof(MemBlock));
109     block->size = MEM_BLOCK_FREE;
110     
111     return 1;
112 }

mem_pool_dlist.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <math.h>
  5 #include "mem_pool.h"
  6 
  7 static byte*          g_pool_buff[MEM_POOL_MAX]     = {0};
  8 static MemBlockDlist* g_pool_objects[MEM_POOL_MAX]  = {0};
  9 static MemBlockDlist* g_pool_freelist[MEM_POOL_MAX] = {0};
 10 static MemBlockDlist* g_pool_cursor[MEM_POOL_MAX]   = {0};
 11 
 12 MemBlockDlist* mem_block_dlist_head(size_t index) {
 13     if (index < 0 || index >= MEM_POOL_MAX) 
 14         return NULL;
 15 
 16     return g_pool_objects[index];
 17 }
 18 
 19 void mem_pool_cursor_init() {
 20     for(size_t i=0; i<MEM_POOL_MAX; i++)
 21         g_pool_cursor[i] = mem_block_dlist_head(i);
 22 }
 23 
 24 static MemBlockDlist* mem_block_dlist_alloc(byte* buf, int bk_size, int bk_num){
 25     MemBlockDlist *head, *curr, *next;
 26     int i;
 27 
 28     head = (MemBlockDlist *)buf;
 29     head->size = MEM_BLOCK_FREE;
 30     head->ptr  = (byte*)head + sizeof(MemBlockDlist);
 31     head->prev = NULL;
 32     head->next = NULL;
 33 
 34     curr = head;
 35     for (i=1; i<bk_num; i++) {
 36         next = (MemBlockDlist*)((byte*)curr + bk_size);
 37         next->size = MEM_BLOCK_FREE;
 38         next->ptr  = (byte*)next + sizeof(MemBlockDlist);
 39 
 40         curr->next = next;
 41         next->prev = curr;
 42         next->next = NULL;
 43 
 44         curr = next;
 45     }
 46     return head;
 47 }
 48 
 49 void mem_pool_dlist_init() {
 50     size_t l, i, s, n, b;
 51     for (l=0; l<MEM_BLOCK_TYPE_NUM; l++) {
 52         i = (size_t)pow(2.0, (double)l);
 53         b = i * MEM_BLOCK;
 54         s = b + sizeof(MemBlockDlist);
 55         n = mem_block_num(b);
 56 
 57         g_pool_buff[l] = (byte *)malloc(s * n);
 58         if (NULL == g_pool_buff[l]) {
 59             break;
 60         }
 61         g_pool_objects[l] = mem_block_dlist_alloc(g_pool_buff[l], s, n);
 62     }
 63 
 64     mem_pool_cursor_init();
 65 }
 66 
 67 void mem_pool_dlist_free() {
 68     for (int i=0; i<MEM_BLOCK_TYPE_NUM; i++) {
 69         if (NULL != g_pool_buff[i]) {
 70             free(g_pool_buff[i]);
 71 
 72             g_pool_buff[i]     = NULL;
 73             g_pool_objects[i]  = NULL;
 74             g_pool_freelist[i] = NULL;
 75             g_pool_cursor[i]   = NULL;
 76         }
 77     }
 78 }
 79 
 80 MemBlockDlist* mem_free_block_get(int index) {
 81     if (index < 0 || index >= MEM_POOL_MAX) return NULL;
 82 
 83     MemBlockDlist* tmp = g_pool_freelist[index];
 84     if (!tmp) return NULL;
 85 
 86     g_pool_freelist[index] = tmp->next;
 87     g_pool_freelist[index]->prev = NULL;
 88     tmp->next = NULL;
 89 
 90     return tmp;
 91 }
 92 
 93 void* mem_realloc(size_t size) {
 94     int index = mem_pool_index(size);
 95     if (index < 0 || index >= MEM_POOL_MAX) 
 96         return NULL;
 97     
 98     MemBlockDlist* ptr = mem_free_block_get(index);
 99     if (ptr) {
100         ptr->size = size;
101         return ptr->ptr;
102     }
103 
104     MemBlockDlist* cursor = g_pool_cursor[index];
105     if (NULL == cursor) {
106         printf("pool index=%d memory leak or queue is all used.\n", index);
107         return NULL;
108     }
109     
110     if (MEM_BLOCK_FREE == cursor->size) {
111         g_pool_cursor[index] = cursor->next;
112         cursor->size = size;
113         return cursor->ptr;
114     }
115 
116     return NULL;
117 }
118 
119 void  mem_release(void** ptr) {
120     if (NULL == ptr || NULL == *ptr) 
121         return;
122 
123     size_t len = sizeof(MemBlockDlist);
124     MemBlockDlist *block = (MemBlockDlist *)((byte*)(*ptr) - len);
125 
126     int index = mem_pool_index(block->size);
127     if (index < 0 || index >= MEM_POOL_MAX) 
128         return;
129 
130     memset((byte*)(*ptr), 0, block->size);
131     MemBlockDlist* top = g_pool_freelist[index];
132 
133     g_pool_freelist[index] = block;
134     if (top) {    
135         g_pool_freelist[index]->next = top;
136     }
137 
138     g_pool_freelist[index]->size = MEM_BLOCK_FREE;
139 }

 

重复造轮子系列--内存池(C语言)