diff options
author | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/yt/memory/blob.cpp |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/yt/memory/blob.cpp')
-rw-r--r-- | library/cpp/yt/memory/blob.cpp | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/library/cpp/yt/memory/blob.cpp b/library/cpp/yt/memory/blob.cpp new file mode 100644 index 00000000000..86000b033bc --- /dev/null +++ b/library/cpp/yt/memory/blob.cpp @@ -0,0 +1,224 @@ +#include "blob.h" +#include "ref.h" + +#include <library/cpp/ytalloc/api/ytalloc.h> + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +static constexpr size_t InitialBlobCapacity = 16; +static constexpr double BlobCapacityMultiplier = 1.5; + +TBlob::TBlob( + TRefCountedTypeCookie tagCookie, + size_t size, + bool initiailizeStorage, + bool pageAligned) + : PageAligned_(pageAligned) +{ + SetTagCookie(tagCookie); + if (size == 0) { + Reset(); + } else { + Allocate(std::max(size, InitialBlobCapacity)); + Size_ = size; + if (initiailizeStorage) { + ::memset(Begin_, 0, Size_); + } + } +} + +TBlob::TBlob( + TRefCountedTypeCookie tagCookie, + TRef data, + bool pageAligned) + : PageAligned_(pageAligned) +{ + SetTagCookie(tagCookie); + Reset(); + Append(data); +} + +TBlob::TBlob(const TBlob& other) + : PageAligned_(other.PageAligned_) +{ + SetTagCookie(other); + if (other.Size_ == 0) { + Reset(); + } else { + Allocate(std::max(InitialBlobCapacity, other.Size_)); + ::memcpy(Begin_, other.Begin_, other.Size_); + Size_ = other.Size_; + } +} + +TBlob::TBlob(TBlob&& other) noexcept + : Begin_(other.Begin_) + , Size_(other.Size_) + , Capacity_(other.Capacity_) + , PageAligned_(other.PageAligned_) +{ + SetTagCookie(other); + other.Reset(); +} + +TBlob::~TBlob() +{ + Free(); +} + +void TBlob::Reserve(size_t newCapacity) +{ + if (newCapacity > Capacity_) { + Reallocate(newCapacity); + } +} + +void TBlob::Resize(size_t newSize, bool initializeStorage /*= true*/) +{ + if (newSize > Size_) { + if (newSize > Capacity_) { + size_t newCapacity; + if (Capacity_ == 0) { + newCapacity = std::max(InitialBlobCapacity, newSize); + } else { + newCapacity = std::max(static_cast<size_t>(Capacity_ * BlobCapacityMultiplier), newSize); + } + Reallocate(newCapacity); + } + if (initializeStorage) { + ::memset(Begin_ + Size_, 0, newSize - Size_); + } + } + Size_ = newSize; +} + +TBlob& TBlob::operator = (const TBlob& rhs) +{ + if (this != &rhs) { + this->~TBlob(); + new(this) TBlob(rhs); + } + return *this; +} + +TBlob& TBlob::operator = (TBlob&& rhs) noexcept +{ + if (this != &rhs) { + this->~TBlob(); + new(this) TBlob(std::move(rhs)); + } + return *this; +} + +void TBlob::Append(const void* data, size_t size) +{ + if (Size_ + size > Capacity_) { + Resize(Size_ + size, false); + ::memcpy(Begin_ + Size_ - size, data, size); + } else { + ::memcpy(Begin_ + Size_, data, size); + Size_ += size; + } +} + +void TBlob::Append(TRef ref) +{ + Append(ref.Begin(), ref.Size()); +} + +void TBlob::Append(char ch) +{ + if (Size_ + 1 > Capacity_) { + Resize(Size_ + 1, false); + Begin_[Size_ - 1] = ch; + } else { + Begin_[Size_++] = ch; + } +} + +void TBlob::Reset() +{ + Begin_ = nullptr; + Size_ = Capacity_ = 0; +} + +char* TBlob::DoAllocate(size_t size) +{ + return static_cast<char*>(PageAligned_ + ? NYTAlloc::AllocatePageAligned(size) + : NYTAlloc::Allocate(size)); +} + +void TBlob::Allocate(size_t newCapacity) +{ + YT_VERIFY(!Begin_); + Begin_ = DoAllocate(newCapacity); + Capacity_ = newCapacity; +#ifdef YT_ENABLE_REF_COUNTED_TRACKING + TRefCountedTrackerFacade::AllocateTagInstance(TagCookie_); + TRefCountedTrackerFacade::AllocateSpace(TagCookie_, newCapacity); +#endif +} + +void TBlob::Reallocate(size_t newCapacity) +{ + if (!Begin_) { + Allocate(newCapacity); + return; + } + char* newBegin = DoAllocate(newCapacity); + ::memcpy(newBegin, Begin_, Size_); + NYTAlloc::FreeNonNull(Begin_); +#ifdef YT_ENABLE_REF_COUNTED_TRACKING + TRefCountedTrackerFacade::AllocateSpace(TagCookie_, newCapacity); + TRefCountedTrackerFacade::FreeSpace(TagCookie_, Capacity_); +#endif + Begin_ = newBegin; + Capacity_ = newCapacity; +} + +void TBlob::Free() +{ + if (!Begin_) { + return; + } + NYTAlloc::FreeNonNull(Begin_); +#ifdef YT_ENABLE_REF_COUNTED_TRACKING + TRefCountedTrackerFacade::FreeTagInstance(TagCookie_); + TRefCountedTrackerFacade::FreeSpace(TagCookie_, Capacity_); +#endif + Reset(); +} + +void TBlob::SetTagCookie(TRefCountedTypeCookie tagCookie) +{ +#ifdef YT_ENABLE_REF_COUNTED_TRACKING + TagCookie_ = tagCookie; +#endif +} + +void TBlob::SetTagCookie(const TBlob& other) +{ +#ifdef YT_ENABLE_REF_COUNTED_TRACKING + TagCookie_ = other.TagCookie_; +#endif +} + +void swap(TBlob& left, TBlob& right) +{ + if (&left != &right) { + std::swap(left.Begin_, right.Begin_); + std::swap(left.Size_, right.Size_); + std::swap(left.Capacity_, right.Capacity_); + std::swap(left.PageAligned_, right.PageAligned_); +#ifdef YT_ENABLE_REF_COUNTED_TRACKING + std::swap(left.TagCookie_, right.TagCookie_); +#endif + } +} + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT |