acl  3.5.3.0
dbuf_pool.hpp
浏览该文件的文档.
1 #pragma once
2 #include "../acl_cpp_define.hpp"
3 #include "noncopyable.hpp"
4 #include <vector>
5 
6 struct ACL_DBUF_POOL;
7 
8 namespace acl
9 {
10 
11 /**
12  * 会话类的内存链管理类,该类仅提供内存分配函数,在整个类对象被析构时该内存链
13  * 会被一次性地释放,该类适合于需要频繁分配一些大小不等的小内存的应用;
14  * 该类实际上是封装了 lib_acl 中的 ACL_DBUF_POOL 结构及方法
15  */
16 
17 class ACL_CPP_API dbuf_pool // : public noncopyable
18 {
19 public:
20  /**
21  * 该类对象必须动态创建
22  */
23  dbuf_pool();
24 
25  /**
26  * 该类对象必须要动态创建,所以隐藏了析构函数,使用者需要调用 destroy
27  * 函数来销毁动态对象
28  */
29  void destroy();
30 
31  /**
32  * 重载 new/delete 操作符,使 dbuf_pool 对象本身也创建在内存池上,
33  * 从而减少了 malloc/free 的次数
34  * @param size {size_t} 由编译传入的 dbuf_pool 对象的长度大小
35  * @param nblock {size_t} 内部采用的内存块(4096)的倍数
36  */
37  void *operator new(size_t size, size_t nblock = 2);
38 
39 #if defined(_WIN32) || defined(_WIN64)
40  void operator delete(void* ptr, size_t);
41 #endif
42  void operator delete(void* ptr);
43 
44  /**
45  * 重置内存池的状态以便于重复使用该内存池对象
46  * @param reserve {size_t} 若该值 > 0,则需要指定额外保留的内存大小,
47  * 该大小必须小于等于已经在该内存池对象分配的大小
48  * @return {bool} 如果输入参数非法,则返回 false
49  */
50  bool dbuf_reset(size_t reserve = 0);
51 
52  /**
53  * 分配指定长度的内存
54  * @param len {size_t} 需要分配的内存长度,当内存比较小时(小于构造函数
55  * 中的 block_size)时,所分配的内存是在 dbuf_pool 所管理的内存链上,
56  * 当内存较大时会直接使用 malloc 进行分配
57  * @return {void*} 新分配的内存地址
58  */
59  void* dbuf_alloc(size_t len);
60 
61  /**
62  * 分配指定长度的内存并将内存区域清零
63  * @param len {size_t} 需要分配的内存长度
64  * @return {void*} 新分配的内存地址
65  */
66  void* dbuf_calloc(size_t len);
67 
68  /**
69  * 根据输入的字符串动态创建新的内存并将字符串进行复制,类似于 strdup
70  * @param s {const char*} 源字符串
71  * @return {char*} 新复制的字符串地址
72  */
73  char* dbuf_strdup(const char* s);
74 
75  /**
76  * 根据输入的字符串动态创建新的内存并将字符串进行复制,类似于 strdup
77  * @param s {const char*} 源字符串
78  * @param len {size_t} 限制所复制字符串的最大长度
79  * @return {char*} 新复制的字符串地址
80  */
81  char* dbuf_strndup(const char* s, size_t len);
82 
83  /**
84  * 根据输入的内存数据动态创建内存并将数据进行复制
85  * @param addr {const void*} 源数据内存地址
86  * @param len {size_t} 源数据长度
87  * @return {void*} 新复制的数据地址
88  */
89  void* dbuf_memdup(const void* addr, size_t len);
90 
91  /**
92  * 归还由内存池分配的内存
93  * @param addr {const void*} 由内存池分配的内存地址
94  * @return {bool} 如果该内存地址非内存池分配或释放多次,则返回 false
95  */
96  bool dbuf_free(const void* addr);
97 
98  /**
99  * 保留由内存池分配的某段地址,以免当调用 dbuf_reset 时被提前释放掉
100  * @param addr {const void*} 由内存池分配的内存地址
101  * @return {bool} 如果该内存地址非内存池分配,则返回 false
102  */
103  bool dbuf_keep(const void* addr);
104 
105  /**
106  * 取消保留由内存池分配的某段地址,以便于调用 dbuf_reset 时被释放掉
107  * @param addr {const void*} 由内存池分配的内存地址
108  * @return {bool} 如果该内存地址非内存池分配,则返回 false
109  */
110  bool dbuf_unkeep(const void* addr);
111 
112  /**
113  * 获得内部 ACL_DBUF_POOL 对象,以便于操作 C 接口的内存池对象
114  * @return {ACL_DBUF_POOL*}
115  */
117  {
118  return pool_;
119  }
120 
121 private:
122  ACL_DBUF_POOL* pool_;
123  size_t mysize_;
124 
125 public:
126  ~dbuf_pool();
127 };
128 
129 /**
130  * sample:
131  * void test()
132  * {
133  * acl::dbuf_pool* dbuf = new acl::dbuf_pool;
134  * for (int i = 0; i < 1000; i++)
135  * {
136  * char* ptr = dbuf->dbuf_strdup("hello world!");
137  * printf("%s\r\n", p);
138  * }
139  * dbuf->destroy();
140  *
141  * // 创建 dbuf 对象时,指定了内部分配内存块的位数
142  * dbuf = new(8) acl::dbuf_pool;
143  * for (int i = 0; i < 1000; i++)
144  * {
145  * ptr = dbuf->dbuf_strdup("hello world!");
146  * printf("%s\r\n", p);
147  * }
148  *
149  * // 销毁 dbuf 对象
150  * dbuf->destroy();
151  * }
152  *
153  */
154 //////////////////////////////////////////////////////////////////////////////
155 
156 class dbuf_guard;
157 
158 /**
159  * 在会话内存池对象上分配的对象基础类
160  */
161 class ACL_CPP_API dbuf_obj //: public noncopyable
162 {
163 public:
164  /**
165  * 构造函数
166  * @param guard {dbuf_guard*} 该参数非空时,则本类的子类对象会被
167  * dbuf_guard 类对象自动管理,统一销毁;如果该参数为空,则应用应
168  * 调用 dbuf_guard::push_back 方法将子类对象纳入统一管理
169  */
170  dbuf_obj(dbuf_guard* guard = NULL);
171 
172  virtual ~dbuf_obj() {}
173 
174  /**
175  * 获得该对象在 dbuf_guard 中的数组中的下标位置
176  * @return {int} 返回该对象在 dbuf_guard 中的数组中的下标位置,当该
177  * 对象没有被 dbuf_guard 保存时,则返回 -1,此时有可能会造成内存泄露
178  */
179  int pos() const
180  {
181  return pos_;
182  }
183 
184  /**
185  * 返回构造函数中 dbuf_guard 对象
186  * @return {dbuf_guard*}
187  */
189  {
190  return guard_;
191  }
192 
193 private:
194  friend class dbuf_guard;
195 
196  // 记录本对象所属的 dbuf_guard 对象
197  dbuf_guard* guard_;
198 
199  // 该变量便于 dbuf_guard 对象使用,以增加安全性
200  int nrefer_;
201 
202  // 该对象在 dbuf_guard 对象中记录的数组的位置
203  int pos_;
204 };
205 
206 /**
207  * 会话内存池管理器,由该类对象管理 dbuf_pool 对象及在其上分配的对象,当该类
208  * 对象销毁时,dbuf_pool 对象及在上面均被释放。
209  */
210 class ACL_CPP_API dbuf_guard // : public noncopyable
211 {
212 public:
213  /**
214  * 构造函数
215  * @param dbuf {dbuf_pool*} 当该内存池对象非空时,dbuf 将由 dbuf_guard
216  * 接管,如果为空,则本构造函数内部将会自动创建一个 dbuf_pool 对象
217  * @param capacity {size_t} 内部创建的 objs_ 数组的初始长度
218  */
219  dbuf_guard(dbuf_pool* dbuf, size_t capacity = 500);
220 
221  /**
222  * 构造函数
223  * @param nblock {size_t} 本类对象内部创建 dbuf_pool 对象时,本参数
224  * 指定了内存块(4096)的倍数
225  * @param capacity {size_t} 内部创建的 objs_ 数组的初始长度
226  */
227  dbuf_guard(size_t nblock = 2, size_t capacity = 500);
228 
229  /**
230  * 析构函数,在析构函数内部将会自动销毁由构造函数传入的 dbuf_pool 对象
231  */
232  ~dbuf_guard();
233 
234  /**
235  * 调用 dbuf_pool::dbuf_reset
236  * @param reserve {size_t}
237  * @return {bool}
238  */
239  bool dbuf_reset(size_t reserve = 0);
240 
241  /**
242  * 调用 dbuf_pool::dbuf_alloc
243  * @param len {size_t}
244  * @return {void*}
245  */
246  void* dbuf_alloc(size_t len)
247  {
248  return dbuf_->dbuf_alloc(len);
249  }
250 
251  /**
252  * 调用 dbuf_pool::dbuf_calloc
253  * @param len {size_t}
254  * @return {void*}
255  */
256  void* dbuf_calloc(size_t len)
257  {
258  return dbuf_->dbuf_calloc(len);
259  }
260 
261  /**
262  * 调用 dbuf_pool::dbuf_strdup
263  * @param s {const char*}
264  * @return {char*}
265  */
266  char* dbuf_strdup(const char* s)
267  {
268  return dbuf_->dbuf_strdup(s);
269  }
270 
271  /**
272  * 调用 dbuf_pool::dbuf_strndup
273  * @param s {const char*}
274  * @param len {size_t}
275  * @return {char*}
276  */
277  char* dbuf_strndup(const char* s, size_t len)
278  {
279  return dbuf_->dbuf_strndup(s, len);
280  }
281 
282  /**
283  * 调用 dbuf_pool::dbuf_memdup
284  * @param addr {const void*}
285  * @param len {size_t}
286  * @return {void*}
287  */
288  void* dbuf_memdup(const void* addr, size_t len)
289  {
290  return dbuf_->dbuf_memdup(addr, len);
291  }
292 
293  /**
294  * 调用 dbuf_pool::dbuf_free
295  * @param addr {const void*}
296  * @return {bool}
297  */
298  bool dbuf_free(const void* addr)
299  {
300  return dbuf_->dbuf_free(addr);
301  }
302 
303  /**
304  * 调用 dbuf_pool::dbuf_keep
305  * @param addr {const void*}
306  * @return {bool}
307  */
308  bool dbuf_keep(const void* addr)
309  {
310  return dbuf_->dbuf_keep(addr);
311  }
312 
313  /**
314  * 调用 dbuf_pool::dbuf_unkeep
315  * @param addr {const void*}
316  * @return {bool}
317  */
318  bool dbuf_unkeep(const void* addr)
319  {
320  return dbuf_->dbuf_unkeep(addr);
321  }
322 
323  /**
324  * 获得 dbuf_pool 对象
325  * @return {acl::dbuf_pool&}
326  */
328  {
329  return *dbuf_;
330  }
331 
332  /**
333  * 可以手动调用本函数,将在 dbuf_pool 上分配的 dbuf_obj 子类对象交给
334  * dbuf_guard 对象统一进行销毁管理;严禁将同一个 dbuf_obj 子类对象同
335  * 时将给多个 dbuf_guard 对象进行管理,否则将会产生对象的重复释放
336  * @param obj {dbuf_obj*}
337  * @return {int} 返回 obj 被添加后其在 dbuf_obj 对象数组中的下标位置,
338  * dbuf_guard 内部对 dbuf_obj 对象的管理具有防重添加机制,所以当多次
339  * 将同一个 dbuf_obj 对象置入同一个 dbuf_guard 对象时,内部只会放一次
340  */
341  int push_back(dbuf_obj* obj);
342 
343  /**
344  * 获得当前内存池中管理的对象数量
345  * @return {size_t}
346  */
347  size_t size() const
348  {
349  return size_;
350  }
351 
352  /**
353  * 返回指定下标的对象
354  * @param pos {size_t} 指定对象的下标位置,不应越界
355  * @return {dbuf_obj*} 当下标位置越界时返回 NULL
356  */
357  dbuf_obj* operator[](size_t pos) const;
358 
359  /**
360  * 返回指定下标的对象
361  * @param pos {size_t} 指定对象的下标位置,不应越界
362  * @return {dbuf_obj*} 当下标位置越界时返回 NULL
363  */
364  dbuf_obj* get(size_t pos) const;
365 
366  /**
367  * 设置内建 objs_ 数组对象每次在扩充空间时的增量,内部缺省值为 100
368  * @param incr {size_t}
369  */
370  void set_increment(size_t incr);
371 
372 public:
373  template <typename T>
374  T* create()
375  {
376  T* t = new (dbuf_alloc(sizeof(T))) T();
377  (void) push_back(t);
378  return t;
379  }
380 
381  template <typename T, typename P1>
382  T* create(P1 p)
383  {
384  T* t = new (dbuf_alloc(sizeof(T))) T(p);
385  (void) push_back(t);
386  return t;
387  }
388 
389  template <typename T, typename P1, typename P2>
390  T* create(P1 p1, P2 p2)
391  {
392  T* t = new (dbuf_alloc(sizeof(T))) T(p1, p2);
393  (void) push_back(t);
394  return t;
395  }
396 
397  template <typename T, typename P1, typename P2, typename P3>
398  T* create(P1 p1, P2 p2, P3 p3)
399  {
400  T* t = new (dbuf_alloc(sizeof(T))) T(p1, p2, p3);
401  (void) push_back(t);
402  return t;
403  }
404 
405  template <typename T, typename P1, typename P2, typename P3,
406  typename P4>
407  T* create(P1 p1, P2 p2, P3 p3, P4 p4)
408  {
409  T* t = new (dbuf_alloc(sizeof(T))) T(p1, p2, p3, p4);
410  (void) push_back(t);
411  return t;
412  }
413 
414  template <typename T, typename P1, typename P2, typename P3,
415  typename P4, typename P5>
416  T* create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
417  {
418  T* t = new (dbuf_alloc(sizeof(T))) T(p1, p2, p3, p4, p5);
419  (void) push_back(t);
420  return t;
421  }
422 
423  template <typename T, typename P1, typename P2, typename P3,
424  typename P4, typename P5, typename P6>
425  T* create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
426  {
427  T* t = new (dbuf_alloc(sizeof(T))) T(p1, p2, p3, p4, p5, p6);
428  (void) push_back(t);
429  return t;
430  }
431 
432  template <typename T, typename P1, typename P2, typename P3,
433  typename P4, typename P5, typename P6, typename P7>
434  T* create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
435  {
436  T* t = new (dbuf_alloc(sizeof(T)))
437  T(p1, p2, p3, p4, p5, p6, p7);
438  (void) push_back(t);
439  return t;
440  }
441 
442  template <typename T, typename P1, typename P2, typename P3,
443  typename P4, typename P5, typename P6, typename P7,
444  typename P8>
445  T* create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
446  {
447  T* t = new (dbuf_alloc(sizeof(T)))
448  T(p1, p2, p3, p4, p5, p6, p7, p8);
449  (void) push_back(t);
450  return t;
451  }
452 
453  template <typename T, typename P1, typename P2, typename P3,
454  typename P4, typename P5, typename P6, typename P7,
455  typename P8,typename P9>
456  T* create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7,
457  P8 p8, P9 p9)
458  {
459  T* t = new (dbuf_alloc(sizeof(T)))
460  T(p1, p2, p3, p4, p5, p6, p7, p8, p9);
461  (void) push_back(t);
462  return t;
463  }
464 
465  template <typename T, typename P1, typename P2, typename P3,
466  typename P4, typename P5, typename P6, typename P7,
467  typename P8, typename P9, typename P10>
468  T* create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7,
469  P8 p8, P9 p9, P10 p10)
470  {
471  T* t = new (dbuf_alloc(sizeof(T)))
472  T(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
473  (void) push_back(t);
474  return t;
475  }
476 
477 private:
478  size_t nblock_; // 内部自建 dbuf_pool 内存块的单位个数
479  size_t incr_; // 增加新的 dbuf_objs_link 时的
480  // capacity 大小
481  dbuf_pool* dbuf_; // 内存池对象
482 
483  // 此处之所以使用自实现的 dbuf_obj 数组对象,而没有使用 std::vector,
484  // 一方面使数组对象也在 dbuf_pool 内存池上创建,另一方面可以避免
485  // std::vector 内部在扩容时的内存不可控性
486 
487  struct dbuf_objs_link
488  {
489  dbuf_obj** objs; // 存储 dbuf_obj 对象的数组对象
490  size_t size; // 存储于 objs 中的对象个数
491  size_t capacity; // objs 数组的大小
492 
493  struct dbuf_objs_link* next;
494  };
495 
496  dbuf_objs_link head_;
497  dbuf_objs_link* curr_;
498  size_t size_;
499 
500  void init(size_t capacity);
501 
502  // 扩充 objs_ 数组对象的空间
503  void extend_objs();
504 };
505 
506 /**
507  * sample1:
508  * // 继承 acl::dbuf_obj 的子类
509  * class myobj1 : public acl::dbuf_obj
510  * {
511  * public:
512  * // 将 guard 对象传递给基类对象,基类将本对象加入 guard 的对象集合中
513  * myobj1(acl::dbuf_guard* guard) : dbuf_obj(guard) {}
514  *
515  * void doit()
516  * {
517  * printf("hello world!\r\n");
518  * }
519  *
520  * private:
521  * ~myobj1() {}
522  * };
523  *
524  * void test()
525  * {
526  * acl::dbuf_guard dbuf;
527  *
528  * // 在 dbuf_guard 对象上创建动态 100 个 myobj 对象
529  * for (int i = 0; i < 100; i++)
530  * {
531  * // 在 guard 对象上创建动态 myobj 对象,且将 guard 作为构造参数
532  * myobj* obj = new (dbuf.dbuf_alloc(sizeof(myobj))) myobj(&dbuf);
533  * obj->doit();
534  * }
535  *
536  * // 当 dbuf 销毁时,在其上面创建的动态对象自动销毁
537  * }
538  *
539  * // sample2
540  * class myobj2 : public acl::dbuf_obj
541  * {
542  * public:
543  * myobj2() {}
544  *
545  * void doit()
546  * {
547  * printf("hello world\r\n");
548  * }
549  *
550  * private:
551  * ~myobj2() {}
552  * };
553  *
554  * void test2()
555  * {
556  * acl::dbuf_guard dbuf;
557  *
558  * for (int i = 0; i < 100; i++)
559  * {
560  * myobj2* obj = dbuf.create<myobj2>();
561  * obj->doit();
562  * }
563  * }
564  *
565  * // sample3
566  * class myobj2 : public acl::dbuf_obj
567  * {
568  * public:
569  * myobj2(int i) : i_(i) {}
570  *
571  * void doit()
572  * {
573  * printf("hello world, i: %d\r\n", i_);
574  * }
575  *
576  * private:
577  * ~myobj2() {}
578  *
579  * private:
580  * int i_;
581  * };
582  *
583  * void test2()
584  * {
585  * acl::dbuf_guard dbuf;
586  *
587  * for (int i = 0; i < 100; i++)
588  * {
589  * myobj2* obj = dbuf.create<myobj2>(i);
590  * obj->doit();
591  * }
592  * }
593  */
594 } // namespace acl
T * create(P1 p1, P2 p2, P3 p3)
Definition: dbuf_pool.hpp:398
T * create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
Definition: dbuf_pool.hpp:445
void * dbuf_memdup(const void *addr, size_t len)
Definition: dbuf_pool.hpp:288
char * dbuf_strndup(const char *s, size_t len)
Definition: dbuf_pool.hpp:277
char * dbuf_strdup(const char *s)
Definition: dbuf_pool.hpp:266
T * create(P1 p)
Definition: dbuf_pool.hpp:382
T * create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
Definition: dbuf_pool.hpp:425
int pos() const
Definition: dbuf_pool.hpp:179
dbuf_guard * get_guard() const
Definition: dbuf_pool.hpp:188
bool dbuf_free(const void *addr)
Definition: dbuf_pool.hpp:298
size_t size() const
Definition: dbuf_pool.hpp:347
T * create(P1 p1, P2 p2)
Definition: dbuf_pool.hpp:390
void * dbuf_alloc(size_t len)
Definition: dbuf_pool.hpp:246
void * dbuf_calloc(size_t len)
Definition: dbuf_pool.hpp:256
T * create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9)
Definition: dbuf_pool.hpp:456
bool dbuf_unkeep(const void *addr)
Definition: dbuf_pool.hpp:318
virtual ~dbuf_obj()
Definition: dbuf_pool.hpp:172
ACL_DBUF_POOL * get_dbuf()
Definition: dbuf_pool.hpp:116
struct ACL_DBUF_POOL ACL_DBUF_POOL
Definition: acl_dbuf_pool.h:8
T * create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
Definition: dbuf_pool.hpp:434
T * create(P1 p1, P2 p2, P3 p3, P4 p4)
Definition: dbuf_pool.hpp:407
acl::dbuf_pool & get_dbuf() const
Definition: dbuf_pool.hpp:327
#define ACL_CPP_API
bool dbuf_keep(const void *addr)
Definition: dbuf_pool.hpp:308
T * create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10)
Definition: dbuf_pool.hpp:468
T * create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
Definition: dbuf_pool.hpp:416