design_pattern_for_c  V 1.00
memorypool.c
Go to the documentation of this file.
1 #include <elf.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <pthread.h>
6 #include "memorypool.h"
7 
9 /* @{ */
11 static int get_far_right_bit_index(uint64_t data) {
12  int index=0;
13  for(index=0;index< 64;index++) {
14  if((data)&(0x01<<index))break;
15  }
16  return index;
17 }
18 
20 static int get_bit_digit_index_over_size(uint64_t size) {
21  uint64_t current_size=size;
22  int digit = 0, tmp_digit=0;
23  while(current_size != 0) {
24  tmp_digit = get_far_right_bit_index(current_size);
25  digit += tmp_digit + 1;
26  current_size = current_size >> tmp_digit + 1;
27  }
28 
29  if(digit == get_far_right_bit_index(size) + 1) digit--;
30  return digit;
31 }
32 
33 /* @} */
34 
38 typedef struct maloc_data_t {
39  struct maloc_data_t * next;
40  struct maloc_data_t * prev;
41  int used;
42  void * mem;
44 
45 typedef struct memorypool_t {
48  size_t max_size;
49  size_t max_cnt;
50  size_t cur_cnt;
51  size_t slide_bit;
52  uint8_t * buf;
53  uint8_t * user_buf;
54  pthread_mutex_t *lock;
55 } memorypool_t;
56 
57 static inline void mpool_list_push(MemoryPool this, malloc_data_t * data);
58 static inline void mpool_list_pull(MemoryPool this, malloc_data_t * data);
59 static inline void mpool_list_head(MemoryPool this, malloc_data_t * data);
60 static inline void * mpool_get_memory(MemoryPool this);
61 static inline void * mpool_get_next_memory(MemoryPool this, void * ptr);
62 static inline void mpool_unuse_memory(MemoryPool this, void *ptr);
63 static inline uint64_t mpool_get_buffer_place(MemoryPool this, uint8_t * buffer_list, void * ptr);
64 static inline int mpool_is_not_ptr_in_buf(MemoryPool this, void * ptr);
65 
66 /*define for pthread_cleanup_push*/
67 static inline void pthread_mutex_unlock_(void *arg) {
68  if(arg) pthread_mutex_unlock((pthread_mutex_t *)arg);
69 }
70 
71 static inline void pthread_mutex_lock_(MemoryPool this) {
72  if(this->lock) pthread_mutex_lock(this->lock);
73 }
74 #define MPOOL_LOCK(this) \
75  pthread_mutex_lock_(this);\
76  pthread_cleanup_push(pthread_mutex_unlock_, this->lock);
77 #define MPOOL_UNLOCK pthread_cleanup_pop(1);
78 
80 /* @{ */
81 
82 static inline void mpool_list_push(MemoryPool this, malloc_data_t * data) {
83  /* add to tail */
84  data->prev = this->tail;
85  data->next = NULL;
86  //slide tail
87  if(this->tail) this->tail->next = data;
88 
89  this->tail = data;
90  /* if head is null, set to head */
91  if(!this->head) this->head = data;
92 }
93 
94 static inline void mpool_list_pull(MemoryPool this, malloc_data_t * data) {
95  if(!data) return;
96 
97  /* update content */
98  if(this->head == data) this->head = data->next;
99  /* else case, account is not head. So there is a prev. */
100  else data->prev->next = data->next;
101 
102  if(this->tail == data) this->tail = data->prev;
103  /* else case, account is not tail. So there is a next. */
104  else data->next->prev = data->prev;
105 }
106 
107 static inline void mpool_list_head(MemoryPool this, malloc_data_t * data) {
108 
109  //there is a prev.
110  data->next = this->head;
111  data->prev = NULL;
112  this->head->prev = data;
113  this->head = data;
114 }
115 
116 static inline void * mpool_get_memory(MemoryPool this) {
117  malloc_data_t * memory=NULL;
118  if(!this->head->used) {
119  memory = this->head;
120  mpool_list_pull(this, memory);
121  memory->used=1;
122  mpool_list_push(this, memory);
123  return memory->mem;
124  } else {
125  printf("nused\n");
126  return NULL;
127  }
128 }
129 
130 static inline void * mpool_get_next_memory(MemoryPool this, void * ptr) {
131  malloc_data_t * memory=NULL;
132 
133  /* get memory place */
134  if(!ptr) {
135  memory=this->tail;
136  } else {
137  uint64_t place = mpool_get_buffer_place(this, this->user_buf, ptr);
138  memory= ((malloc_data_t *)(this->buf) + place);
139  memory = memory->prev;
140  }
141 
142  /* check used flag */
143  if(memory && memory->used) return memory->mem;
144  else return NULL;
145 }
146 
147 static inline void mpool_unuse_memory(MemoryPool this, void *ptr) {
148  //get plage of memory, and get list from this place
149  uint64_t place = mpool_get_buffer_place(this, this->user_buf, ptr);
150  malloc_data_t * memory = (malloc_data_t *)(this->buf + (sizeof(malloc_data_t) * place));
151 
152  mpool_list_pull(this, memory);
153  memory->used=0;
154  mpool_list_head(this, memory);
155 }
156 
157 static inline uint64_t mpool_get_buffer_place(MemoryPool this, uint8_t * buffer_list, void * ptr) {
158  //this place is XXX00000 bit place, slide by using this->slide_bit
159  return ((uint64_t)ptr - (uint64_t)buffer_list) >> this->slide_bit;
160 }
161 
162 static inline int mpool_is_not_ptr_in_buf(MemoryPool this, void * ptr) {
163 
164  return (uint64_t)ptr < (uint64_t)this->user_buf || (uint64_t)(this->user_buf) + this->max_cnt * this->max_size < (uint64_t)ptr;
165 }
166 /* @} */
167 
169 /* @{ */
170 MemoryPool mpool_create(size_t max_size, size_t max_cnt, int is_multithread, void (*constructor)(void *this, void *parameter), void * constructor_parameter) {
171  //create magic hash table first
172  int ret=-1;
173  size_t slide_bit;
174 
175  MemoryPool instance;
176  size_t mutex_size=0;
177  if(is_multithread) mutex_size = sizeof(pthread_mutex_t);
178 
179  //get slide bit to use hash
180  slide_bit = get_bit_digit_index_over_size(max_size);
181 
182  //Update max size
183  max_size = 0x01 << slide_bit;
184 
185  instance = malloc(sizeof(*instance) + mutex_size + max_cnt * (sizeof(malloc_data_t) + max_size));
186  if(!instance) return NULL;
187  memset(instance, 0, sizeof(*instance) + mutex_size + max_cnt * (sizeof(malloc_data_t) + max_size));
188 
189  instance->slide_bit = slide_bit;
190  instance->max_size = max_size;
191  instance->max_cnt = max_cnt;
192  void *correut = (instance + 1);
193  //set lock
194  if(is_multithread) {
195  instance->lock=(pthread_mutex_t *) (correut);
196  correut = instance->lock + 1;
197  pthread_mutex_init(instance->lock, NULL);
198  } else {
199  instance->lock = NULL;
200  }
201 
202  //keep pointer line, head is list of malloc_data_t
203  instance->buf = (uint8_t *)(correut);
204  correut = instance->buf + max_cnt * sizeof(malloc_data_t);
205 
206  //set user pointer list
207  instance->user_buf = correut;
208 
209  //set user pointer list
210  malloc_data_t * memory;
211  int i=0;
212  for(i=0;i<max_cnt;i++) {
213  memory = (malloc_data_t *)(instance->buf + (sizeof(malloc_data_t) * i));
214  memory->mem = correut;
215  correut = memory->mem + max_size;
216  if(constructor) constructor(memory->mem, constructor_parameter);
217  mpool_list_push(instance, memory);
218  }
219 
220  return instance;
221 }
222 
223 void mpool_delete(MemoryPool this, void (*destructor)(void *)) {
224 MPOOL_LOCK(this)
225  if(destructor) {
226  malloc_data_t * memory = this->head;
227  while(memory) {
228  destructor(memory->mem);
229  memory = memory->next;
230  }
231  }
233  free(this);
234 }
235 
236 void * mpool_get(MemoryPool this) {
237  void * mem=NULL;
238 MPOOL_LOCK(this)
239  mem = mpool_get_memory(this);
240  if(mem) this->cur_cnt++;
242  return mem;
243 }
244 
245 void * mpool_get_next_usedmem(MemoryPool this, void * ptr) {
246  if(ptr && mpool_is_not_ptr_in_buf(this, ptr)) {
247  return NULL;
248  }
249 
250  void * mem=NULL;
251 MPOOL_LOCK(this)
252  mem = mpool_get_next_memory(this, ptr);
254  return mem;
255 }
256 
258  if(!this) return 0;
259  size_t retval=0;
260 MPOOL_LOCK(this)
261  retval = this->cur_cnt;
263  return retval;
264 }
265 
266 void mpool_release(MemoryPool this, void * ptr) {
267  if(!ptr) return;
268 
269  if(mpool_is_not_ptr_in_buf(this, ptr)) {
270  //no info
271  return;
272  }
273 MPOOL_LOCK(this)
274  mpool_unuse_memory(this, ptr);
275  this->cur_cnt--;
277 }
278 
279 void mpool_show(MemoryPool this) {
280 MPOOL_LOCK(this)
281  malloc_data_t *memory=this->head;
282  while(memory) {
283  fprintf(stderr, "used:%d\n", memory->used);
284  memory = memory->next;
285  }
287 }
288 /* @} */
static uint64_t mpool_get_buffer_place(MemoryPool this, uint8_t *buffer_list, void *ptr)
Definition: memorypool.c:157
uint8_t * buf
list of buffer for user + list of malloc_data_t
Definition: memorypool.c:52
size_t cur_cnt
Definition: memorypool.c:50
void mpool_release(MemoryPool this, void *ptr)
release memory to pool
Definition: memorypool.c:266
malloc_data_t * head
Definition: memorypool.c:46
void * mpool_get(MemoryPool this)
get memory from pool
Definition: memorypool.c:236
struct maloc_data_t * prev
Definition: memorypool.c:40
static void mpool_list_pull(MemoryPool this, malloc_data_t *data)
Definition: memorypool.c:94
static void mpool_list_push(MemoryPool this, malloc_data_t *data)
Definition: memorypool.c:82
void * mpool_get_next_usedmem(MemoryPool this, void *ptr)
get used memory
Definition: memorypool.c:245
void(* free)(EventInstance this)
Definition: event_thread.c:39
size_t max_size
Definition: memorypool.c:48
struct maloc_data_t malloc_data_t
size_t slide_bit
keep slide bit size related to max_size, to search buffer fast
Definition: memorypool.c:51
static int get_bit_digit_index_over_size(uint64_t size)
get minimum of x, which 2^x > input_value
Definition: memorypool.c:20
#define MPOOL_LOCK(this)
Definition: memorypool.c:74
struct memorypool_t memorypool_t
void mpool_show(MemoryPool this)
Definition: memorypool.c:279
static int mpool_is_not_ptr_in_buf(MemoryPool this, void *ptr)
Definition: memorypool.c:162
struct maloc_data_t * next
Definition: memorypool.c:39
static void mpool_unuse_memory(MemoryPool this, void *ptr)
Definition: memorypool.c:147
static void pthread_mutex_lock_(MemoryPool this)
Definition: memorypool.c:71
malloc_data_t * tail
Definition: memorypool.c:47
static void * mpool_get_next_memory(MemoryPool this, void *ptr)
Definition: memorypool.c:130
void * mem
Definition: memorypool.c:42
uint8_t * user_buf
list of buffer for user
Definition: memorypool.c:53
#define MPOOL_UNLOCK
Definition: memorypool.c:77
static void mpool_list_head(MemoryPool this, malloc_data_t *data)
Definition: memorypool.c:107
pthread_mutex_t * lock
mutex
Definition: memorypool.c:54
static void * mpool_get_memory(MemoryPool this)
Definition: memorypool.c:116
size_t mpool_get_usedcnt(MemoryPool this)
get used cnt
Definition: memorypool.c:257
static void pthread_mutex_unlock_(void *arg)
Definition: memorypool.c:67
static int get_far_right_bit_index(uint64_t data)
get right bit index
Definition: memorypool.c:11
size_t max_cnt
Definition: memorypool.c:49
void mpool_delete(MemoryPool this, void(*destructor)(void *))
free MemoryPool class
Definition: memorypool.c:223
MemoryPool class member definition, detail is defined in C file.
Definition: memorypool.c:45
This is API for memory pool.
MemoryPool mpool_create(size_t max_size, size_t max_cnt, int is_multithread, void(*constructor)(void *this, void *parameter), void *constructor_parameter)
Definition: memorypool.c:170