segpool_alloc.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #pragma once
  2. #include "segmented_string_pool.h"
  3. /**
  4. This is a partially implemented allocator class that uses segmented_pool
  5. as its allocatior base.
  6. In fact, segpool_alloc can only allocate, it can't deallocate. Therefore,
  7. it should be used with add-only containers that are just clear()'ed in the
  8. end of their life cycle.
  9. External segmented_pool object must be cleared explicitly after all
  10. containers use it in their allocator are cleared.
  11. Single segmented_pool object may be used for several containers.
  12. Use segpool_alloc_vt as allocator template parameter for container.
  13. Example:
  14. using TSomething = THashMap<A, B, hash<A>, TEqualTo<A>, segpool_alloc_vt>;
  15. ...
  16. TSomething something;
  17. something.GetNodeAllocator().pool = &alloc_pool;
  18. Some containers may provide no way to access their allocator. In that case,
  19. if you want to use them with segpool_alloc_vt, you should first either
  20. hack them, or fix segpool_alloc so that it would create ref-counted
  21. segmented_pool object on it's own
  22. ! Only tested with THashMap
  23. */
  24. template <class _Tp>
  25. struct segpool_alloc {
  26. using pool_type = segmented_pool<char>;
  27. pool_type* pool;
  28. using pointer = _Tp*;
  29. using const_pointer = const _Tp*;
  30. using reference = _Tp&;
  31. using const_reference = const _Tp&;
  32. using size_type = size_t;
  33. using difference_type = ptrdiff_t;
  34. using value_type = _Tp;
  35. #ifndef NDEBUG
  36. ui64 pool_count, malloc_count, pool_free_count, malloc_free_count;
  37. #endif
  38. segpool_alloc()
  39. : pool(nullptr)
  40. {
  41. Y_IF_DEBUG(pool_count = malloc_count = pool_free_count = malloc_free_count = 0);
  42. }
  43. segpool_alloc(pool_type* p)
  44. : pool(p)
  45. {
  46. Y_IF_DEBUG(pool_count = malloc_count = pool_free_count = malloc_free_count = 0);
  47. }
  48. segpool_alloc(const segpool_alloc& a)
  49. : pool(a.pool)
  50. {
  51. Y_IF_DEBUG(pool_count = malloc_count = pool_free_count = malloc_free_count = 0);
  52. }
  53. template <class _Tp1>
  54. segpool_alloc(const segpool_alloc<_Tp1>& a)
  55. : pool(a.pool)
  56. {
  57. Y_IF_DEBUG(pool_count = malloc_count = pool_free_count = malloc_free_count = 0);
  58. }
  59. _Tp* allocate(size_t __n) {
  60. if (!pool) {
  61. _Tp* data = (_Tp*)malloc(__n * sizeof(_Tp));
  62. Y_IF_DEBUG(if (data) malloc_count++);
  63. return data;
  64. }
  65. _Tp* data = (_Tp*)pool->append(nullptr, __n * sizeof(_Tp));
  66. Y_IF_DEBUG(pool_count++);
  67. return data;
  68. }
  69. void deallocate(pointer __p, size_t /*__n*/) {
  70. if (!pool) {
  71. Y_IF_DEBUG(malloc_free_count++);
  72. free(__p);
  73. } else {
  74. Y_IF_DEBUG(pool_free_count++);
  75. }
  76. }
  77. ~segpool_alloc() {
  78. // assert(pool_count == pool_free_count && malloc_count == malloc_free_count); <- uncomment when swap() problem is solved
  79. // printf("in ~segpool_alloc: size = %u, pool_count = %" PRId64 ", malloc_count = %" PRId64 ", pool_free_count = %" PRId64 ", malloc_free_count = %" PRId64 "\n",
  80. // sizeof(_Tp), pool_count, malloc_count, pool_free_count, malloc_free_count);
  81. // fflush(stdout);
  82. }
  83. template <class _Tp1>
  84. struct rebind {
  85. using other = segpool_alloc<_Tp1>;
  86. };
  87. size_type max_size() const {
  88. return size_type(-1) / sizeof(_Tp);
  89. }
  90. void construct(pointer __p, const _Tp& __val) {
  91. new (__p) _Tp(__val);
  92. }
  93. void destroy(pointer __p) {
  94. (void)__p; /* Make MSVC happy. */
  95. __p->~_Tp();
  96. }
  97. };
  98. template <class _Tp>
  99. inline bool operator==(const segpool_alloc<_Tp>& a1, const segpool_alloc<_Tp>& a2) {
  100. return a1.pool == a2.pool;
  101. }
  102. template <class _Tp>
  103. inline bool operator!=(const segpool_alloc<_Tp>& a1, const segpool_alloc<_Tp>& a2) {
  104. return a1.pool != a2.pool;
  105. }
  106. // Any type since it is supposed to be rebound anyway.
  107. using segpool_alloc_vt = segpool_alloc<int>;