chunked_memory_pool-inl.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #ifndef CHUNKED_MEMORY_POOL_INL_H_
  2. #error "Direct inclusion of this file is not allowed, include chunked_memory_pool.h"
  3. // For the sake of sane code completion.
  4. #include "chunked_memory_pool.h"
  5. #endif
  6. #include "serialize.h"
  7. #include <library/cpp/yt/system/exit.h>
  8. #include <library/cpp/yt/malloc/malloc.h>
  9. #include <util/system/align.h>
  10. namespace NYT {
  11. ////////////////////////////////////////////////////////////////////////////////
  12. inline void TAllocationHolder::operator delete(void* ptr) noexcept
  13. {
  14. ::free(ptr);
  15. }
  16. inline TMutableRef TAllocationHolder::GetRef() const
  17. {
  18. return Ref_;
  19. }
  20. template <class TDerived>
  21. TDerived* TAllocationHolder::Allocate(size_t size, TRefCountedTypeCookie cookie)
  22. {
  23. auto requestedSize = sizeof(TDerived) + size;
  24. auto* ptr = ::malloc(requestedSize);
  25. if (Y_UNLIKELY(!ptr)) {
  26. AbortProcessDramatically(
  27. EProcessExitCode::OutOfMemory,
  28. "Out-of-memory during chunked memory pool allocation");
  29. }
  30. #ifndef _win_
  31. auto allocatedSize = ::malloc_usable_size(ptr);
  32. if (allocatedSize) {
  33. size += allocatedSize - requestedSize;
  34. }
  35. #endif
  36. auto* instance = static_cast<TDerived*>(ptr);
  37. try {
  38. new (instance) TDerived(TMutableRef(instance + 1, size), cookie);
  39. } catch (const std::exception& ex) {
  40. // Do not forget to free the memory.
  41. ::free(ptr);
  42. throw;
  43. }
  44. return instance;
  45. }
  46. ////////////////////////////////////////////////////////////////////////////////
  47. inline TChunkedMemoryPool::TChunkedMemoryPool()
  48. : TChunkedMemoryPool(
  49. GetRefCountedTypeCookie<TDefaultChunkedMemoryPoolTag>())
  50. { }
  51. template <class TTag>
  52. inline TChunkedMemoryPool::TChunkedMemoryPool(
  53. TTag,
  54. size_t startChunkSize)
  55. : TChunkedMemoryPool(
  56. GetRefCountedTypeCookie<TTag>(),
  57. startChunkSize)
  58. { }
  59. inline char* TChunkedMemoryPool::AllocateUnaligned(size_t size)
  60. {
  61. // Fast path.
  62. if (FreeZoneEnd_ >= FreeZoneBegin_ + size) {
  63. FreeZoneEnd_ -= size;
  64. Size_ += size;
  65. return FreeZoneEnd_;
  66. }
  67. // Slow path.
  68. return AllocateUnalignedSlow(size);
  69. }
  70. inline char* TChunkedMemoryPool::AllocateAligned(size_t size, int align)
  71. {
  72. // NB: This can lead to FreeZoneBegin_ >= FreeZoneEnd_ in which case the chunk is full.
  73. FreeZoneBegin_ = AlignUp(FreeZoneBegin_, align);
  74. // Fast path.
  75. if (FreeZoneBegin_ + size <= FreeZoneEnd_) {
  76. char* result = FreeZoneBegin_;
  77. Size_ += size;
  78. FreeZoneBegin_ += size;
  79. return result;
  80. }
  81. // Slow path.
  82. return AllocateAlignedSlow(size, align);
  83. }
  84. template <class T>
  85. inline T* TChunkedMemoryPool::AllocateUninitialized(int n, int align)
  86. {
  87. return reinterpret_cast<T*>(AllocateAligned(sizeof(T) * n, align));
  88. }
  89. template <class T>
  90. inline TMutableRange<T> TChunkedMemoryPool::Capture(TRange<T> src, int align)
  91. {
  92. auto* dst = AllocateUninitialized<T>(src.Size(), align);
  93. ::memcpy(dst, src.Begin(), sizeof(T) * src.Size());
  94. return TMutableRange<T>(dst, src.Size());
  95. }
  96. inline void TChunkedMemoryPool::Free(char* from, char* to)
  97. {
  98. if (FreeZoneBegin_ == to) {
  99. FreeZoneBegin_ = from;
  100. }
  101. if (FreeZoneEnd_ == from) {
  102. FreeZoneEnd_ = to;
  103. }
  104. }
  105. inline void TChunkedMemoryPool::Clear()
  106. {
  107. Size_ = 0;
  108. if (Chunks_.empty()) {
  109. FreeZoneBegin_ = nullptr;
  110. FreeZoneEnd_ = nullptr;
  111. NextChunkIndex_ = 0;
  112. } else {
  113. FreeZoneBegin_ = Chunks_.front()->GetRef().Begin();
  114. FreeZoneEnd_ = Chunks_.front()->GetRef().End();
  115. NextChunkIndex_ = 1;
  116. }
  117. for (const auto& block : OtherBlocks_) {
  118. Capacity_ -= block->GetRef().Size();
  119. }
  120. OtherBlocks_.clear();
  121. }
  122. ////////////////////////////////////////////////////////////////////////////////
  123. } // namespace NYT