chunked_memory_pool-inl.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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 (!ptr) {
  26. AbortProcess(ToUnderlying(EProcessExitCode::OutOfMemory));
  27. }
  28. #ifndef _win_
  29. auto allocatedSize = ::malloc_usable_size(ptr);
  30. if (allocatedSize) {
  31. size += allocatedSize - requestedSize;
  32. }
  33. #endif
  34. auto* instance = static_cast<TDerived*>(ptr);
  35. try {
  36. new (instance) TDerived(TMutableRef(instance + 1, size), cookie);
  37. } catch (const std::exception& ex) {
  38. // Do not forget to free the memory.
  39. ::free(ptr);
  40. throw;
  41. }
  42. return instance;
  43. }
  44. ////////////////////////////////////////////////////////////////////////////////
  45. inline TChunkedMemoryPool::TChunkedMemoryPool()
  46. : TChunkedMemoryPool(
  47. GetRefCountedTypeCookie<TDefaultChunkedMemoryPoolTag>())
  48. { }
  49. template <class TTag>
  50. inline TChunkedMemoryPool::TChunkedMemoryPool(
  51. TTag,
  52. size_t startChunkSize)
  53. : TChunkedMemoryPool(
  54. GetRefCountedTypeCookie<TTag>(),
  55. startChunkSize)
  56. { }
  57. inline char* TChunkedMemoryPool::AllocateUnaligned(size_t size)
  58. {
  59. // Fast path.
  60. if (FreeZoneEnd_ >= FreeZoneBegin_ + size) {
  61. FreeZoneEnd_ -= size;
  62. Size_ += size;
  63. return FreeZoneEnd_;
  64. }
  65. // Slow path.
  66. return AllocateUnalignedSlow(size);
  67. }
  68. inline char* TChunkedMemoryPool::AllocateAligned(size_t size, int align)
  69. {
  70. // NB: This can lead to FreeZoneBegin_ >= FreeZoneEnd_ in which case the chunk is full.
  71. FreeZoneBegin_ = AlignUp(FreeZoneBegin_, align);
  72. // Fast path.
  73. if (FreeZoneBegin_ + size <= FreeZoneEnd_) {
  74. char* result = FreeZoneBegin_;
  75. Size_ += size;
  76. FreeZoneBegin_ += size;
  77. return result;
  78. }
  79. // Slow path.
  80. return AllocateAlignedSlow(size, align);
  81. }
  82. template <class T>
  83. inline T* TChunkedMemoryPool::AllocateUninitialized(int n, int align)
  84. {
  85. return reinterpret_cast<T*>(AllocateAligned(sizeof(T) * n, align));
  86. }
  87. template <class T>
  88. inline TMutableRange<T> TChunkedMemoryPool::Capture(TRange<T> src, int align)
  89. {
  90. auto* dst = AllocateUninitialized<T>(src.Size(), align);
  91. ::memcpy(dst, src.Begin(), sizeof(T) * src.Size());
  92. return TMutableRange<T>(dst, src.Size());
  93. }
  94. inline void TChunkedMemoryPool::Free(char* from, char* to)
  95. {
  96. if (FreeZoneBegin_ == to) {
  97. FreeZoneBegin_ = from;
  98. }
  99. if (FreeZoneEnd_ == from) {
  100. FreeZoneEnd_ = to;
  101. }
  102. }
  103. inline void TChunkedMemoryPool::Clear()
  104. {
  105. Size_ = 0;
  106. if (Chunks_.empty()) {
  107. FreeZoneBegin_ = nullptr;
  108. FreeZoneEnd_ = nullptr;
  109. NextChunkIndex_ = 0;
  110. } else {
  111. FreeZoneBegin_ = Chunks_.front()->GetRef().Begin();
  112. FreeZoneEnd_ = Chunks_.front()->GetRef().End();
  113. NextChunkIndex_ = 1;
  114. }
  115. for (const auto& block : OtherBlocks_) {
  116. Capacity_ -= block->GetRef().Size();
  117. }
  118. OtherBlocks_.clear();
  119. }
  120. ////////////////////////////////////////////////////////////////////////////////
  121. } // namespace NYT