Chinaunix首页 | 论坛 | 博客
  • 博客访问: 955423
  • 博文数量: 116
  • 博客积分: 3923
  • 博客等级: 中校
  • 技术积分: 1337
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-23 01:22
文章分类

全部博文(116)

文章存档

2013年(1)

2012年(17)

2011年(69)

2009年(29)

分类: C/C++

2011-08-14 22:42:11

http://vincent.blog.chinaunix.net
这几天,业余的使用链表的方式实现了一个内存池管理器,原理很简单,就是通过一个链表把内存块链接起来,然后再把内存块以动态单元的方式划分出去,动态单元之间使用单链表方式组织,不过没详细的测试过,只是大概的测试一下, 大概实现原理如下图:

图:简单内存管理器,不支持多线程




实现代码如下:
file: mpool.h
========================================================================================
  1. /*
  2.  * author: vincent.cws2008@gmail.com
  3.  * history:
  4.  * initial @ 2011-08-14
  5.  */

  6. #ifndef _MPOOL_H_
  7. #define _MPOOL_H_

  8. #include "list.h"

  9. #define assert(x)

  10. typedef unsigned int size_t;

  11. #define NULL 0

  12. typedef unsigned int lnk_t;

  13. #define __align_mask(x,mask)    (((x)+(mask))&~(mask))

  14. #ifndef offsetof
  15. #define offsetof(type,member) ((size_t) &((type *)0)->member)
  16. #endif

  17. /* pointer alignment */
  18. #define ptr_align(p,mask) ((void*)(((char*)(p)-(char*)0+(mask))&~(mask)))

  19. /* get the pointer of the first unit */
  20. #define unit_first_ptr(base,mbh,mask)    ((char*)(base)+__align_mask(sizeof(mbh),mask))

  21. /* flag operator */
  22. #define is_free(p) (!(*(lnk_t*)(p)&1))
  23. #define flag_get(p) (*(lnk_t*)(p)&1)
  24. #define flag_set(p) (*(lnk_t*)(p)|=1)
  25. #define flag_clr(p) (*(lnk_t*)(p)&=(~1))

  26. /* offset operator */
  27. #define next_offset_get(p) (*(lnk_t*)(p)>>1)
  28. #define next_offset_set(p,v) (*(lnk_t*)(p)=(((v)<<1)+flag_get(p)))

  29. /* include the linking head */
  30. #define unit_size(p) ((*(lnk_t*)(p)>>1))
  31. /* exclude the linking head */
  32. #define unit_len(p,mask) ((*(lnk_t*)(p)>>1)-__align_mask(sizeof(lnk_t),(mask)))
  33. /* the button of the linking head, but NOTE */
  34. #define unit_ptr(p,mask) ((char*)(p)+__align_mask(sizeof(lnk_t),(mask)))
  35. /* setting the head of the linking unit */
  36. #define unit_set(p,flag,offset) (*(lnk_t*)(p)=(((flag)&1)|((offset)<<1)))
  37. /* point to the next unit, top of the next linking head */
  38. #define next_ptr(p) ((char*)(p)+next_offset_get(p))
  39. /* pointer of plus (size) bytes, but NOTE */
  40. #define ptr_add(p,size,mask) (ptr_align(unit_ptr(p,mask)+(size),(mask)))

  41. /*
  42.  * head: point to the top of first unit.
  43.  * limit: point to the button of last unit.
  44.  */
  45. #define mblocks_for_each(pos, pre, head, limit) \
  46.     for (pre=pos=(char*)(head); pos<limit; \
  47.         pre=pos, pos=next_ptr(pos))

  48. #define FIT_SIZE    0
  49. #define FIT_FIRST 1


  50. typedef struct mblock_s{
  51.     struct list_head list;
  52.     size_t size_block;
  53. }MBLOCK_T;


  54. typedef struct mpool_s{
  55.     struct list_head head;
  56.     int align_mask;
  57.     int tactics;
  58.     void* (*malloc)(struct mpool_s* mpool_p, size_t size);
  59.     void (*free)(struct mpool_s* mpool_p, void *obj_p);
  60.     char* (*grow)(struct mpool_s* mpool_p, char *new_p, size_t size);
  61.     void (*print)(struct mpool_s* mpool_p);
  62. }MPOOL_T;

  63. void mpool_init(MPOOL_T* mpool_p, char *mem_p, size_t size,
  64.                 int tactics, unsigned int alignment);

  65. #define mpool_malloc(mp,size) \
  66.         ((mp).malloc(&(mp),size))

  67. #define mpool_free(mp,fp) \
  68.         ((mp).free(&(mp),(fp)))

  69. #define mpool_grow(mp,np,size) \
  70.         ((mp).grow(&(mp),(np),(size)))

  71. #define mpool_print(mp) \
  72.      ((mp).print(&(mp)))

  73. #endif

