19#include "common/lang/mutex.h"
20#include "common/lang/string.h"
21#include "common/lang/set.h"
22#include "common/lang/list.h"
23#include "common/lang/memory.h"
24#include "common/lang/sstream.h"
25#include "common/log/log.h"
26#include "common/os/os.h"
28#include <sanitizer/asan_interface.h>
32#define DEFAULT_ITEM_NUM_PER_POOL 128
33#define DEFAULT_POOL_NUM 1
35typedef bool (*match)(
void *item,
void *input_arg);
41 MemPool(
const char *tag) : name(tag)
45 pthread_mutexattr_t mutexatr;
46 pthread_mutexattr_init(&mutexatr);
47 pthread_mutexattr_settype(&mutexatr, PTHREAD_MUTEX_RECURSIVE);
49 MUTEX_INIT(&mutex, &mutexatr);
52 virtual ~MemPool() { MUTEX_DESTROY(&mutex); }
61 bool dynamic =
true,
int pool_num = DEFAULT_POOL_NUM,
int item_num_per_pool = DEFAULT_ITEM_NUM_PER_POOL) = 0;
83 virtual void free(T *item) = 0;
91 const string get_name()
const {
return name; }
92 bool is_dynamic()
const {
return dynamic; }
93 int get_size()
const {
return size; }
96 pthread_mutex_t mutex;
121 int init(
bool dynamic =
true,
int pool_num = DEFAULT_POOL_NUM,
int item_num_per_pool = DEFAULT_ITEM_NUM_PER_POOL);
151 int get_item_num_per_pool()
const {
return item_num_per_pool; }
155 MUTEX_LOCK(&this->mutex);
156 auto num = used.size();
157 MUTEX_UNLOCK(&this->mutex);
165 int item_num_per_pool;
168 inline void asan_poison(
void *addr,
size_t size) { ASAN_POISON_MEMORY_REGION(addr, size); }
169 inline void asan_unpoison(
void *addr,
size_t size) { ASAN_UNPOISON_MEMORY_REGION(addr, size); }
175 if (pools.empty() ==
false) {
176 LOG_WARN(
"Memory pool has been initialized, but still begin to be initialized, this->name:%s.", this->name.c_str());
180 if (pool_num <= 0 || item_num_per_pool <= 0) {
181 LOG_ERROR(
"Invalid arguments, pool_num:%d, item_num_per_pool:%d, this->name:%s.",
182 pool_num, item_num_per_pool, this->name.c_str());
186 this->item_num_per_pool = item_num_per_pool;
188 this->dynamic =
true;
189 for (
int i = 0; i < pool_num; i++) {
195 this->dynamic = dynamic;
197 LOG_INFO(
"Extend one pool, this->size:%d, item_num_per_pool:%d, this->name:%s.",
198 this->size, item_num_per_pool, this->name.c_str());
205 if (pools.empty() ==
true) {
206 LOG_WARN(
"Begin to do cleanup, but there is no memory pool, this->name:%s!", this->name.c_str());
209 MUTEX_LOCK(&this->mutex);
210 for (
auto &&i : frees) {
211 asan_unpoison(i,
sizeof(T));
217 for (
typename list<T *>::iterator iter = pools.begin(); iter != pools.end(); iter++) {
222 MUTEX_UNLOCK(&this->mutex);
223 LOG_INFO(
"Successfully do cleanup, this->name:%s.", this->name.c_str());
229 if (this->dynamic ==
false) {
230 LOG_ERROR(
"Disable dynamic extend memory pool, but begin to extend, this->name:%s", this->name.c_str());
234 MUTEX_LOCK(&this->mutex);
235 T *pool =
new T[item_num_per_pool];
236 if (pool ==
nullptr) {
237 MUTEX_UNLOCK(&this->mutex);
238 LOG_ERROR(
"Failed to extend memory pool, this->size:%d, item_num_per_pool:%d, this->name:%s.",
239 this->size, item_num_per_pool, this->name.c_str());
243 pools.push_back(pool);
244 this->size += item_num_per_pool;
245 for (
int i = 0; i < item_num_per_pool; i++) {
246 frees.push_back(pool + i);
247 asan_poison(pool + i,
sizeof(T));
249 MUTEX_UNLOCK(&this->mutex);
251 LOG_INFO(
"Extend one pool, this->size:%d, item_num_per_pool:%d, this->name:%s.",
252 this->size, item_num_per_pool, this->name.c_str());
259 MUTEX_LOCK(&this->mutex);
260 if (frees.empty() ==
true) {
261 if (this->dynamic ==
false) {
262 MUTEX_UNLOCK(&this->mutex);
267 MUTEX_UNLOCK(&this->mutex);
271 T *buffer = frees.front();
272 asan_unpoison(buffer,
sizeof(T));
277 MUTEX_UNLOCK(&this->mutex);
287 MUTEX_LOCK(&this->mutex);
289 size_t num = used.erase(buf);
291 MUTEX_UNLOCK(&this->mutex);
292 LOG_WARN(
"No entry of %p in %s.", buf, this->name.c_str());
296 asan_poison(buf,
sizeof(T));
297 frees.push_back(buf);
299 MUTEX_UNLOCK(&this->mutex);
308 ss <<
"name:" << this->name <<
","
309 <<
"dyanmic:" << this->dynamic <<
","
310 <<
"size:" << this->size <<
","
311 <<
"pool_size:" << this->pools.size() <<
","
312 <<
"used_size:" << this->used.size() <<
","
313 <<
"free_size:" << this->frees.size();
320 using item_unique_ptr = unique_ptr<void, function<void(
void *
const)>>;
327 pthread_mutexattr_t mutexatr;
328 pthread_mutexattr_init(&mutexatr);
329 pthread_mutexattr_settype(&mutexatr, PTHREAD_MUTEX_RECURSIVE);
331 MUTEX_INIT(&mutex, &mutexatr);
337 MUTEX_DESTROY(&mutex);
346 int init(
int item_size,
bool dynamic =
true,
int pool_num = DEFAULT_POOL_NUM,
347 int item_num_per_pool = DEFAULT_ITEM_NUM_PER_POOL);
364 item_unique_ptr alloc_unique_ptr();
370 void free(
void *item);
380 auto it = used.find(item);
381 MUTEX_UNLOCK(&mutex);
382 return it != used.end();
390 ss <<
"name:" << this->name <<
","
391 <<
"dyanmic:" << this->dynamic <<
","
392 <<
"size:" << this->size <<
","
393 <<
"pool_size:" << this->pools.size() <<
","
394 <<
"used_size:" << this->used.size() <<
","
395 <<
"free_size:" << this->frees.size();
399 const string get_name()
const {
return name; }
400 bool is_dynamic()
const {
return dynamic; }
401 int get_size()
const {
return size; }
402 int get_item_size()
const {
return item_size; }
403 int get_item_num_per_pool()
const {
return item_num_per_pool; }
408 auto num = used.size();
409 MUTEX_UNLOCK(&mutex);
414 pthread_mutex_t mutex;
419 int item_num_per_pool;
Definition: mem_pool.h:318
void cleanup()
Definition: mem_pool.cpp:47
void * alloc()
Definition: mem_pool.cpp:104
int init(int item_size, bool dynamic=true, int pool_num=DEFAULT_POOL_NUM, int item_num_per_pool=DEFAULT_ITEM_NUM_PER_POOL)
Definition: mem_pool.cpp:17
int extend()
Definition: mem_pool.cpp:70
bool is_used(void *item)
Definition: mem_pool.h:377
void free(void *item)
Definition: mem_pool.cpp:136
Definition: mem_pool.h:109
void cleanup()
Definition: mem_pool.h:203
int extend()
Definition: mem_pool.h:227
string to_string()
Definition: mem_pool.h:304
void free(T *item)
Definition: mem_pool.h:283
int init(bool dynamic=true, int pool_num=DEFAULT_POOL_NUM, int item_num_per_pool=DEFAULT_ITEM_NUM_PER_POOL)
Definition: mem_pool.h:173
T * alloc()
Definition: mem_pool.h:257
Definition: mem_pool.h:39
virtual void free(T *item)=0
virtual string to_string()=0
virtual int init(bool dynamic=true, int pool_num=DEFAULT_POOL_NUM, int item_num_per_pool=DEFAULT_ITEM_NUM_PER_POOL)=0