file: mpool.c
========================================================================================
  1. /*
  2.  * author: vincent.cws2008@gmail.com
  3.  * history:
  4.  * initial @ 2011-08-14
  5.  */

  6. #include "mpool.h"

  7. #ifndef __cplusplus
  8. #define max(a,b) (((a) > (b)) ? (a) : (b))
  9. #define min(a,b) (((a) < (b)) ? (a) : (b))
  10. #endif

  11. union fooround{
  12.     long double d;
  13.     void *p;
  14. };

  15. struct fooalign{
  16.     char c;
  17.     union fooround u;
  18. };

  19. #define    DFT_ALIGN (offsetof(struct fooalign, u))

  20. static void *mblock_malloc__(struct mpool_s* mpool_p, MBLOCK_T* mblock_p, size_t size)
  21. {
  22.     char *limit_p, *head_p, *pos_p, *prev_p, *end_p, *next_p, *mark_p=0;
  23.     unsigned int size_mark=(unsigned int)(-1);
  24.     int size_fit, mask;

  25.     assert(mblock_p && mpool_p);
  26.     mask = mpool_p->align_mask;
  27.     head_p = unit_first_ptr(mblock_p, MBLOCK_T, mask);
  28.     limit_p = (char*)mblock_p+mblock_p->size_block;
  29.     
  30.     mblocks_for_each(pos_p, prev_p, head_p, limit_p)
  31.     {
  32.         if (is_free(pos_p) && (size_fit=unit_len(pos_p,mask)-size)>=0){
  33.             if (mpool_p->tactics==FIT_FIRST || size_fit==0/*matched*/){
  34.                 end_p = ptr_add(pos_p,size,mask);
  35.                 next_p = next_ptr(pos_p);
  36.                 if (end_p < next_p){
  37.                     unit_set(pos_p, 0, end_p-pos_p);
  38.                     unit_set(end_p, 0, next_p-end_p);
  39.                 }                
  40.                 flag_set(pos_p);
  41.                 return unit_ptr(pos_p,mask);
  42.             }else{
  43.                 if (size_fit<size_mark){ /* pick up the fittest size */
  44.                     size_mark=size_fit;
  45.                     mark_p=pos_p;
  46.                 }
  47.             }
  48.         }
  49.     }
  50.     if (mark_p){ /* the fittest size marked */
  51.         end_p = ptr_add(mark_p,size,mask);
  52.         next_p = next_ptr(mark_p);
  53.         if (end_p < next_p){
  54.             unit_set(mark_p, 0, end_p-mark_p);
  55.             unit_set(end_p, 0, next_p-end_p);
  56.         }                
  57.         flag_set(mark_p);
  58.         return unit_ptr(mark_p,mask);
  59.     }
  60.     return (void*)0;
  61. }

  62. static void *mpool_malloc__(struct mpool_s* mpool_p, size_t size)
  63. {
  64.     struct list_head *list_p;
  65.     MBLOCK_T *mblock_p;
  66.     void *new_p;
  67.     assert(mpool_p);
  68.     list_for_each(list_p, &mpool_p->head){
  69.         mblock_p = list_entry(list_p, MBLOCK_T, list);
  70.         if(new_p=mblock_malloc__(mpool_p, mblock_p, size))
  71.             return new_p;
  72.     }
  73.     return 0;
  74. }

  75. static void mblock_free__(struct mpool_s* mpool_p, MBLOCK_T* mblock_p, void* free_p)
  76. {
  77.     char *limit_p, *head_p, *pos_p, *prev_p, *next_p;
  78.     unsigned int mask, size_fit, size_mark=(unsigned int)(-1);
  79.     
  80.     assert(mblock_p && free_p);        

  81.     mask = mpool_p->align_mask;

  82.     head_p = unit_first_ptr(mblock_p, MBLOCK_T, mask);
  83.     limit_p = (char*)mblock_p+mblock_p->size_block;
  84.     
  85.     mblocks_for_each(pos_p, prev_p, head_p, limit_p)
  86.     {
  87.         if (unit_ptr(pos_p,mask)==(char*)free_p) /* matched */
  88.         {
  89.             next_p = next_ptr(pos_p);
  90.             /* look at up to the previous unit */
  91.             if (prev_p != pos_p && is_free(prev_p))
  92.             {
  93.                 unit_set(prev_p, 0, next_ptr(pos_p)-prev_p); /* merge up */
  94.                 pos_p = prev_p;
  95.             }
  96.             flag_clr(pos_p);
  97.             /* look at down to the next unit */
  98.             if (next_p<limit_p && is_free(next_p))
  99.             {
  100.                 unit_set(pos_p, 0, next_ptr(next_p)-pos_p); /* merge down */
  101.             }
  102.             break;
  103.         }
  104.     }
  105. }

  106. static void mpool_free__(struct mpool_s* mpool_p, void *obj_p)
  107. {
  108.     struct list_head *list_p;
  109.     MBLOCK_T *mblock_p;
  110.     int offset;
  111.     void *new_p;
  112.     assert(obj_p);
  113.     list_for_each(list_p, &mpool_p->head){
  114.         mblock_p = list_entry(list_p, MBLOCK_T, list);
  115.         if (mblock_p){
  116.             offset = (char*)obj_p-(char*)mblock_p;
  117.             if (offset>0 && offset < mblock_p->size_block)
  118.                 return mblock_free__(mpool_p, mblock_p, obj_p);
  119.         }
  120.     }    
  121. }

  122. static char* mblock_init__(struct mpool_s* mpool_p, char *new_p, size_t size)
  123. {
  124.     MBLOCK_T *mblock_p;
  125.     char *base_p, *limit_p, *fp;
  126.     
  127.     assert(mpool_p && new_p);

  128.     if (size < sizeof(MBLOCK_T)+max(sizeof(lnk_t),DFT_ALIGN))
  129.         return (char*)0;

  130.     base_p = ptr_align(new_p, mpool_p->align_mask);
  131.     limit_p = ptr_align(new_p+size, mpool_p->align_mask);

  132.     mblock_p = (MBLOCK_T*)base_p;
  133.     mblock_p->size_block = limit_p-base_p;

  134.     fp = unit_first_ptr(base_p, MBLOCK_T, mpool_p->align_mask);

  135.     unit_set(fp, 0, limit_p-fp);
  136.     return base_p;
  137. }

  138. static int mpool_grow__(struct mpool_s* mpool_p, char *new_p, size_t size)
  139. {
  140.     char *bp;
  141.     assert(mpool_p && new_p);
  142.     bp = mblock_init__(mpool_p, new_p, size);
  143.     if (!bp) return -1;
  144.     list_add(&((MBLOCK_T*)bp)->list, &mpool_p->head);
  145.     return 0;
  146. }

  147. void mpool_print__(struct mpool_s* mpool_p)
  148. {    
  149.     struct list_head *list_p;
  150.     MBLOCK_T *mblock_p;
  151.     char *limit_p, *head_p, *pos_p, *prev_p;
  152.     int mask, num_block=0;

  153.     assert(mpool_p);    
  154.     mask = mpool_p->align_mask;
  155.     
  156.     list_for_each(list_p, &mpool_p->head){
  157.         mblock_p = list_entry(list_p, MBLOCK_T, list);
  158.         if (mblock_p){
  159.             printf("block(%d): memory=%p, size=%d ===\n",
  160.                 num_block++, mblock_p, mblock_p->size_block);
  161.             head_p = unit_first_ptr(mblock_p, MBLOCK_T, mask);
  162.             limit_p = (char*)mblock_p+mblock_p->size_block;
  163.             mblocks_for_each(pos_p, prev_p, head_p, limit_p)
  164.             {
  165.                 printf("[addr=%p flag=%d offset=%d room=%d]-->\n",
  166.                         unit_ptr(pos_p, mask),
  167.                         flag_get(pos_p),
  168.                         unit_size(pos_p),
  169.                         unit_len(pos_p, mask));
  170.             }
  171.         }
  172.     }        
  173. }

  174. extern void mpool_init(MPOOL_T* mpool_p, char *mem_p, size_t size,
  175.                      int tactics, unsigned int alignment)
  176. {
  177.     assert(mpool_p && mem_p);
  178.     
  179.     INIT_LIST_HEAD(&mpool_p->head);

  180.     mpool_p->align_mask=
  181.         alignment?(alignment-1):(DFT_ALIGN-1);
  182.     
  183.     if (tactics==FIT_FIRST)
  184.         mpool_p->tactics = tactics;
  185.     else
  186.         mpool_p->tactics = FIT_SIZE;

  187.     *(mpool_p->malloc) = mpool_malloc__;
  188.     *(mpool_p->free) = mpool_free__;
  189.     *(mpool_p->grow) = mpool_grow__;
  190.     *(mpool_p->print) = mpool_print__;
  191.     mpool_p->grow(mpool_p, mem_p, size);
  192. }

file: main.c
========================================================================================
  1. /*
  2.  * author: vincent.cws2008@gmail.com
  3.  * history:
  4.  * initial @ 2011-08-14
  5.  */

  6. #include "mpool.h"

  7. #include <stdlib.h>
  8. #include <time.h>

  9. #define PROMPT_FAILED "mpool malloc failed!\n"

  10. #define MAX_HANDLES 20

  11. void random_test(MPOOL_T *mpool_p, void *arr_malloc[], size_t count, int times)
  12. {
  13.     int index, rand_bytes, i;
  14.     assert(mpool_p && arr_malloc)
  15.     memset(arr_malloc, 0, count*sizeof(void*));
  16.     srand ((unsigned)time(NULL));
  17.     i=0;
  18.     while (times--)
  19.     {
  20.         printf("---------------------------------------------------\n");
  21.         index=rand()%count;
  22.         rand_bytes = rand()%150;
  23.         printf("[%d]test: index=%d rand_bytes=%d\n", i++, index, rand_bytes);
  24.         if (arr_malloc[index])
  25.             mpool_free(*mpool_p, arr_malloc[index]);
  26.         arr_malloc[index]=mpool_malloc(*mpool_p, rand_bytes);
  27.         if (!arr_malloc[index])
  28.             printf("%s\n", PROMPT_FAILED);
  29.         else
  30.             memset(arr_malloc[index], 5,rand_bytes);
  31.         mpool_print(*mpool_p);
  32.     }
  33.     i=0;
  34.     while(i < count)
  35.     {
  36.         mpool_free(*mpool_p, arr_malloc[i++]);
  37.     }
  38.     mpool_print(*mpool_p);
  39. }

  40. void lining_test(MPOOL_T *mpool_p, void *arr_malloc[], size_t count)
  41. {
  42.     int index, bytes, i, max_bytes;
  43.     assert(mpool_p && arr_malloc);    
  44.     memset(arr_malloc, 0, count*sizeof(void*));
  45.     index = 0;
  46.     bytes = 0;
  47.     i = 0;
  48.     max_bytes = 10;
  49.     while(bytes < max_bytes)
  50.     {
  51.         printf("---------------------------------------------------\n");
  52.         index = i % count;
  53.         printf("[%d]test: index=%d bytes=%d\n", i++, index, bytes);
  54.         if (arr_malloc[index])
  55.             mpool_free(*mpool_p, arr_malloc[index]);
  56.         arr_malloc[index]=mpool_malloc(*mpool_p, bytes);
  57.         if (!arr_malloc[index])
  58.             printf("%s\n", PROMPT_FAILED);
  59.         else
  60.             memset(arr_malloc[index], 5,bytes);
  61.         mpool_print(*mpool_p);
  62.         bytes++;
  63.     }
  64.     i=0;
  65.     while(i < count)
  66.     {
  67.         mpool_free(*mpool_p, arr_malloc[i++]);
  68.     }
  69.     mpool_print(*mpool_p);
  70. }

  71. void fixing_test(MPOOL_T *mpool_p, void *arr_malloc[], size_t count)
  72. {
  73.     int index, i, fix_bytes;
  74.     assert(mpool_p && arr_malloc);    
  75.     memset(arr_malloc, 0, count*sizeof(void*));
  76.     index = 0;
  77.     i = 0;
  78.     fix_bytes = 33;
  79.     while(i++ < 50)
  80.     {
  81.         printf("---------------------------------------------------\n");
  82.         index = i % count;
  83.         printf("[%d]test: index=%d bytes=%d\n", i++, index, fix_bytes);
  84.         if (arr_malloc[index])
  85.             mpool_free(*mpool_p, arr_malloc[index]);
  86.         arr_malloc[index]=mpool_malloc(*mpool_p, fix_bytes);
  87.         if (!arr_malloc[index])
  88.             printf("%s\n", PROMPT_FAILED);
  89.         else
  90.             memset(arr_malloc[index], 5, fix_bytes);
  91.         mpool_print(*mpool_p);
  92.     }
  93.     i=0;
  94.     while(i < count)
  95.     {
  96.         mpool_free(*mpool_p, arr_malloc[i++]);
  97.     }
  98.     mpool_print(*mpool_p);
  99. }


  100. void main()
  101. {
  102.     MPOOL_T mpool;
  103.     int i=20;
  104.     char *new_p1, *new_p2, *new_p3;
  105.     void* arr_malloc[MAX_HANDLES];
  106.     char mem_1[500];
  107.     char mem_2[300];
  108.     mpool_init(&mpool, mem_1, sizeof(mem_1), 0, 4);
  109.     new_p1 = mpool_malloc(mpool, 10);
  110.     mpool_print(mpool);
  111.     if (!new_p1) printf("%s", PROMPT_FAILED);

  112.     mpool_grow(mpool,mem_2, sizeof(mem_2));
  113.     mpool_print(mpool);

  114.     new_p2 = mpool_malloc(mpool, 32);
  115.     if (!new_p2) printf("%s", PROMPT_FAILED);
  116.     mpool_free(mpool, new_p2);
  117.     mpool_print(mpool);
  118.     new_p3 = mpool_malloc(mpool, 12);
  119.     mpool_print(mpool);
  120.     if (!new_p3) printf("%s", PROMPT_FAILED);
  121.     mpool_free(mpool, new_p1);
  122.     mpool_print(mpool);
  123.     mpool_free(mpool, new_p2);
  124.     mpool_print(mpool);
  125.     mpool_free(mpool, new_p3);
  126.     mpool_print(mpool);
  127.     random_test(&mpool, arr_malloc, MAX_HANDLES, 10);
  128.     lining_test(&mpool, arr_malloc, MAX_HANDLES);
  129.     fixing_test(&mpool, arr_malloc, MAX_HANDLES);
  130. }

附件:  mpool.rar  
========================================================================================

阅读(2775) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~