diff options
author | Anton Samokhvalov <pg83@yandex.ru> | 2022-02-10 16:45:17 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:17 +0300 |
commit | d3a398281c6fd1d3672036cb2d63f842d2cb28c5 (patch) | |
tree | dd4bd3ca0f36b817e96812825ffaf10d645803f2 /util/memory | |
parent | 72cb13b4aff9bc9cf22e49251bc8fd143f82538f (diff) | |
download | ydb-d3a398281c6fd1d3672036cb2d63f842d2cb28c5.tar.gz |
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 2 of 2.
Diffstat (limited to 'util/memory')
-rw-r--r-- | util/memory/addstorage.cpp | 2 | ||||
-rw-r--r-- | util/memory/addstorage.h | 90 | ||||
-rw-r--r-- | util/memory/addstorage_ut.cpp | 46 | ||||
-rw-r--r-- | util/memory/alloc.cpp | 38 | ||||
-rw-r--r-- | util/memory/alloc.h | 40 | ||||
-rw-r--r-- | util/memory/benchmark/pool/main.cpp | 20 | ||||
-rw-r--r-- | util/memory/benchmark/ya.make | 2 | ||||
-rw-r--r-- | util/memory/blob.cpp | 430 | ||||
-rw-r--r-- | util/memory/blob.h | 262 | ||||
-rw-r--r-- | util/memory/blob_ut.cpp | 122 | ||||
-rw-r--r-- | util/memory/mmapalloc.cpp | 62 | ||||
-rw-r--r-- | util/memory/mmapalloc.h | 14 | ||||
-rw-r--r-- | util/memory/pool.cpp | 76 | ||||
-rw-r--r-- | util/memory/pool.h | 430 | ||||
-rw-r--r-- | util/memory/pool_ut.cpp | 150 | ||||
-rw-r--r-- | util/memory/segmented_string_pool.cpp | 2 | ||||
-rw-r--r-- | util/memory/segmented_string_pool.h | 82 | ||||
-rw-r--r-- | util/memory/segpool_alloc.cpp | 2 | ||||
-rw-r--r-- | util/memory/segpool_alloc.h | 52 | ||||
-rw-r--r-- | util/memory/smallobj.cpp | 2 | ||||
-rw-r--r-- | util/memory/smallobj.h | 182 | ||||
-rw-r--r-- | util/memory/smallobj_ut.cpp | 126 | ||||
-rw-r--r-- | util/memory/tempbuf.cpp | 484 | ||||
-rw-r--r-- | util/memory/tempbuf.h | 132 | ||||
-rw-r--r-- | util/memory/tempbuf_ut.cpp | 116 | ||||
-rw-r--r-- | util/memory/ut/ya.make | 12 |
26 files changed, 1488 insertions, 1488 deletions
diff --git a/util/memory/addstorage.cpp b/util/memory/addstorage.cpp index 32c7eb0a8f..0fe4b1465f 100644 --- a/util/memory/addstorage.cpp +++ b/util/memory/addstorage.cpp @@ -1 +1 @@ -#include "addstorage.h" +#include "addstorage.h" diff --git a/util/memory/addstorage.h b/util/memory/addstorage.h index e335fcdeca..597c73a988 100644 --- a/util/memory/addstorage.h +++ b/util/memory/addstorage.h @@ -1,81 +1,81 @@ #pragma once - -#include <util/system/align.h> + +#include <util/system/align.h> #include <util/system/defaults.h> - -#include <new> - + +#include <new> + namespace NPrivate { class TAdditionalStorageInfo { - public: + public: constexpr TAdditionalStorageInfo(size_t length) noexcept : Length_(length) { - } - + } + constexpr size_t Length() const noexcept { return Length_; - } - - private: + } + + private: size_t Length_; - }; + }; } - + template <class T> class alignas(::NPrivate::TAdditionalStorageInfo) TAdditionalStorage { using TInfo = ::NPrivate::TAdditionalStorageInfo; -public: +public: inline TAdditionalStorage() noexcept = default; - + inline ~TAdditionalStorage() = default; - - inline void* operator new(size_t len1, size_t len2) { + + inline void* operator new(size_t len1, size_t len2) { static_assert(alignof(T) >= alignof(TInfo)); Y_ASSERT(len1 == sizeof(T)); void* data = ::operator new(CombinedSizeOfInstanceWithTInfo() + len2); void* info = InfoPtr(static_cast<T*>(data)); Y_UNUSED(new (info) TInfo(len2)); - + return data; - } - + } + inline void operator delete(void* ptr) noexcept { - DoDelete(ptr); - } - + DoDelete(ptr); + } + inline void operator delete(void* ptr, size_t) noexcept { - DoDelete(ptr); - } - + DoDelete(ptr); + } + inline void operator delete(void* ptr, size_t, size_t) noexcept { - /* - * this delete operator can be called automagically by compiler - */ - - DoDelete(ptr); - } - + /* + * this delete operator can be called automagically by compiler + */ + + DoDelete(ptr); + } + inline void* AdditionalData() const noexcept { return (char*)(static_cast<const T*>(this)) + CombinedSizeOfInstanceWithTInfo(); - } - + } + static inline T* ObjectFromData(void* data) noexcept { return reinterpret_cast<T*>(static_cast<char*>(data) - CombinedSizeOfInstanceWithTInfo()); - } - + } + inline size_t AdditionalDataLength() const noexcept { return InfoPtr(static_cast<const T*>(this))->Length(); - } - -private: + } + +private: static inline void DoDelete(void* ptr) noexcept { TInfo* info = InfoPtr(static_cast<T*>(ptr)); - info->~TInfo(); + info->~TInfo(); ::operator delete(ptr); - } - + } + static constexpr size_t CombinedSizeOfInstanceWithTInfo() noexcept { return AlignUp(sizeof(T), alignof(TInfo)) + sizeof(TInfo); } @@ -88,6 +88,6 @@ private: return reinterpret_cast<const TInfo*>(reinterpret_cast<const char*>(instance) + CombinedSizeOfInstanceWithTInfo() - sizeof(TInfo)); } -private: +private: void* operator new(size_t) = delete; -}; +}; diff --git a/util/memory/addstorage_ut.cpp b/util/memory/addstorage_ut.cpp index 94d5c4df06..9b0c4989ab 100644 --- a/util/memory/addstorage_ut.cpp +++ b/util/memory/addstorage_ut.cpp @@ -1,24 +1,24 @@ -#include "addstorage.h" - +#include "addstorage.h" + #include <library/cpp/testing/unittest/registar.h> - -class TAddStorageTest: public TTestBase { - UNIT_TEST_SUITE(TAddStorageTest); - UNIT_TEST(TestIt) - UNIT_TEST_SUITE_END(); - - class TClass: public TAdditionalStorage<TClass> { - }; - -private: - inline void TestIt() { - THolder<TClass> c(new (100) TClass); - - UNIT_ASSERT_EQUAL(c->AdditionalDataLength(), 100); - - //test segfault - memset(c->AdditionalData(), 0, c->AdditionalDataLength()); - } -}; - -UNIT_TEST_SUITE_REGISTRATION(TAddStorageTest); + +class TAddStorageTest: public TTestBase { + UNIT_TEST_SUITE(TAddStorageTest); + UNIT_TEST(TestIt) + UNIT_TEST_SUITE_END(); + + class TClass: public TAdditionalStorage<TClass> { + }; + +private: + inline void TestIt() { + THolder<TClass> c(new (100) TClass); + + UNIT_ASSERT_EQUAL(c->AdditionalDataLength(), 100); + + //test segfault + memset(c->AdditionalData(), 0, c->AdditionalDataLength()); + } +}; + +UNIT_TEST_SUITE_REGISTRATION(TAddStorageTest); diff --git a/util/memory/alloc.cpp b/util/memory/alloc.cpp index 50ccb1b25d..49f012d857 100644 --- a/util/memory/alloc.cpp +++ b/util/memory/alloc.cpp @@ -1,20 +1,20 @@ -#include "alloc.h" - -#include <util/generic/singleton.h> -#include <util/system/sys_alloc.h> - -using TBlock = TDefaultAllocator::TBlock; - -TBlock TDefaultAllocator::Allocate(size_t len) { - TBlock ret = {y_allocate(len), len}; - - return ret; -} - -void TDefaultAllocator::Release(const TBlock& block) { - y_deallocate(block.Data); -} - +#include "alloc.h" + +#include <util/generic/singleton.h> +#include <util/system/sys_alloc.h> + +using TBlock = TDefaultAllocator::TBlock; + +TBlock TDefaultAllocator::Allocate(size_t len) { + TBlock ret = {y_allocate(len), len}; + + return ret; +} + +void TDefaultAllocator::Release(const TBlock& block) { + y_deallocate(block.Data); +} + IAllocator* TDefaultAllocator::Instance() noexcept { - return SingletonWithPriority<TDefaultAllocator, 0>(); -} + return SingletonWithPriority<TDefaultAllocator, 0>(); +} diff --git a/util/memory/alloc.h b/util/memory/alloc.h index 51c5a8e50b..d59575aef5 100644 --- a/util/memory/alloc.h +++ b/util/memory/alloc.h @@ -1,27 +1,27 @@ #pragma once -#include <memory> - -template <class Allocator, class T> +#include <memory> + +template <class Allocator, class T> using TReboundAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<T>; - -class IAllocator { -public: - struct TBlock { - void* Data; - size_t Len; - }; - + +class IAllocator { +public: + struct TBlock { + void* Data; + size_t Len; + }; + virtual ~IAllocator() = default; - - virtual TBlock Allocate(size_t len) = 0; - virtual void Release(const TBlock& block) = 0; -}; - -class TDefaultAllocator: public IAllocator { -public: + + virtual TBlock Allocate(size_t len) = 0; + virtual void Release(const TBlock& block) = 0; +}; + +class TDefaultAllocator: public IAllocator { +public: TBlock Allocate(size_t len) override; void Release(const TBlock& block) override; - + static IAllocator* Instance() noexcept; -}; +}; diff --git a/util/memory/benchmark/pool/main.cpp b/util/memory/benchmark/pool/main.cpp index 1dcbc55b7b..0b4d6c94af 100644 --- a/util/memory/benchmark/pool/main.cpp +++ b/util/memory/benchmark/pool/main.cpp @@ -4,17 +4,17 @@ #include <util/generic/xrange.h> #include <util/stream/output.h> -#define BENCHMARK_POOL_ALLOC(chunkSize, allocSize, allocAlign) \ +#define BENCHMARK_POOL_ALLOC(chunkSize, allocSize, allocAlign) \ Y_CPU_BENCHMARK(MemroyPool_chunk##chunkSize##_alloc##allocSize##_align##allocAlign, p) { \ - TMemoryPool pool(chunkSize); \ - for (auto i : xrange<size_t>(0, p.Iterations())) { \ - (void)i; \ - Y_DO_NOT_OPTIMIZE_AWAY(pool.Allocate(allocSize, allocAlign)); \ - } \ - /* \ - Cerr << "Allocated: " << pool.MemoryAllocated() << Endl; \ - Cerr << "Waste: " << pool.MemoryWaste() << Endl; \ - */ \ + TMemoryPool pool(chunkSize); \ + for (auto i : xrange<size_t>(0, p.Iterations())) { \ + (void)i; \ + Y_DO_NOT_OPTIMIZE_AWAY(pool.Allocate(allocSize, allocAlign)); \ + } \ + /* \ + Cerr << "Allocated: " << pool.MemoryAllocated() << Endl; \ + Cerr << "Waste: " << pool.MemoryWaste() << Endl; \ + */ \ } BENCHMARK_POOL_ALLOC(4096, 1, 1) diff --git a/util/memory/benchmark/ya.make b/util/memory/benchmark/ya.make index f81bb6de21..2259b9434e 100644 --- a/util/memory/benchmark/ya.make +++ b/util/memory/benchmark/ya.make @@ -3,5 +3,5 @@ SUBSCRIBER(g:util-subscribers) RECURSE( pool - pool/metrics + pool/metrics ) diff --git a/util/memory/blob.cpp b/util/memory/blob.cpp index 08e3964dab..91da5cadca 100644 --- a/util/memory/blob.cpp +++ b/util/memory/blob.cpp @@ -1,225 +1,225 @@ -#include "blob.h" -#include "addstorage.h" - -#include <util/system/yassert.h> -#include <util/system/filemap.h> +#include "blob.h" +#include "addstorage.h" + +#include <util/system/yassert.h> +#include <util/system/filemap.h> #include <util/system/mlock.h> #include <util/stream/buffer.h> #include <util/generic/ptr.h> #include <util/generic/string.h> -#include <util/generic/buffer.h> -#include <util/generic/ylimits.h> -#include <util/generic/singleton.h> +#include <util/generic/buffer.h> +#include <util/generic/ylimits.h> +#include <util/generic/singleton.h> #include <util/generic/yexception.h> - -template <class TCounter> -class TDynamicBlobBase: public TBlob::TBase, - public TRefCounted<TDynamicBlobBase<TCounter>, TCounter>, - public TAdditionalStorage<TDynamicBlobBase<TCounter>> { + +template <class TCounter> +class TDynamicBlobBase: public TBlob::TBase, + public TRefCounted<TDynamicBlobBase<TCounter>, TCounter>, + public TAdditionalStorage<TDynamicBlobBase<TCounter>> { using TRefBase = TRefCounted<TDynamicBlobBase, TCounter>; - -public: + +public: inline TDynamicBlobBase() = default; - + ~TDynamicBlobBase() override = default; - + void Ref() noexcept override { - TRefBase::Ref(); - } - + TRefBase::Ref(); + } + void UnRef() noexcept override { - TRefBase::UnRef(); - } - + TRefBase::UnRef(); + } + inline void* Data() const noexcept { - return this->AdditionalData(); - } - + return this->AdditionalData(); + } + inline size_t Length() const noexcept { - return this->AdditionalDataLength(); - } -}; - -template <class TCounter> -class TBufferBlobBase: public TBlob::TBase, public TRefCounted<TBufferBlobBase<TCounter>, TCounter> { + return this->AdditionalDataLength(); + } +}; + +template <class TCounter> +class TBufferBlobBase: public TBlob::TBase, public TRefCounted<TBufferBlobBase<TCounter>, TCounter> { using TRefBase = TRefCounted<TBufferBlobBase, TCounter>; - -public: - inline TBufferBlobBase(TBuffer& buf) { - Buf_.Swap(buf); - } - + +public: + inline TBufferBlobBase(TBuffer& buf) { + Buf_.Swap(buf); + } + ~TBufferBlobBase() override = default; - + void Ref() noexcept override { - TRefBase::Ref(); - } - + TRefBase::Ref(); + } + void UnRef() noexcept override { - TRefBase::UnRef(); - } - + TRefBase::UnRef(); + } + inline const TBuffer& Buffer() const noexcept { - return Buf_; - } - -private: - TBuffer Buf_; -}; - -template <class TCounter> -class TStringBlobBase: public TBlob::TBase, public TRefCounted<TStringBlobBase<TCounter>, TCounter> { + return Buf_; + } + +private: + TBuffer Buf_; +}; + +template <class TCounter> +class TStringBlobBase: public TBlob::TBase, public TRefCounted<TStringBlobBase<TCounter>, TCounter> { using TRefBase = TRefCounted<TStringBlobBase, TCounter>; - -public: + +public: inline TStringBlobBase(const TString& s) - : S_(s) - { - } - + : S_(s) + { + } + TStringBlobBase(TString&& s) noexcept : S_(std::move(s)) { } ~TStringBlobBase() override = default; - + void Ref() noexcept override { - TRefBase::Ref(); - } - + TRefBase::Ref(); + } + void UnRef() noexcept override { - TRefBase::UnRef(); - } - + TRefBase::UnRef(); + } + inline const TString& String() const noexcept { - return S_; - } - -private: + return S_; + } + +private: const TString S_; -}; - -template <class TCounter> -class TMappedBlobBase: public TBlob::TBase, public TRefCounted<TMappedBlobBase<TCounter>, TCounter> { +}; + +template <class TCounter> +class TMappedBlobBase: public TBlob::TBase, public TRefCounted<TMappedBlobBase<TCounter>, TCounter> { using TRefBase = TRefCounted<TMappedBlobBase<TCounter>, TCounter>; - -public: + +public: inline TMappedBlobBase(const TMemoryMap& map, ui64 offset, size_t len, EMappingMode mode) - : Map_(map) + : Map_(map) , Mode_(mode) - { + { Y_ENSURE(Map_.IsOpen(), TStringBuf("memory map not open")); - - Map_.Map(offset, len); - - if (len && !Map_.Ptr()) { // Ptr is 0 for blob of size 0 - ythrow yexception() << "can not map(" << offset << ", " << len << ")"; - } + + Map_.Map(offset, len); + + if (len && !Map_.Ptr()) { // Ptr is 0 for blob of size 0 + ythrow yexception() << "can not map(" << offset << ", " << len << ")"; + } if (Mode_ == EMappingMode::Locked) { LockMemory(Data(), Length()); - } - } - + } + } + ~TMappedBlobBase() override { if (Mode_ == EMappingMode::Locked && Length()) { UnlockMemory(Data(), Length()); - } + } } - + void Ref() noexcept override { - TRefBase::Ref(); - } - + TRefBase::Ref(); + } + void UnRef() noexcept override { - TRefBase::UnRef(); - } - + TRefBase::UnRef(); + } + inline const void* Data() const noexcept { - return Map_.Ptr(); - } - + return Map_.Ptr(); + } + inline size_t Length() const noexcept { - return Map_.MappedSize(); - } - -private: - TFileMap Map_; + return Map_.MappedSize(); + } + +private: + TFileMap Map_; EMappingMode Mode_; -}; - -TBlob TBlob::SubBlob(size_t len) const { - /* - * may be slightly optimized - */ - - return SubBlob(0, len); -} - -TBlob TBlob::SubBlob(size_t begin, size_t end) const { - if (begin > Length() || end > Length() || begin > end) { +}; + +TBlob TBlob::SubBlob(size_t len) const { + /* + * may be slightly optimized + */ + + return SubBlob(0, len); +} + +TBlob TBlob::SubBlob(size_t begin, size_t end) const { + if (begin > Length() || end > Length() || begin > end) { ythrow yexception() << "incorrect subblob (" << begin << ", " << end << ", outer length = " << Length() << ")"; - } - - return TBlob(Begin() + begin, end - begin, S_.Base); -} - -TBlob TBlob::DeepCopy() const { + } + + return TBlob(Begin() + begin, end - begin, S_.Base); +} + +TBlob TBlob::DeepCopy() const { return TBlob::Copy(Data(), Length()); -} - -template <class TCounter> -static inline TBlob CopyConstruct(const void* data, size_t len) { +} + +template <class TCounter> +static inline TBlob CopyConstruct(const void* data, size_t len) { using Base = TDynamicBlobBase<TCounter>; - THolder<Base> base(new (len) Base); - + THolder<Base> base(new (len) Base); + Y_ASSERT(base->Length() == len); - - memcpy(base->Data(), data, len); - - TBlob ret(base->Data(), len, base.Get()); + + memcpy(base->Data(), data, len); + + TBlob ret(base->Data(), len, base.Get()); Y_UNUSED(base.Release()); - - return ret; -} - + + return ret; +} + TBlob TBlob::CopySingleThreaded(const void* data, size_t length) { - return CopyConstruct<TSimpleCounter>(data, length); -} - + return CopyConstruct<TSimpleCounter>(data, length); +} + TBlob TBlob::Copy(const void* data, size_t length) { - return CopyConstruct<TAtomicCounter>(data, length); -} - -TBlob TBlob::NoCopy(const void* data, size_t length) { + return CopyConstruct<TAtomicCounter>(data, length); +} + +TBlob TBlob::NoCopy(const void* data, size_t length) { return TBlob(data, length, nullptr); -} - -template <class TCounter> +} + +template <class TCounter> static inline TBlob ConstructFromMap(const TMemoryMap& map, ui64 offset, size_t length, EMappingMode mode) { using TBase = TMappedBlobBase<TCounter>; THolder<TBase> base(new TBase(map, offset, length, mode)); - TBlob ret(base->Data(), base->Length(), base.Get()); + TBlob ret(base->Data(), base->Length(), base.Get()); Y_UNUSED(base.Release()); - - return ret; -} - + + return ret; +} + template <class TCounter, class T> static inline TBlob ConstructAsMap(const T& t, EMappingMode mode) { TMemoryMap::EOpenMode openMode = (mode == EMappingMode::Precharged) ? (TMemoryMap::oRdOnly | TMemoryMap::oPrecharge) : TMemoryMap::oRdOnly; TMemoryMap map(t, openMode); - const ui64 toMap = map.Length(); - - if (toMap > Max<size_t>()) { - ythrow yexception() << "can not map whole file(length = " << toMap << ")"; - } - + const ui64 toMap = map.Length(); + + if (toMap > Max<size_t>()) { + ythrow yexception() << "can not map whole file(length = " << toMap << ")"; + } + return ConstructFromMap<TCounter>(map, 0, static_cast<size_t>(toMap), mode); -} - +} + TBlob TBlob::FromFileSingleThreaded(const TString& path, EMappingMode mode) { return ConstructAsMap<TSimpleCounter>(path, mode); } @@ -238,20 +238,20 @@ TBlob TBlob::FromFile(const TFile& file, EMappingMode mode) { TBlob TBlob::FromFileSingleThreaded(const TString& path) { return ConstructAsMap<TSimpleCounter>(path, EMappingMode::Standard); -} - +} + TBlob TBlob::FromFile(const TString& path) { return ConstructAsMap<TAtomicCounter>(path, EMappingMode::Standard); -} - +} + TBlob TBlob::FromFileSingleThreaded(const TFile& file) { return ConstructAsMap<TSimpleCounter>(file, EMappingMode::Standard); -} - +} + TBlob TBlob::FromFile(const TFile& file) { return ConstructAsMap<TAtomicCounter>(file, EMappingMode::Standard); -} - +} + TBlob TBlob::PrechargedFromFileSingleThreaded(const TString& path) { return ConstructAsMap<TSimpleCounter>(path, EMappingMode::Precharged); } @@ -294,36 +294,36 @@ TBlob TBlob::LockedFromMemoryMap(const TMemoryMap& map, ui64 offset, size_t leng TBlob TBlob::FromMemoryMapSingleThreaded(const TMemoryMap& map, ui64 offset, size_t length) { return ConstructFromMap<TSimpleCounter>(map, offset, length, EMappingMode::Standard); -} - +} + TBlob TBlob::FromMemoryMap(const TMemoryMap& map, ui64 offset, size_t length) { return ConstructFromMap<TAtomicCounter>(map, offset, length, EMappingMode::Standard); -} - -template <class TCounter> +} + +template <class TCounter> static inline TBlob ReadFromFile(const TFile& file, ui64 offset, size_t length) { using TBase = TDynamicBlobBase<TCounter>; - THolder<TBase> base(new (length) TBase); - + THolder<TBase> base(new (length) TBase); + Y_ASSERT(base->Length() == length); - - file.Pload(base->Data(), length, offset); - - TBlob ret(base->Data(), length, base.Get()); + + file.Pload(base->Data(), length, offset); + + TBlob ret(base->Data(), length, base.Get()); Y_UNUSED(base.Release()); - - return ret; -} - -template <class TCounter> + + return ret; +} + +template <class TCounter> static inline TBlob ConstructFromFileContent(const TFile& file, ui64 offset, ui64 length) { if (length > Max<size_t>()) { ythrow yexception() << "can not read whole file(length = " << length << ")"; } return ReadFromFile<TCounter>(file, offset, static_cast<size_t>(length)); -} - +} + TBlob TBlob::FromFileContentSingleThreaded(const TString& path) { TFile file(path, RdOnly); return ConstructFromFileContent<TSimpleCounter>(file, 0, file.GetLength()); @@ -343,14 +343,14 @@ TBlob TBlob::FromFileContent(const TFile& file) { } TBlob TBlob::FromFileContentSingleThreaded(const TFile& file, ui64 offset, size_t length) { - return ConstructFromFileContent<TSimpleCounter>(file, offset, length); -} - + return ConstructFromFileContent<TSimpleCounter>(file, offset, length); +} + TBlob TBlob::FromFileContent(const TFile& file, ui64 offset, size_t length) { - return ConstructFromFileContent<TAtomicCounter>(file, offset, length); -} - -template <class TCounter> + return ConstructFromFileContent<TAtomicCounter>(file, offset, length); +} + +template <class TCounter> static inline TBlob ConstructFromBuffer(TBuffer& in) { using TBase = TBufferBlobBase<TCounter>; THolder<TBase> base(new TBase(in)); @@ -364,23 +364,23 @@ static inline TBlob ConstructFromBuffer(TBuffer& in) { template <class TCounter> static inline TBlob ConstructFromStream(IInputStream& in) { TBuffer buf; - - { - TBufferOutput out(buf); - - TransferData(&in, &out); - } - + + { + TBufferOutput out(buf); + + TransferData(&in, &out); + } + return ConstructFromBuffer<TCounter>(buf); -} - +} + TBlob TBlob::FromStreamSingleThreaded(IInputStream& in) { return ConstructFromStream<TSimpleCounter>(in); -} - +} + TBlob TBlob::FromStream(IInputStream& in) { return ConstructFromStream<TAtomicCounter>(in); -} +} TBlob TBlob::FromBufferSingleThreaded(TBuffer& in) { return ConstructFromBuffer<TSimpleCounter>(in); @@ -389,29 +389,29 @@ TBlob TBlob::FromBufferSingleThreaded(TBuffer& in) { TBlob TBlob::FromBuffer(TBuffer& in) { return ConstructFromBuffer<TAtomicCounter>(in); } - + template <class TCounter, class S> TBlob ConstructFromString(S&& s) { using TBase = TStringBlobBase<TCounter>; auto base = MakeHolder<TBase>(std::forward<S>(s)); - + TBlob ret(base->String().data(), base->String().size(), base.Get()); Y_UNUSED(base.Release()); - - return ret; -} - + + return ret; +} + TBlob TBlob::FromStringSingleThreaded(const TString& s) { - return ConstructFromString<TSimpleCounter>(s); -} - + return ConstructFromString<TSimpleCounter>(s); +} + TBlob TBlob::FromStringSingleThreaded(TString&& s) { return ConstructFromString<TSimpleCounter>(std::move(s)); } TBlob TBlob::FromString(const TString& s) { - return ConstructFromString<TAtomicCounter>(s); -} + return ConstructFromString<TAtomicCounter>(s); +} TBlob TBlob::FromString(TString&& s) { return ConstructFromString<TAtomicCounter>(std::move(s)); diff --git a/util/memory/blob.h b/util/memory/blob.h index 4375e6e416..20c02a68df 100644 --- a/util/memory/blob.h +++ b/util/memory/blob.h @@ -1,15 +1,15 @@ #pragma once - + #include <util/generic/fwd.h> #include <util/generic/strbuf.h> #include <util/generic/utility.h> #include <util/system/defaults.h> - -class TMemoryMap; + +class TMemoryMap; class IInputStream; class TFile; class TBuffer; - + enum class EMappingMode { /// Just mmap a file allowing lazy page loading at access Standard, @@ -21,45 +21,45 @@ enum class EMappingMode { /// @addtogroup BLOBs /// @{ -class TBlob { -public: - class TBase { - public: +class TBlob { +public: + class TBase { + public: inline TBase() noexcept = default; virtual ~TBase() = default; - + virtual void Ref() noexcept = 0; virtual void UnRef() noexcept = 0; - }; - -private: - struct TStorage { - const void* Data; - size_t Length; - TBase* Base; - + }; + +private: + struct TStorage { + const void* Data; + size_t Length; + TBase* Base; + inline TStorage(const void* data, size_t length, TBase* base) noexcept - : Data(data) - , Length(length) - , Base(base) - { - } - + : Data(data) + , Length(length) + , Base(base) + { + } + inline ~TStorage() = default; - + inline void Swap(TStorage& r) noexcept { - DoSwap(Data, r.Data); - DoSwap(Length, r.Length); - DoSwap(Base, r.Base); - } - }; - -public: + DoSwap(Data, r.Data); + DoSwap(Length, r.Length); + DoSwap(Base, r.Base); + } + }; + +public: using value_type = ui8; using const_reference = const value_type&; using const_pointer = const value_type*; using const_iterator = const_pointer; - + /** * Constructs a null blob (data array points to nullptr). */ @@ -67,13 +67,13 @@ public: : S_(nullptr, 0, nullptr) { } - + inline TBlob(const TBlob& r) noexcept - : S_(r.S_) - { - Ref(); - } - + : S_(r.S_) + { + Ref(); + } + TBlob(TBlob&& r) noexcept : TBlob() { @@ -81,41 +81,41 @@ public: } inline TBlob(const void* data, size_t length, TBase* base) noexcept - : S_(data, length, base) - { - Ref(); - } - + : S_(data, length, base) + { + Ref(); + } + inline ~TBlob() { - UnRef(); - } - + UnRef(); + } + inline TBlob& operator=(const TBlob& r) noexcept { - TBlob(r).Swap(*this); - - return *this; - } - + TBlob(r).Swap(*this); + + return *this; + } + /// Swaps content of two data arrays. inline void Swap(TBlob& r) noexcept { - S_.Swap(r.S_); - } - + S_.Swap(r.S_); + } + /// Returns a const reference to the data array. inline const void* Data() const noexcept { - return S_.Data; - } - + return S_.Data; + } + /// Returns the size of the data array in bytes. inline size_t Length() const noexcept { - return S_.Length; - } - + return S_.Length; + } + /// Checks if the object has an empty data array. - Y_PURE_FUNCTION inline bool Empty() const noexcept { - return !Length(); - } - + Y_PURE_FUNCTION inline bool Empty() const noexcept { + return !Length(); + } + /// Checks if the blob owns data Y_PURE_FUNCTION inline bool OwnsData() const noexcept { return S_.Base != nullptr; @@ -123,31 +123,31 @@ public: /// Checks if the object has a data array. inline bool IsNull() const noexcept { - return !Data(); - } - + return !Data(); + } + /// Returns a const pointer of char type to the data array. inline const char* AsCharPtr() const noexcept { - return (const char*)Data(); - } - + return (const char*)Data(); + } + /// Returns a const pointer of unsigned char type to the data array. inline const unsigned char* AsUnsignedCharPtr() const noexcept { - return (const unsigned char*)Data(); - } - + return (const unsigned char*)Data(); + } + inline TStringBuf AsStringBuf() const noexcept { return TStringBuf(AsCharPtr(), size()); } /// Drops the data array. inline void Drop() noexcept { - TBlob().Swap(*this); - } - - /* + TBlob().Swap(*this); + } + + /* * Some stl-like methods - */ + */ /// Returns a const reference to the data array. /// result type is const ui8* which is not consistent with Data method above @@ -164,42 +164,42 @@ public: /// Returns the size of the data array in bytes. inline size_t Size() const noexcept { - return Length(); - } - + return Length(); + } + /// Standard iterator. inline const_iterator Begin() const noexcept { - return AsUnsignedCharPtr(); - } - + return AsUnsignedCharPtr(); + } + /// Standard iterator. inline const_iterator End() const noexcept { - return Begin() + Size(); - } - + return Begin() + Size(); + } + inline value_type operator[](size_t n) const noexcept { - return *(Begin() + n); - } - + return *(Begin() + n); + } + /// Shortcut to SubBlob(0, len) - TBlob SubBlob(size_t len) const; - + TBlob SubBlob(size_t len) const; + /// Creates a new object from the provided range [begin, end) of internal data. No memory allocation and no copy. /// @details Increments the refcounter of the current object - TBlob SubBlob(size_t begin, size_t end) const; - + TBlob SubBlob(size_t begin, size_t end) const; + /// Calls Copy() for the internal data. - TBlob DeepCopy() const; - + TBlob DeepCopy() const; + /// Creates a new blob with a single-threaded (non atomic) refcounter. Dynamically allocates memory and copies the data content. - static TBlob CopySingleThreaded(const void* data, size_t length); - + static TBlob CopySingleThreaded(const void* data, size_t length); + /// Creates a new blob with a multi-threaded (atomic) refcounter. Dynamically allocates memory and copies the data content. - static TBlob Copy(const void* data, size_t length); - + static TBlob Copy(const void* data, size_t length); + /// Creates a blob which doesn't own data. No refcounter, no memory allocation, no data copy. - static TBlob NoCopy(const void* data, size_t length); - + static TBlob NoCopy(const void* data, size_t length); + /// Creates a blob with a single-threaded (non atomic) refcounter. It maps the file on the path as data. static TBlob FromFileSingleThreaded(const TString& path, EMappingMode); @@ -214,16 +214,16 @@ public: /// Creates a blob with a single-threaded (non atomic) refcounter. It maps the file on the path as data. static TBlob FromFileSingleThreaded(const TString& path); - + /// Creates a blob with a multi-threaded (atomic) refcounter. It maps the file on the path as data. static TBlob FromFile(const TString& path); - + /// Creates a blob with a single-threaded (non atomic) refcounter. It maps the file on the path as data. static TBlob FromFileSingleThreaded(const TFile& file); - + /// Creates a blob with a multi-threaded (atomic) refcounter. It maps the file on the path as data. static TBlob FromFile(const TFile& file); - + // TODO: drop Precharged* functions. /// Creates a precharged blob with a single-threaded (non atomic) refcounter. It maps the file on the path as data. @@ -257,11 +257,11 @@ public: static TBlob LockedFromMemoryMap(const TMemoryMap& map, ui64 offset, size_t length); /// Creates a blob with a single-threaded (non atomic) refcounter from the mapped memory. - static TBlob FromMemoryMapSingleThreaded(const TMemoryMap& map, ui64 offset, size_t length); - + static TBlob FromMemoryMapSingleThreaded(const TMemoryMap& map, ui64 offset, size_t length); + /// Creates a blob with a multi-threaded (atomic) refcounter from the mapped memory. - static TBlob FromMemoryMap(const TMemoryMap& map, ui64 offset, size_t length); - + static TBlob FromMemoryMap(const TMemoryMap& map, ui64 offset, size_t length); + /// Creates a blob with a single-threaded (non atomic) refcounter. Dynamically allocates memory and copies data from the file on the path using pread(). static TBlob FromFileContentSingleThreaded(const TString& path); @@ -269,58 +269,58 @@ public: static TBlob FromFileContent(const TString& path); /// Creates a blob with a single-threaded (non atomic) refcounter. Dynamically allocates memory and copies data from the file using pread(). - static TBlob FromFileContentSingleThreaded(const TFile& file); + static TBlob FromFileContentSingleThreaded(const TFile& file); /// Creates a blob with a multi-threaded (atomic) refcounter. Dynamically allocates memory and copies data from the file using pread(). - static TBlob FromFileContent(const TFile& file); + static TBlob FromFileContent(const TFile& file); /// Creates a blob with a single-threaded (non atomic) refcounter. Dynamically allocates memory and copies data from the provided range of the file content using pread(). - static TBlob FromFileContentSingleThreaded(const TFile& file, ui64 offset, size_t length); - + static TBlob FromFileContentSingleThreaded(const TFile& file, ui64 offset, size_t length); + /// Creates a blob with a multi-threaded (atomic) refcounter. Dynamically allocates memory and copies data from the provided range of the file content using pread(). - static TBlob FromFileContent(const TFile& file, ui64 offset, size_t length); - + static TBlob FromFileContent(const TFile& file, ui64 offset, size_t length); + /// Creates a blob from the stream content with a single-threaded (non atomic) refcounter. static TBlob FromStreamSingleThreaded(IInputStream& in); - + /// Creates a blob from the stream content with a multi-threaded (atomic) refcounter. static TBlob FromStream(IInputStream& in); - + /// Creates a blob with a single-threaded (non atomic) refcounter. No memory allocation, no content copy. /// @details The input object becomes empty. - static TBlob FromBufferSingleThreaded(TBuffer& in); + static TBlob FromBufferSingleThreaded(TBuffer& in); /// Creates a blob with a multi-threaded (atomic) refcounter. No memory allocation, no content copy. /// @details The input object becomes empty. - static TBlob FromBuffer(TBuffer& in); + static TBlob FromBuffer(TBuffer& in); /// Creates a blob from TString with a single-threaded (non atomic) refcounter. static TBlob FromStringSingleThreaded(const TString& s); - + /// Creates a blob from TString with a single-threaded (non atomic) refcounter. Doesn't copy its content. static TBlob FromStringSingleThreaded(TString&& s); /// Creates a blob from TString with a multi-threaded (atomic) refcounter. static TBlob FromString(const TString& s); - + /// Creates a blob from TString with a multi-threaded (atomic) refcounter. Doesn't copy its content. static TBlob FromString(TString&& s); -private: +private: inline void Ref() noexcept { if (S_.Base) { S_.Base->Ref(); } - } - + } + inline void UnRef() noexcept { if (S_.Base) { S_.Base->UnRef(); } - } - -private: - TStorage S_; -}; - + } + +private: + TStorage S_; +}; + /// @} diff --git a/util/memory/blob_ut.cpp b/util/memory/blob_ut.cpp index 84882a7a9d..023f9a0487 100644 --- a/util/memory/blob_ut.cpp +++ b/util/memory/blob_ut.cpp @@ -1,5 +1,5 @@ -#include "blob.h" - +#include "blob.h" + #include <library/cpp/testing/unittest/registar.h> #include <util/system/tempfile.h> @@ -8,72 +8,72 @@ #include <util/stream/file.h> #include <util/generic/buffer.h> #include <util/generic/array_ref.h> - -Y_UNIT_TEST_SUITE(TBlobTest) { - Y_UNIT_TEST(TestSubBlob) { - TBlob child; - const char* p = nullptr; - { - TBlob parent = TBlob::CopySingleThreaded("0123456789", 10); - UNIT_ASSERT_EQUAL(parent.Length(), 10); - p = parent.AsCharPtr(); - UNIT_ASSERT_EQUAL(memcmp(p, "0123456789", 10), 0); - child = parent.SubBlob(2, 5); - } // Don't worry about parent +Y_UNIT_TEST_SUITE(TBlobTest) { + Y_UNIT_TEST(TestSubBlob) { + TBlob child; + const char* p = nullptr; + + { + TBlob parent = TBlob::CopySingleThreaded("0123456789", 10); + UNIT_ASSERT_EQUAL(parent.Length(), 10); + p = parent.AsCharPtr(); + UNIT_ASSERT_EQUAL(memcmp(p, "0123456789", 10), 0); + child = parent.SubBlob(2, 5); + } // Don't worry about parent + + UNIT_ASSERT_EQUAL(child.Length(), 3); + UNIT_ASSERT_EQUAL(memcmp(child.AsCharPtr(), "234", 3), 0); + UNIT_ASSERT_EQUAL(p + 2, child.AsCharPtr()); + } + + Y_UNIT_TEST(TestFromStream) { + TString s("sjklfgsdyutfuyas54fa78s5f89a6df790asdf7"); + TMemoryInput mi(s.data(), s.size()); + TBlob b = TBlob::FromStreamSingleThreaded(mi); - UNIT_ASSERT_EQUAL(child.Length(), 3); - UNIT_ASSERT_EQUAL(memcmp(child.AsCharPtr(), "234", 3), 0); - UNIT_ASSERT_EQUAL(p + 2, child.AsCharPtr()); - } + UNIT_ASSERT_EQUAL(TString((const char*)b.Data(), b.Length()), s); + } - Y_UNIT_TEST(TestFromStream) { - TString s("sjklfgsdyutfuyas54fa78s5f89a6df790asdf7"); - TMemoryInput mi(s.data(), s.size()); - TBlob b = TBlob::FromStreamSingleThreaded(mi); - - UNIT_ASSERT_EQUAL(TString((const char*)b.Data(), b.Length()), s); - } - - Y_UNIT_TEST(TestFromString) { - TString s("dsfkjhgsadftusadtf"); - TBlob b(TBlob::FromString(s)); + Y_UNIT_TEST(TestFromString) { + TString s("dsfkjhgsadftusadtf"); + TBlob b(TBlob::FromString(s)); - UNIT_ASSERT_EQUAL(TString((const char*)b.Data(), b.Size()), s); - const auto expectedRef = TArrayRef<const ui8>{(ui8*)s.data(), s.size()}; - UNIT_ASSERT_EQUAL(TArrayRef<const ui8>{b}, expectedRef); - } + UNIT_ASSERT_EQUAL(TString((const char*)b.Data(), b.Size()), s); + const auto expectedRef = TArrayRef<const ui8>{(ui8*)s.data(), s.size()}; + UNIT_ASSERT_EQUAL(TArrayRef<const ui8>{b}, expectedRef); + } - Y_UNIT_TEST(TestFromBuffer) { - const size_t sz = 1234u; - TBuffer buf; - buf.Resize(sz); - UNIT_ASSERT_EQUAL(buf.Size(), sz); - TBlob b = TBlob::FromBuffer(buf); - UNIT_ASSERT_EQUAL(buf.Size(), 0u); - UNIT_ASSERT_EQUAL(b.Size(), sz); - } + Y_UNIT_TEST(TestFromBuffer) { + const size_t sz = 1234u; + TBuffer buf; + buf.Resize(sz); + UNIT_ASSERT_EQUAL(buf.Size(), sz); + TBlob b = TBlob::FromBuffer(buf); + UNIT_ASSERT_EQUAL(buf.Size(), 0u); + UNIT_ASSERT_EQUAL(b.Size(), sz); + } - Y_UNIT_TEST(TestFromFile) { - TString path = "testfile"; + Y_UNIT_TEST(TestFromFile) { + TString path = "testfile"; - TOFStream stream(path); - stream.Write("1234", 4); - stream.Finish(); + TOFStream stream(path); + stream.Write("1234", 4); + stream.Finish(); - auto testMode = [](TBlob blob) { - UNIT_ASSERT_EQUAL(blob.Size(), 4); - UNIT_ASSERT_EQUAL(TStringBuf(static_cast<const char*>(blob.Data()), 4), "1234"); - }; + auto testMode = [](TBlob blob) { + UNIT_ASSERT_EQUAL(blob.Size(), 4); + UNIT_ASSERT_EQUAL(TStringBuf(static_cast<const char*>(blob.Data()), 4), "1234"); + }; - testMode(TBlob::FromFile(path)); - testMode(TBlob::PrechargedFromFile(path)); - testMode(TBlob::LockedFromFile(path)); - } + testMode(TBlob::FromFile(path)); + testMode(TBlob::PrechargedFromFile(path)); + testMode(TBlob::LockedFromFile(path)); + } - Y_UNIT_TEST(TestEmptyLockedFiles) { - TString path = MakeTempName(); - TFsPath(path).Touch(); - TBlob::LockedFromFile(path); - } -}; + Y_UNIT_TEST(TestEmptyLockedFiles) { + TString path = MakeTempName(); + TFsPath(path).Touch(); + TBlob::LockedFromFile(path); + } +}; diff --git a/util/memory/mmapalloc.cpp b/util/memory/mmapalloc.cpp index 59e4ef8012..ec618cc808 100644 --- a/util/memory/mmapalloc.cpp +++ b/util/memory/mmapalloc.cpp @@ -1,33 +1,33 @@ -#include "alloc.h" -#include "mmapalloc.h" - -#include <util/system/filemap.h> -#include <util/generic/singleton.h> - -namespace { - class TMmapAllocator: public IAllocator { - public: +#include "alloc.h" +#include "mmapalloc.h" + +#include <util/system/filemap.h> +#include <util/generic/singleton.h> + +namespace { + class TMmapAllocator: public IAllocator { + public: TBlock Allocate(size_t len) override { - TMappedAllocation m(len + sizeof(TMappedAllocation)); - TMappedAllocation* real = (TMappedAllocation*)m.Data(); - - (new (real) TMappedAllocation(0))->swap(m); - - TBlock ret = {real + 1, len}; - - return ret; - } - + TMappedAllocation m(len + sizeof(TMappedAllocation)); + TMappedAllocation* real = (TMappedAllocation*)m.Data(); + + (new (real) TMappedAllocation(0))->swap(m); + + TBlock ret = {real + 1, len}; + + return ret; + } + void Release(const TBlock& block) override { - TMappedAllocation tmp(0); - TMappedAllocation* real = ((TMappedAllocation*)block.Data) - 1; - - real->swap(tmp); - real->~TMappedAllocation(); - } - }; -} - -IAllocator* MmapAllocator() { - return SingletonWithPriority<TMmapAllocator, 0>(); -} + TMappedAllocation tmp(0); + TMappedAllocation* real = ((TMappedAllocation*)block.Data) - 1; + + real->swap(tmp); + real->~TMappedAllocation(); + } + }; +} + +IAllocator* MmapAllocator() { + return SingletonWithPriority<TMmapAllocator, 0>(); +} diff --git a/util/memory/mmapalloc.h b/util/memory/mmapalloc.h index d1410795c8..06002e58fc 100644 --- a/util/memory/mmapalloc.h +++ b/util/memory/mmapalloc.h @@ -1,8 +1,8 @@ #pragma once - -class IAllocator; - -/* - * return anonymous memory based allocator - */ -IAllocator* MmapAllocator(); + +class IAllocator; + +/* + * return anonymous memory based allocator + */ +IAllocator* MmapAllocator(); diff --git a/util/memory/pool.cpp b/util/memory/pool.cpp index b3144aefc3..9a011f0e4f 100644 --- a/util/memory/pool.cpp +++ b/util/memory/pool.cpp @@ -1,55 +1,55 @@ -#include "pool.h" - +#include "pool.h" + TMemoryPool::IGrowPolicy* TMemoryPool::TLinearGrow::Instance() noexcept { - return SingletonWithPriority<TLinearGrow, 0>(); -} - + return SingletonWithPriority<TLinearGrow, 0>(); +} + TMemoryPool::IGrowPolicy* TMemoryPool::TExpGrow::Instance() noexcept { - return SingletonWithPriority<TExpGrow, 0>(); -} - -void TMemoryPool::AddChunk(size_t hint) { - const size_t dataLen = Max(BlockSize_, hint); + return SingletonWithPriority<TExpGrow, 0>(); +} + +void TMemoryPool::AddChunk(size_t hint) { + const size_t dataLen = Max(BlockSize_, hint); size_t allocSize = dataLen + sizeof(TChunk); if (Options_.RoundUpToNextPowerOfTwo) { allocSize = FastClp2(allocSize); } TBlock nb = Alloc_->Allocate(allocSize); - + // Add previous chunk's stats if (Current_ != &Empty_) { MemoryAllocatedBeforeCurrent_ += Current_->Used(); MemoryWasteBeforeCurrent_ += Current_->Left(); } - BlockSize_ = GrowPolicy_->Next(dataLen); - Current_ = new (nb.Data) TChunk(nb.Len - sizeof(TChunk)); - Chunks_.PushBack(Current_); -} - -void TMemoryPool::DoClear(bool keepfirst) noexcept { - while (!Chunks_.Empty()) { - TChunk* c = Chunks_.PopBack(); - - if (keepfirst && Chunks_.Empty()) { - c->ResetChunk(); - Chunks_.PushBack(c); - Current_ = c; - BlockSize_ = c->BlockLength() - sizeof(TChunk); - MemoryAllocatedBeforeCurrent_ = 0; + BlockSize_ = GrowPolicy_->Next(dataLen); + Current_ = new (nb.Data) TChunk(nb.Len - sizeof(TChunk)); + Chunks_.PushBack(Current_); +} + +void TMemoryPool::DoClear(bool keepfirst) noexcept { + while (!Chunks_.Empty()) { + TChunk* c = Chunks_.PopBack(); + + if (keepfirst && Chunks_.Empty()) { + c->ResetChunk(); + Chunks_.PushBack(c); + Current_ = c; + BlockSize_ = c->BlockLength() - sizeof(TChunk); + MemoryAllocatedBeforeCurrent_ = 0; MemoryWasteBeforeCurrent_ = 0; - return; - } - - TBlock b = {c, c->BlockLength()}; - - c->~TChunk(); - Alloc_->Release(b); - } - - Current_ = &Empty_; - BlockSize_ = Origin_; + return; + } + + TBlock b = {c, c->BlockLength()}; + + c->~TChunk(); + Alloc_->Release(b); + } + + Current_ = &Empty_; + BlockSize_ = Origin_; MemoryAllocatedBeforeCurrent_ = 0; MemoryWasteBeforeCurrent_ = 0; -} +} diff --git a/util/memory/pool.h b/util/memory/pool.h index 8802f4fb1b..13c8b6b9ed 100644 --- a/util/memory/pool.h +++ b/util/memory/pool.h @@ -1,19 +1,19 @@ #pragma once - -#include "alloc.h" - -#include <util/system/align.h> -#include <util/system/yassert.h> + +#include "alloc.h" + +#include <util/system/align.h> +#include <util/system/yassert.h> #include <util/generic/bitops.h> #include <util/generic/utility.h> -#include <util/generic/intrlist.h> +#include <util/generic/intrlist.h> #include <util/generic/strbuf.h> #include <util/generic/singleton.h> #include <new> #include <string> #include <utility> - + /** * Memory pool implements a memory allocation scheme that is very fast, but * limited in its usage. @@ -23,32 +23,32 @@ * can just drop them off into oblivion without calling any destructors, * provided that all associated memory was allocated on the pool. */ -class TMemoryPool { -private: +class TMemoryPool { +private: using TBlock = IAllocator::TBlock; - - class TChunk: public TIntrusiveListItem<TChunk> { - public: + + class TChunk: public TIntrusiveListItem<TChunk> { + public: inline TChunk(size_t len = 0) noexcept - : Cur_((char*)(this + 1)) - , Left_(len) - { + : Cur_((char*)(this + 1)) + , Left_(len) + { Y_ASSERT((((size_t)Cur_) % PLATFORM_DATA_ALIGN) == 0); - } - + } + inline void* Allocate(size_t len) noexcept { - if (Left_ >= len) { - char* ret = Cur_; - - Cur_ += len; - Left_ -= len; - - return ret; - } - + if (Left_ >= len) { + char* ret = Cur_; + + Cur_ += len; + Left_ -= len; + + return ret; + } + return nullptr; - } - + } + inline void* Allocate(size_t len, size_t align) noexcept { size_t pad = AlignUp(Cur_, align) - Cur_; @@ -61,68 +61,68 @@ private: } inline size_t BlockLength() const noexcept { - return (Cur_ + Left_) - (char*)this; - } - + return (Cur_ + Left_) - (char*)this; + } + inline size_t Used() const noexcept { - return Cur_ - (const char*)this; - } + return Cur_ - (const char*)this; + } inline size_t Left() const noexcept { - return Left_; - } - + return Left_; + } + inline const char* Data() const noexcept { - return (const char*)(this + 1); - } + return (const char*)(this + 1); + } inline char* Data() noexcept { - return (char*)(this + 1); - } + return (char*)(this + 1); + } inline size_t DataSize() const noexcept { - return Cur_ - Data(); - } + return Cur_ - Data(); + } inline void ResetChunk() noexcept { - size_t total = DataSize() + Left(); - Cur_ = Data(); - Left_ = total; - } - - private: - char* Cur_; - size_t Left_; - }; + size_t total = DataSize() + Left(); + Cur_ = Data(); + Left_ = total; + } + + private: + char* Cur_; + size_t Left_; + }; using TChunkList = TIntrusiveList<TChunk>; - -public: - class IGrowPolicy { - public: + +public: + class IGrowPolicy { + public: virtual ~IGrowPolicy() = default; - + virtual size_t Next(size_t prev) const noexcept = 0; - }; - - class TLinearGrow: public IGrowPolicy { - public: + }; + + class TLinearGrow: public IGrowPolicy { + public: size_t Next(size_t prev) const noexcept override { - return prev; - } - + return prev; + } + static IGrowPolicy* Instance() noexcept; - }; - - class TExpGrow: public IGrowPolicy { - public: + }; + + class TExpGrow: public IGrowPolicy { + public: size_t Next(size_t prev) const noexcept override { - return prev * 2; - } - + return prev * 2; + } + static IGrowPolicy* Instance() noexcept; - }; - + }; + struct TOptions { bool RoundUpToNextPowerOfTwo; TOptions() @@ -132,44 +132,44 @@ public: }; inline TMemoryPool(size_t initial, IGrowPolicy* grow = TExpGrow::Instance(), IAllocator* alloc = TDefaultAllocator::Instance(), const TOptions& options = TOptions()) - : Current_(&Empty_) - , BlockSize_(initial) - , GrowPolicy_(grow) - , Alloc_(alloc) + : Current_(&Empty_) + , BlockSize_(initial) + , GrowPolicy_(grow) + , Alloc_(alloc) , Options_(options) - , Origin_(initial) + , Origin_(initial) , MemoryAllocatedBeforeCurrent_(0) , MemoryWasteBeforeCurrent_(0) - { - } - + { + } + inline ~TMemoryPool() { - Clear(); - } + Clear(); + } - inline void* Allocate(size_t len) { - return RawAllocate(AlignUp<size_t>(len, PLATFORM_DATA_ALIGN)); - } + inline void* Allocate(size_t len) { + return RawAllocate(AlignUp<size_t>(len, PLATFORM_DATA_ALIGN)); + } inline void* Allocate(size_t len, size_t align) { return RawAllocate(AlignUp<size_t>(len, PLATFORM_DATA_ALIGN), align); } - template <typename T> - inline T* Allocate() { + template <typename T> + inline T* Allocate() { return (T*)this->Allocate(sizeof(T), alignof(T)); - } + } - template <typename T> + template <typename T> inline T* Allocate(size_t align) { return (T*)this->Allocate(sizeof(T), Max(align, alignof(T))); } template <typename T> - inline T* AllocateArray(size_t count) { + inline T* AllocateArray(size_t count) { return (T*)this->Allocate(sizeof(T) * count, alignof(T)); - } - + } + template <typename T> inline T* AllocateArray(size_t count, size_t align) { return (T*)this->Allocate(sizeof(T) * count, Max(align, alignof(T))); @@ -192,90 +192,90 @@ public: template <typename T, typename... Args> inline T* New(Args&&... args) { return new (Allocate<T>()) T(std::forward<Args>(args)...); - } - - template <typename T> - inline T* NewArray(size_t count) { + } + + template <typename T> + inline T* NewArray(size_t count) { T* arr = (T*)AllocateArray<T>(count); - - for (T *ptr = arr, *end = arr + count; ptr != end; ++ptr) { - new (ptr) T; - } - return arr; - } + for (T *ptr = arr, *end = arr + count; ptr != end; ++ptr) { + new (ptr) T; + } + + return arr; + } - template <typename TChar> - inline TChar* Append(const TChar* str) { + template <typename TChar> + inline TChar* Append(const TChar* str) { return Append(str, std::char_traits<TChar>::length(str) + 1); // include terminating zero byte - } + } - template <typename TChar> - inline TChar* Append(const TChar* str, size_t len) { + template <typename TChar> + inline TChar* Append(const TChar* str, size_t len) { TChar* ret = AllocateArray<TChar>(len); std::char_traits<TChar>::copy(ret, str, len); - return ret; - } + return ret; + } - template <typename TChar> + template <typename TChar> inline TBasicStringBuf<TChar> AppendString(const TBasicStringBuf<TChar>& buf) { return TBasicStringBuf<TChar>(Append(buf.data(), buf.size()), buf.size()); - } + } - template <typename TChar> + template <typename TChar> inline TBasicStringBuf<TChar> AppendCString(const TBasicStringBuf<TChar>& buf) { TChar* ret = static_cast<TChar*>(Allocate((buf.size() + 1) * sizeof(TChar))); - + std::char_traits<TChar>::copy(ret, buf.data(), buf.size()); *(ret + buf.size()) = 0; return TBasicStringBuf<TChar>(ret, buf.size()); - } + } inline size_t Available() const noexcept { - return Current_->Left(); - } - + return Current_->Left(); + } + inline void Clear() noexcept { - DoClear(false); - } - + DoClear(false); + } + inline void ClearKeepFirstChunk() noexcept { - DoClear(true); - } - + DoClear(true); + } + inline size_t MemoryAllocated() const noexcept { return MemoryAllocatedBeforeCurrent_ + (Current_ != &Empty_ ? Current_->Used() : 0); - } - + } + inline size_t MemoryWaste() const noexcept { return MemoryWasteBeforeCurrent_ + (Current_ != &Empty_ ? Current_->Left() : 0); - } - - template <class TOp> + } + + template <class TOp> inline void Traverse(TOp& op) const noexcept { - for (TChunkList::TConstIterator i = Chunks_.Begin(); i != Chunks_.End(); ++i) { - op(i->Data(), i->DataSize()); + for (TChunkList::TConstIterator i = Chunks_.Begin(); i != Chunks_.End(); ++i) { + op(i->Data(), i->DataSize()); } - } - - inline IAllocator* RealAllocator() const noexcept { - return Alloc_; - } - -protected: - inline void* RawAllocate(size_t len) { - void* ret = Current_->Allocate(len); - - if (ret) { - return ret; - } - - AddChunk(len); - - return Current_->Allocate(len); - } - + } + + inline IAllocator* RealAllocator() const noexcept { + return Alloc_; + } + +protected: + inline void* RawAllocate(size_t len) { + void* ret = Current_->Allocate(len); + + if (ret) { + return ret; + } + + AddChunk(len); + + return Current_->Allocate(len); + } + inline void* RawAllocate(size_t len, size_t align) { Y_ASSERT(align > 0); void* ret = Current_->Allocate(len, align); @@ -289,38 +289,38 @@ protected: return Current_->Allocate(len, align); } -private: - void AddChunk(size_t hint); - void DoClear(bool keepfirst) noexcept; +private: + void AddChunk(size_t hint); + void DoClear(bool keepfirst) noexcept; -private: - TChunk Empty_; - TChunk* Current_; - size_t BlockSize_; - IGrowPolicy* GrowPolicy_; - IAllocator* Alloc_; +private: + TChunk Empty_; + TChunk* Current_; + size_t BlockSize_; + IGrowPolicy* GrowPolicy_; + IAllocator* Alloc_; TOptions Options_; - TChunkList Chunks_; - const size_t Origin_; + TChunkList Chunks_; + const size_t Origin_; size_t MemoryAllocatedBeforeCurrent_; size_t MemoryWasteBeforeCurrent_; -}; - -template <typename TPool> +}; + +template <typename TPool> struct TPoolableBase { inline void* operator new(size_t bytes, TPool& pool) { return pool.Allocate(bytes); } - + inline void* operator new(size_t bytes, std::align_val_t align, TPool& pool) { return pool.Allocate(bytes, (size_t)align); } inline void operator delete(void*, size_t) noexcept { - } - + } + inline void operator delete(void*, TPool&) noexcept { - } + } private: inline void* operator new(size_t); // disallow default allocation @@ -329,30 +329,30 @@ private: struct TPoolable: public TPoolableBase<TMemoryPool> { }; -class TMemoryPoolAllocator: public IAllocator { -public: - inline TMemoryPoolAllocator(TMemoryPool* pool) - : Pool_(pool) - { - } - +class TMemoryPoolAllocator: public IAllocator { +public: + inline TMemoryPoolAllocator(TMemoryPool* pool) + : Pool_(pool) + { + } + TBlock Allocate(size_t len) override { - TBlock ret = {Pool_->Allocate(len), len}; - - return ret; - } - + TBlock ret = {Pool_->Allocate(len), len}; + + return ret; + } + void Release(const TBlock& block) override { - (void)block; - } - -private: - TMemoryPool* Pool_; -}; - + (void)block; + } + +private: + TMemoryPool* Pool_; +}; + template <class T, class TPool> class TPoolAllocBase { -public: +public: using pointer = T*; using const_pointer = const T*; using reference = T&; @@ -361,46 +361,46 @@ public: using difference_type = ptrdiff_t; using value_type = T; - inline TPoolAllocBase(TPool* pool) - : Pool_(pool) - { - } + inline TPoolAllocBase(TPool* pool) + : Pool_(pool) + { + } - template <typename TOther> - inline TPoolAllocBase(const TPoolAllocBase<TOther, TPool>& o) - : Pool_(o.GetPool()) - { - } + template <typename TOther> + inline TPoolAllocBase(const TPoolAllocBase<TOther, TPool>& o) + : Pool_(o.GetPool()) + { + } - inline T* allocate(size_t n) { + inline T* allocate(size_t n) { return (T*)Pool_->Allocate(n * sizeof(T), alignof(T)); - } + } - inline void deallocate(pointer /*p*/, size_t /*n*/) { - } + inline void deallocate(pointer /*p*/, size_t /*n*/) { + } - template <class T1> - struct rebind { + template <class T1> + struct rebind { using other = TPoolAllocBase<T1, TPool>; - }; + }; inline size_type max_size() const noexcept { - return size_type(-1) / sizeof(T); - } + return size_type(-1) / sizeof(T); + } template <typename... Args> inline void construct(pointer p, Args&&... args) { new (p) T(std::forward<Args>(args)...); - } + } inline void destroy(pointer p) noexcept { - (void)p; /* Make MSVC happy. */ - p->~T(); - } + (void)p; /* Make MSVC happy. */ + p->~T(); + } - inline TPool* GetPool() const { - return Pool_; - } + inline TPool* GetPool() const { + return Pool_; + } inline friend bool operator==(const TPoolAllocBase& l, const TPoolAllocBase& r) { return l.Pool_ == r.Pool_; @@ -410,11 +410,11 @@ public: return !(l == r); } -private: - TPool* Pool_; +private: + TPool* Pool_; }; -template <class T> +template <class T> using TPoolAlloc = TPoolAllocBase<T, TMemoryPool>; // Any type since it is supposed to be rebound anyway. diff --git a/util/memory/pool_ut.cpp b/util/memory/pool_ut.cpp index 2d0bfa011d..1158a8ca42 100644 --- a/util/memory/pool_ut.cpp +++ b/util/memory/pool_ut.cpp @@ -1,55 +1,55 @@ -#include "pool.h" - +#include "pool.h" + #include <library/cpp/testing/unittest/registar.h> - + #include <util/stream/output.h> - + class TCheckedAllocator: public TDefaultAllocator { public: inline TCheckedAllocator() : Alloced_(0) , Released_(0) , Allocs_(0) - , Frees_(0) - { + , Frees_(0) + { } - + TBlock Allocate(size_t len) override { Check(); - + Alloced_ += len; ++Allocs_; - + return TDefaultAllocator::Allocate(len); } - + void Release(const TBlock& block) override { Released_ += block.Len; ++Frees_; - + Check(); - + TDefaultAllocator::Release(block); } - + inline void CheckAtEnd() { UNIT_ASSERT_EQUAL(Alloced_, Released_); UNIT_ASSERT_EQUAL(Allocs_, Frees_); } - + private: inline void Check() { UNIT_ASSERT(Alloced_ >= Released_); UNIT_ASSERT(Allocs_ >= Frees_); } - + private: size_t Alloced_; size_t Released_; size_t Allocs_; size_t Frees_; }; - + class TErrorOnCopy { public: TErrorOnCopy() = default; @@ -85,46 +85,46 @@ class TMemPoolTest: public TTestBase { UNIT_TEST(TestMoveAlloc) UNIT_TEST(TestRoundUpToNextPowerOfTwoOption) UNIT_TEST_SUITE_END(); - + private: inline void TestMemPool() { TCheckedAllocator alloc; - { - TMemoryPool pool(123, TMemoryPool::TExpGrow::Instance(), &alloc); - - for (size_t i = 0; i < 1000; ++i) { - UNIT_ASSERT(pool.Allocate(i)); - } - } - - alloc.CheckAtEnd(); - - { - TMemoryPool pool(150, TMemoryPool::TExpGrow::Instance(), &alloc); - - pool.Allocate(8); - - size_t memavail = pool.Available(); - size_t memwaste = pool.MemoryWaste(); - size_t memalloc = pool.MemoryAllocated(); - - for (size_t i = 0; i < 1000; ++i) { - void* m = pool.Allocate(i); - UNIT_ASSERT(m); - memset(m, 0, i); - } - - pool.ClearKeepFirstChunk(); - - UNIT_ASSERT_VALUES_EQUAL(memalloc - 8, pool.MemoryAllocated()); - UNIT_ASSERT_VALUES_EQUAL(memwaste + 8, pool.MemoryWaste()); - UNIT_ASSERT_VALUES_EQUAL(memavail + 8, pool.Available()); - - for (size_t i = 0; i < 1000; ++i) { - void* m = pool.Allocate(i); - UNIT_ASSERT(m); - memset(m, 0, i); + { + TMemoryPool pool(123, TMemoryPool::TExpGrow::Instance(), &alloc); + + for (size_t i = 0; i < 1000; ++i) { + UNIT_ASSERT(pool.Allocate(i)); + } + } + + alloc.CheckAtEnd(); + + { + TMemoryPool pool(150, TMemoryPool::TExpGrow::Instance(), &alloc); + + pool.Allocate(8); + + size_t memavail = pool.Available(); + size_t memwaste = pool.MemoryWaste(); + size_t memalloc = pool.MemoryAllocated(); + + for (size_t i = 0; i < 1000; ++i) { + void* m = pool.Allocate(i); + UNIT_ASSERT(m); + memset(m, 0, i); + } + + pool.ClearKeepFirstChunk(); + + UNIT_ASSERT_VALUES_EQUAL(memalloc - 8, pool.MemoryAllocated()); + UNIT_ASSERT_VALUES_EQUAL(memwaste + 8, pool.MemoryWaste()); + UNIT_ASSERT_VALUES_EQUAL(memavail + 8, pool.Available()); + + for (size_t i = 0; i < 1000; ++i) { + void* m = pool.Allocate(i); + UNIT_ASSERT(m); + memset(m, 0, i); } pool.Clear(); @@ -132,28 +132,28 @@ private: UNIT_ASSERT_VALUES_EQUAL(0, pool.MemoryAllocated()); UNIT_ASSERT_VALUES_EQUAL(0, pool.MemoryWaste()); UNIT_ASSERT_VALUES_EQUAL(0, pool.Available()); - } + } - alloc.CheckAtEnd(); + alloc.CheckAtEnd(); struct TConstructorTest { int ConstructorType; - TConstructorTest() - : ConstructorType(1) - { - } - TConstructorTest(int) - : ConstructorType(2) - { - } + TConstructorTest() + : ConstructorType(1) + { + } + TConstructorTest(int) + : ConstructorType(2) + { + } TConstructorTest(const TString&, const TString&) - : ConstructorType(3) - { - } + : ConstructorType(3) + { + } TConstructorTest(TString&&, TString&&) - : ConstructorType(4) - { - } + : ConstructorType(4) + { + } }; { @@ -167,7 +167,7 @@ private: } alloc.CheckAtEnd(); - } + } inline void TestAlign() { TMemoryPool pool(1); @@ -232,7 +232,7 @@ private: elems.reserve(1); elems.emplace_back(); elems.resize(100); - } + } void TestMoveAlloc() { CheckMoveAlloc<TNoMove>(); @@ -243,7 +243,7 @@ private: void TestRoundUpToNextPowerOfTwoOption() { const size_t MEMORY_POOL_BLOCK_SIZE = (1024 - 16) * 4096 - 16 - 16 - 32; - class TFixedBlockSizeMemoryPoolPolicy final: public TMemoryPool::IGrowPolicy { + class TFixedBlockSizeMemoryPoolPolicy final: public TMemoryPool::IGrowPolicy { public: size_t Next(size_t /*prev*/) const noexcept override { return MEMORY_POOL_BLOCK_SIZE; @@ -251,7 +251,7 @@ private: }; TFixedBlockSizeMemoryPoolPolicy allocationPolicy; - class TTestAllocator final: public TDefaultAllocator { + class TTestAllocator final: public TDefaultAllocator { public: TBlock Allocate(size_t len) override { Size_ += len; @@ -280,6 +280,6 @@ private: pool.Allocate(1); UNIT_ASSERT_VALUES_EQUAL(2 * EXPECTED_ALLOCATION_SIZE, allocator.GetSize()); } -}; - -UNIT_TEST_SUITE_REGISTRATION(TMemPoolTest); +}; + +UNIT_TEST_SUITE_REGISTRATION(TMemPoolTest); diff --git a/util/memory/segmented_string_pool.cpp b/util/memory/segmented_string_pool.cpp index e2a561fcb5..9cfe7af8a4 100644 --- a/util/memory/segmented_string_pool.cpp +++ b/util/memory/segmented_string_pool.cpp @@ -1 +1 @@ -#include "segmented_string_pool.h" +#include "segmented_string_pool.h" diff --git a/util/memory/segmented_string_pool.h b/util/memory/segmented_string_pool.h index 2208ceed6d..a40aa408f5 100644 --- a/util/memory/segmented_string_pool.h +++ b/util/memory/segmented_string_pool.h @@ -1,39 +1,39 @@ #pragma once #include <util/system/align.h> -#include <util/system/yassert.h> -#include <util/system/defaults.h> +#include <util/system/yassert.h> +#include <util/system/defaults.h> #include <util/generic/noncopyable.h> -#include <util/generic/vector.h> +#include <util/generic/vector.h> #include <util/generic/strbuf.h> - + #include <memory> -#include <cstdio> -#include <cstdlib> - +#include <cstdio> +#include <cstdlib> + /* * Non-reallocated storage for the objects of POD type */ template <class T, class Alloc = std::allocator<T>> -class segmented_pool: TNonCopyable { +class segmented_pool: TNonCopyable { protected: - Alloc seg_allocator; + Alloc seg_allocator; struct seg_inf { - T* data; // allocated chunk + T* data; // allocated chunk size_t _size; // size of allocated chunk in sizeof(T)-units size_t freepos; // offset to free chunk's memory in bytes - seg_inf() + seg_inf() : data(nullptr) - , _size(0) - , freepos(0) - { - } + , _size(0) + , freepos(0) + { + } seg_inf(T* d, size_t sz) - : data(d) - , _size(sz) - , freepos(0) - { - } + : data(d) + , _size(sz) + , freepos(0) + { + } }; using seg_container = TVector<seg_inf>; using seg_iterator = typename seg_container::iterator; @@ -53,20 +53,20 @@ protected: if (curseg == segs.end() || curseg->_size < last_free) { segs.push_back(seg_inf(seg_allocator.allocate(last_free), last_free)); if (Y_UNLIKELY(Name)) - printf("Pool \"%s\" was increased by %" PRISZT " bytes to %" PRISZT " Mb.\n", Name, last_free * sizeof(T), capacity() / 0x100000); + printf("Pool \"%s\" was increased by %" PRISZT " bytes to %" PRISZT " Mb.\n", Name, last_free * sizeof(T), capacity() / 0x100000); curseg = segs.end() - 1; } Y_ASSERT(curseg->freepos == 0); Y_ASSERT(curseg->_size >= last_free); } } - + public: explicit segmented_pool(size_t segsz, const char* name = nullptr) - : segment_size(segsz) - , last_free(0) - , last_ins_size(0) - , Name(name) + : segment_size(segsz) + , last_free(0) + , last_ins_size(0) + , Name(name) { curseg = segs.begin(); } @@ -74,23 +74,23 @@ public: clear(); } /* src - array of objects, len - count of elements in array */ - T* append(const T* src, size_t len) { + T* append(const T* src, size_t len) { check_capacity(len); - ui8* rv = (ui8*)curseg->data + curseg->freepos; + ui8* rv = (ui8*)curseg->data + curseg->freepos; last_ins_size = sizeof(T) * len; if (src) memcpy(rv, src, last_ins_size); curseg->freepos += last_ins_size, last_free -= len; return (T*)rv; } - T* append() { + T* append() { T* obj = get_raw(); - new (obj) T(); + new (obj) T(); return obj; } - T* get_raw() { // append(0, 1) + T* get_raw() { // append(0, 1) check_capacity(1); - ui8* rv = (ui8*)curseg->data + curseg->freepos; + ui8* rv = (ui8*)curseg->data + curseg->freepos; last_ins_size = sizeof(T); curseg->freepos += last_ins_size, last_free -= 1; return (T*)rv; @@ -100,7 +100,7 @@ public: } bool contains(const T* ptr) const { for (seg_const_iterator i = segs.begin(), ie = segs.end(); i != ie; ++i) - if ((char*)ptr >= (char*)i->data && (char*)ptr < (char*)i->data + i->freepos) + if ((char*)ptr >= (char*)i->data && (char*)ptr < (char*)i->data + i->freepos) return true; return false; } @@ -146,10 +146,10 @@ public: } }; -class segmented_string_pool: public segmented_pool<char> { +class segmented_string_pool: public segmented_pool<char> { private: using _Base = segmented_pool<char>; - + public: segmented_string_pool() : segmented_string_pool(1024 * 1024) @@ -157,14 +157,14 @@ public: } explicit segmented_string_pool(size_t segsz) - : _Base(segsz) - { - } - char* append(const char* src) { + : _Base(segsz) + { + } + char* append(const char* src) { Y_ASSERT(src); return _Base::append(src, strlen(src) + 1); } - char* append(const char* src, size_t len) { + char* append(const char* src, size_t len) { char* rv = _Base::append(nullptr, len + 1); if (src) memcpy(rv, src, len); @@ -185,7 +185,7 @@ public: }; template <typename T, typename C> -inline T* pool_push(segmented_pool<C>& pool, const T* v) { +inline T* pool_push(segmented_pool<C>& pool, const T* v) { static_assert(sizeof(C) == 1, "only char type supported"); size_t len = SizeOf(v); C* buf = pool.append(nullptr, AlignUp(len)); diff --git a/util/memory/segpool_alloc.cpp b/util/memory/segpool_alloc.cpp index 1893487aa6..2b3a29fe51 100644 --- a/util/memory/segpool_alloc.cpp +++ b/util/memory/segpool_alloc.cpp @@ -1 +1 @@ -#include "segpool_alloc.h" +#include "segpool_alloc.h" diff --git a/util/memory/segpool_alloc.h b/util/memory/segpool_alloc.h index 7917f07407..1a83b7a543 100644 --- a/util/memory/segpool_alloc.h +++ b/util/memory/segpool_alloc.h @@ -42,28 +42,28 @@ struct segpool_alloc { #ifndef NDEBUG ui64 pool_count, malloc_count, pool_free_count, malloc_free_count; #endif - segpool_alloc() + segpool_alloc() : pool(nullptr) - { + { Y_IF_DEBUG(pool_count = malloc_count = pool_free_count = malloc_free_count = 0); } segpool_alloc(pool_type* p) - : pool(p) - { + : pool(p) + { Y_IF_DEBUG(pool_count = malloc_count = pool_free_count = malloc_free_count = 0); } segpool_alloc(const segpool_alloc& a) - : pool(a.pool) - { + : pool(a.pool) + { Y_IF_DEBUG(pool_count = malloc_count = pool_free_count = malloc_free_count = 0); } template <class _Tp1> segpool_alloc(const segpool_alloc<_Tp1>& a) - : pool(a.pool) - { + : pool(a.pool) + { Y_IF_DEBUG(pool_count = malloc_count = pool_free_count = malloc_free_count = 0); - } - _Tp* allocate(size_t __n) { + } + _Tp* allocate(size_t __n) { if (!pool) { _Tp* data = (_Tp*)malloc(__n * sizeof(_Tp)); Y_IF_DEBUG(if (data) malloc_count++); @@ -83,35 +83,35 @@ struct segpool_alloc { } } ~segpool_alloc() { - //assert(pool_count == pool_free_count && malloc_count == malloc_free_count); <- uncomment when swap() problem is solved + //assert(pool_count == pool_free_count && malloc_count == malloc_free_count); <- uncomment when swap() problem is solved //printf("in ~segpool_alloc: size = %u, pool_count = %" PRId64 ", malloc_count = %" PRId64 ", pool_free_count = %" PRId64 ", malloc_free_count = %" PRId64 "\n", // sizeof(_Tp), pool_count, malloc_count, pool_free_count, malloc_free_count); - //fflush(stdout); + //fflush(stdout); } - template <class _Tp1> - struct rebind { + template <class _Tp1> + struct rebind { using other = segpool_alloc<_Tp1>; }; size_type max_size() const { return size_type(-1) / sizeof(_Tp); } - void construct(pointer __p, const _Tp& __val) { - new (__p) _Tp(__val); - } - void destroy(pointer __p) { - (void)__p; /* Make MSVC happy. */ - __p->~_Tp(); - } + void construct(pointer __p, const _Tp& __val) { + new (__p) _Tp(__val); + } + void destroy(pointer __p) { + (void)__p; /* Make MSVC happy. */ + __p->~_Tp(); + } }; - + template <class _Tp> -inline bool operator==(const segpool_alloc<_Tp>& a1, const segpool_alloc<_Tp>& a2) { - return a1.pool == a2.pool; +inline bool operator==(const segpool_alloc<_Tp>& a1, const segpool_alloc<_Tp>& a2) { + return a1.pool == a2.pool; } template <class _Tp> -inline bool operator!=(const segpool_alloc<_Tp>& a1, const segpool_alloc<_Tp>& a2) { - return a1.pool != a2.pool; +inline bool operator!=(const segpool_alloc<_Tp>& a1, const segpool_alloc<_Tp>& a2) { + return a1.pool != a2.pool; } // Any type since it is supposed to be rebound anyway. diff --git a/util/memory/smallobj.cpp b/util/memory/smallobj.cpp index 82bd9e29bd..4605c08720 100644 --- a/util/memory/smallobj.cpp +++ b/util/memory/smallobj.cpp @@ -1 +1 @@ -#include "smallobj.h" +#include "smallobj.h" diff --git a/util/memory/smallobj.h b/util/memory/smallobj.h index ef6814bbb3..63de666bae 100644 --- a/util/memory/smallobj.h +++ b/util/memory/smallobj.h @@ -1,42 +1,42 @@ #pragma once - -#include "pool.h" -#include "alloc.h" - + +#include "pool.h" +#include "alloc.h" + #include <util/generic/utility.h> -#include <util/generic/intrlist.h> - -class TFixedSizeAllocator { - struct TAlloc: public TIntrusiveSListItem<TAlloc> { +#include <util/generic/intrlist.h> + +class TFixedSizeAllocator { + struct TAlloc: public TIntrusiveSListItem<TAlloc> { inline void* ToPointer() noexcept { - return this; - } - + return this; + } + static inline TAlloc* FromPointer(void* ptr) noexcept { - return (TAlloc*)ptr; - } - + return (TAlloc*)ptr; + } + static constexpr size_t EntitySize(size_t alloc) noexcept { - return Max(sizeof(TAlloc), alloc); - } - + return Max(sizeof(TAlloc), alloc); + } + static constexpr size_t EntityAlign(size_t align) noexcept { return Max(alignof(TAlloc), align); } static inline TAlloc* Construct(void* ptr) noexcept { - return (TAlloc*)ptr; - } - }; - -public: + return (TAlloc*)ptr; + } + }; + +public: using IGrowPolicy = TMemoryPool::IGrowPolicy; - + TFixedSizeAllocator(size_t allocSize, IAllocator* alloc) : TFixedSizeAllocator(allocSize, alignof(TAlloc), TMemoryPool::TExpGrow::Instance(), alloc) - { - } - + { + } + TFixedSizeAllocator(size_t allocSize, size_t alignSize, IAllocator* alloc) : TFixedSizeAllocator(allocSize, alignSize, TMemoryPool::TExpGrow::Instance(), alloc) { @@ -48,94 +48,94 @@ public: } TFixedSizeAllocator(size_t allocSize, size_t alignSize, IGrowPolicy* grow, IAllocator* alloc) - : Pool_(allocSize, grow, alloc) + : Pool_(allocSize, grow, alloc) , AlignSize_(TAlloc::EntityAlign(alignSize)) , AllocSize_(TAlloc::EntitySize(allocSize)) - { - } - - inline void* Allocate() { + { + } + + inline void* Allocate() { if (Y_UNLIKELY(Free_.Empty())) { return Pool_.Allocate(AllocSize_, AlignSize_); - } - - return Free_.PopFront()->ToPointer(); - } - + } + + return Free_.PopFront()->ToPointer(); + } + inline void Release(void* ptr) noexcept { - Free_.PushFront(TAlloc::FromPointer(ptr)); - } - + Free_.PushFront(TAlloc::FromPointer(ptr)); + } + inline size_t Size() const noexcept { - return AllocSize_; - } - -private: - TMemoryPool Pool_; + return AllocSize_; + } + +private: + TMemoryPool Pool_; const size_t AlignSize_; - const size_t AllocSize_; - TIntrusiveSList<TAlloc> Free_; -}; - -template <class T> -class TSmallObjAllocator { -public: + const size_t AllocSize_; + TIntrusiveSList<TAlloc> Free_; +}; + +template <class T> +class TSmallObjAllocator { +public: using IGrowPolicy = TFixedSizeAllocator::IGrowPolicy; - - inline TSmallObjAllocator(IAllocator* alloc) + + inline TSmallObjAllocator(IAllocator* alloc) : Alloc_(sizeof(T), alignof(T), alloc) - { - } - - inline TSmallObjAllocator(IGrowPolicy* grow, IAllocator* alloc) + { + } + + inline TSmallObjAllocator(IGrowPolicy* grow, IAllocator* alloc) : Alloc_(sizeof(T), alignof(T), grow, alloc) - { - } - - inline T* Allocate() { - return (T*)Alloc_.Allocate(); - } - + { + } + + inline T* Allocate() { + return (T*)Alloc_.Allocate(); + } + inline void Release(T* t) noexcept { - Alloc_.Release(t); - } - -private: - TFixedSizeAllocator Alloc_; -}; - -template <class T> -class TObjectFromPool { -public: + Alloc_.Release(t); + } + +private: + TFixedSizeAllocator Alloc_; +}; + +template <class T> +class TObjectFromPool { +public: struct THeader { void* Pool; // Can't just use T because THeader must be standard layout type for offsetof to work. alignas(T) char Obj[sizeof(T)]; }; using TPool = TSmallObjAllocator<THeader>; - - inline void* operator new(size_t, TPool* pool) { + + inline void* operator new(size_t, TPool* pool) { THeader* ret = pool->Allocate(); ret->Pool = pool; return &ret->Obj; - } - + } + inline void operator delete(void* ptr, size_t) noexcept { - DoDelete(ptr); - } - + DoDelete(ptr); + } + inline void operator delete(void* ptr, TPool*) noexcept { - /* - * this delete operator can be called automagically by compiler - */ - - DoDelete(ptr); - } - -private: + /* + * this delete operator can be called automagically by compiler + */ + + DoDelete(ptr); + } + +private: static inline void DoDelete(void* ptr) noexcept { static_assert(std::is_standard_layout<THeader>::value, "offsetof is only defined for standard layout types"); THeader* header = (THeader*)((char*)ptr - offsetof(THeader, Obj)); ((TPool*)header->Pool)->Release(header); - } -}; + } +}; diff --git a/util/memory/smallobj_ut.cpp b/util/memory/smallobj_ut.cpp index ccd4d7e520..86003d1d53 100644 --- a/util/memory/smallobj_ut.cpp +++ b/util/memory/smallobj_ut.cpp @@ -1,33 +1,33 @@ -#include "smallobj.h" - +#include "smallobj.h" + #include <library/cpp/testing/unittest/registar.h> - + #include <util/generic/hash_set.h> - -class TSmallObjAllocTest: public TTestBase { - struct TClass: public TObjectFromPool<TClass> { - char buf[125]; - }; - - struct TErrClass: public TObjectFromPool<TErrClass> { - inline TErrClass(bool t) { - if (t) { - throw 1; - } - } - }; - + +class TSmallObjAllocTest: public TTestBase { + struct TClass: public TObjectFromPool<TClass> { + char buf[125]; + }; + + struct TErrClass: public TObjectFromPool<TErrClass> { + inline TErrClass(bool t) { + if (t) { + throw 1; + } + } + }; + struct TClass64: public TObjectFromPool<TClass64> { alignas(64) ui64 Data = 0; }; - UNIT_TEST_SUITE(TSmallObjAllocTest); + UNIT_TEST_SUITE(TSmallObjAllocTest); UNIT_TEST(TestAlign) UNIT_TEST(TestError) - UNIT_TEST(TestAllocate) - UNIT_TEST_SUITE_END(); - -private: + UNIT_TEST(TestAllocate) + UNIT_TEST_SUITE_END(); + +private: void TestAlign() { TClass64::TPool pool(TDefaultAllocator::Instance()); TClass64* f1 = new (&pool) TClass64; @@ -41,47 +41,47 @@ private: UNIT_ASSERT_VALUES_EQUAL((size_t)0, (size_t)(f4) & (alignof(TClass64) - 1)); } - inline void TestError() { - TErrClass::TPool pool(TDefaultAllocator::Instance()); - TErrClass* f = new (&pool) TErrClass(false); - - delete f; - - bool wasError = false; - - try { - new (&pool) TErrClass(true); - } catch (...) { - wasError = true; - } - - UNIT_ASSERT(wasError); - UNIT_ASSERT_EQUAL(f, new (&pool) TErrClass(false)); - } - - inline void TestAllocate() { - TClass::TPool pool(TDefaultAllocator::Instance()); + inline void TestError() { + TErrClass::TPool pool(TDefaultAllocator::Instance()); + TErrClass* f = new (&pool) TErrClass(false); + + delete f; + + bool wasError = false; + + try { + new (&pool) TErrClass(true); + } catch (...) { + wasError = true; + } + + UNIT_ASSERT(wasError); + UNIT_ASSERT_EQUAL(f, new (&pool) TErrClass(false)); + } + + inline void TestAllocate() { + TClass::TPool pool(TDefaultAllocator::Instance()); THashSet<TClass*> alloced; - - for (size_t i = 0; i < 10000; ++i) { - TClass* c = new (&pool) TClass; - - UNIT_ASSERT_EQUAL(alloced.find(c), alloced.end()); - alloced.insert(c); - } - + + for (size_t i = 0; i < 10000; ++i) { + TClass* c = new (&pool) TClass; + + UNIT_ASSERT_EQUAL(alloced.find(c), alloced.end()); + alloced.insert(c); + } + for (auto it : alloced) { delete it; - } - - for (size_t i = 0; i < 10000; ++i) { - TClass* c = new (&pool) TClass; - - UNIT_ASSERT(alloced.find(c) != alloced.end()); - } - - UNIT_ASSERT_EQUAL(alloced.find(new (&pool) TClass), alloced.end()); - } -}; - -UNIT_TEST_SUITE_REGISTRATION(TSmallObjAllocTest); + } + + for (size_t i = 0; i < 10000; ++i) { + TClass* c = new (&pool) TClass; + + UNIT_ASSERT(alloced.find(c) != alloced.end()); + } + + UNIT_ASSERT_EQUAL(alloced.find(new (&pool) TClass), alloced.end()); + } +}; + +UNIT_TEST_SUITE_REGISTRATION(TSmallObjAllocTest); diff --git a/util/memory/tempbuf.cpp b/util/memory/tempbuf.cpp index 5e6101f429..09a2d0f140 100644 --- a/util/memory/tempbuf.cpp +++ b/util/memory/tempbuf.cpp @@ -1,159 +1,159 @@ -#include "tempbuf.h" -#include "addstorage.h" - -#include <util/system/tls.h> -#include <util/system/yassert.h> +#include "tempbuf.h" +#include "addstorage.h" + +#include <util/system/tls.h> +#include <util/system/yassert.h> #include <util/system/defaults.h> -#include <util/generic/intrlist.h> -#include <util/generic/singleton.h> -#include <util/generic/yexception.h> +#include <util/generic/intrlist.h> +#include <util/generic/singleton.h> +#include <util/generic/yexception.h> #include <utility> -#include <util/thread/singleton.h> - +#include <util/thread/singleton.h> + #ifndef TMP_BUF_LEN - #define TMP_BUF_LEN (64 * 1024) + #define TMP_BUF_LEN (64 * 1024) #endif - -class TTempBuf::TImpl: public TRefCounted<TImpl, TSimpleCounter, TImpl> { -public: + +class TTempBuf::TImpl: public TRefCounted<TImpl, TSimpleCounter, TImpl> { +public: inline TImpl(void* data, size_t size) noexcept - : Data_(data) - , Size_(size) - , Offset_(0) - { - } - - /* - * We do not really need 'virtual' here - * but for compiler happiness... - */ + : Data_(data) + , Size_(size) + , Offset_(0) + { + } + + /* + * We do not really need 'virtual' here + * but for compiler happiness... + */ virtual ~TImpl() = default; - + inline void* Data() noexcept { - return Data_; - } - + return Data_; + } + const void* Data() const noexcept { - return Data_; - } + return Data_; + } inline size_t Size() const noexcept { - return Size_; - } - + return Size_; + } + inline size_t Filled() const noexcept { - return Offset_; - } - + return Offset_; + } + inline void Reset() noexcept { - Offset_ = 0; - } - + Offset_ = 0; + } + inline size_t Left() const noexcept { - return Size() - Filled(); - } - - void SetPos(size_t off) { + return Size() - Filled(); + } + + void SetPos(size_t off) { Y_ASSERT(off <= Size()); - Offset_ = off; - } + Offset_ = off; + } - inline void Proceed(size_t off) { + inline void Proceed(size_t off) { Y_ASSERT(off <= Left()); - - Offset_ += off; - } - + + Offset_ += off; + } + static inline void Destroy(TImpl* This) noexcept { - This->Dispose(); - } - -protected: + This->Dispose(); + } + +protected: virtual void Dispose() noexcept = 0; - -private: - void* Data_; - size_t Size_; - size_t Offset_; -}; - -namespace { - class TTempBufManager; - - class TAllocedBuf: public TTempBuf::TImpl, public TAdditionalStorage<TAllocedBuf> { - public: - inline TAllocedBuf() - : TImpl(AdditionalData(), AdditionalDataLength()) - { - } - + +private: + void* Data_; + size_t Size_; + size_t Offset_; +}; + +namespace { + class TTempBufManager; + + class TAllocedBuf: public TTempBuf::TImpl, public TAdditionalStorage<TAllocedBuf> { + public: + inline TAllocedBuf() + : TImpl(AdditionalData(), AdditionalDataLength()) + { + } + inline ~TAllocedBuf() override = default; - - private: + + private: void Dispose() noexcept override { - delete this; - } - }; - - class TPerThreadedBuf: public TTempBuf::TImpl, public TIntrusiveSListItem<TPerThreadedBuf> { - friend class TTempBufManager; - - public: + delete this; + } + }; + + class TPerThreadedBuf: public TTempBuf::TImpl, public TIntrusiveSListItem<TPerThreadedBuf> { + friend class TTempBufManager; + + public: inline TPerThreadedBuf(TTempBufManager* manager) noexcept - : TImpl(Data_, sizeof(Data_)) - , Manager_(manager) - { - } - + : TImpl(Data_, sizeof(Data_)) + , Manager_(manager) + { + } + inline ~TPerThreadedBuf() override = default; - - private: + + private: void Dispose() noexcept override; - - private: - char Data_[TMP_BUF_LEN]; - TTempBufManager* Manager_; - }; - - class TTempBufManager { - struct TDelete { + + private: + char Data_[TMP_BUF_LEN]; + TTempBufManager* Manager_; + }; + + class TTempBufManager { + struct TDelete { inline void operator()(TPerThreadedBuf* p) noexcept { - delete p; - } - }; - - public: + delete p; + } + }; + + public: inline TTempBufManager() noexcept { - } - + } + inline ~TTempBufManager() { - TDelete deleter; - - Unused_.ForEach(deleter); - } - + TDelete deleter; + + Unused_.ForEach(deleter); + } + inline TPerThreadedBuf* Acquire() { - if (!Unused_.Empty()) { - return Unused_.PopFront(); - } - - return new TPerThreadedBuf(this); - } - + if (!Unused_.Empty()) { + return Unused_.PopFront(); + } + + return new TPerThreadedBuf(this); + } + inline void Return(TPerThreadedBuf* buf) noexcept { - buf->Reset(); - Unused_.PushFront(buf); - } - - private: - TIntrusiveSList<TPerThreadedBuf> Unused_; - }; -} - -static inline TTempBufManager* TempBufManager() { - return FastTlsSingletonWithPriority<TTempBufManager, 2>(); -} - + buf->Reset(); + Unused_.PushFront(buf); + } + + private: + TIntrusiveSList<TPerThreadedBuf> Unused_; + }; +} + +static inline TTempBufManager* TempBufManager() { + return FastTlsSingletonWithPriority<TTempBufManager, 2>(); +} + static inline TTempBuf::TImpl* AcquireSmallBuffer(size_t size) { #if defined(_asan_enabled_) return new (size) TAllocedBuf(); @@ -164,53 +164,53 @@ static inline TTempBuf::TImpl* AcquireSmallBuffer(size_t size) { } void TPerThreadedBuf::Dispose() noexcept { - if (Manager_ == TempBufManager()) { - Manager_->Return(this); - } else { - delete this; - } -} - -TTempBuf::TTempBuf() + if (Manager_ == TempBufManager()) { + Manager_->Return(this); + } else { + delete this; + } +} + +TTempBuf::TTempBuf() : Impl_(AcquireSmallBuffer(TMP_BUF_LEN)) -{ -} - -/* - * all magick is here: - * if len <= TMP_BUF_LEN. then we get prealloced per threaded buffer - * else allocate one in heap - */ -static inline TTempBuf::TImpl* ConstructImpl(size_t len) { - if (len <= TMP_BUF_LEN) { +{ +} + +/* + * all magick is here: + * if len <= TMP_BUF_LEN. then we get prealloced per threaded buffer + * else allocate one in heap + */ +static inline TTempBuf::TImpl* ConstructImpl(size_t len) { + if (len <= TMP_BUF_LEN) { return AcquireSmallBuffer(len); - } - - return new (len) TAllocedBuf(); -} - -TTempBuf::TTempBuf(size_t len) - : Impl_(ConstructImpl(len)) -{ -} - + } + + return new (len) TAllocedBuf(); +} + +TTempBuf::TTempBuf(size_t len) + : Impl_(ConstructImpl(len)) +{ +} + TTempBuf::TTempBuf(const TTempBuf&) noexcept = default; - + TTempBuf::TTempBuf(TTempBuf&& b) noexcept : Impl_(std::move(b.Impl_)) { } TTempBuf::~TTempBuf() = default; - + TTempBuf& TTempBuf::operator=(const TTempBuf& b) noexcept { - if (this != &b) { - Impl_ = b.Impl_; - } - - return *this; -} - + if (this != &b) { + Impl_ = b.Impl_; + } + + return *this; +} + TTempBuf& TTempBuf::operator=(TTempBuf&& b) noexcept { if (this != &b) { Impl_ = std::move(b.Impl_); @@ -220,103 +220,103 @@ TTempBuf& TTempBuf::operator=(TTempBuf&& b) noexcept { } char* TTempBuf::Data() noexcept { - return (char*)Impl_->Data(); -} - + return (char*)Impl_->Data(); +} + const char* TTempBuf::Data() const noexcept { - return static_cast<const char*>(Impl_->Data()); + return static_cast<const char*>(Impl_->Data()); } size_t TTempBuf::Size() const noexcept { - return Impl_->Size(); -} - + return Impl_->Size(); +} + char* TTempBuf::Current() noexcept { - return Data() + Filled(); -} - + return Data() + Filled(); +} + const char* TTempBuf::Current() const noexcept { return Data() + Filled(); } size_t TTempBuf::Filled() const noexcept { - return Impl_->Filled(); -} - + return Impl_->Filled(); +} + size_t TTempBuf::Left() const noexcept { - return Impl_->Left(); -} - + return Impl_->Left(); +} + void TTempBuf::Reset() noexcept { - Impl_->Reset(); -} - + Impl_->Reset(); +} + void TTempBuf::SetPos(size_t off) { Impl_->SetPos(off); } char* TTempBuf::Proceed(size_t off) { char* ptr = Current(); - Impl_->Proceed(off); + Impl_->Proceed(off); return ptr; -} - -void TTempBuf::Append(const void* data, size_t len) { - if (len > Left()) { - ythrow yexception() << "temp buf exhausted(" << Left() << ", " << len << ")"; - } - - memcpy(Current(), data, len); - Proceed(len); -} - +} + +void TTempBuf::Append(const void* data, size_t len) { + if (len > Left()) { + ythrow yexception() << "temp buf exhausted(" << Left() << ", " << len << ")"; + } + + memcpy(Current(), data, len); + Proceed(len); +} + bool TTempBuf::IsNull() const noexcept { return !Impl_; } -#if 0 - #include <util/datetime/cputimer.h> - - #define LEN (1024) - -void* allocaFunc() { - return alloca(LEN); -} - -int main() { - const size_t num = 10000000; - size_t tmp = 0; - - { - CTimer t("alloca"); - - for (size_t i = 0; i < num; ++i) { - tmp += (size_t)allocaFunc(); - } - } - - { - CTimer t("log buffer"); - - for (size_t i = 0; i < num; ++i) { - TTempBuf buf(LEN); - - tmp += (size_t)buf.Data(); - } - } - - { - CTimer t("malloc"); - - for (size_t i = 0; i < num; ++i) { - void* ptr = malloc(LEN); - - tmp += (size_t)ptr; - - free(ptr); - } - } - - return 0; -} -#endif +#if 0 + #include <util/datetime/cputimer.h> + + #define LEN (1024) + +void* allocaFunc() { + return alloca(LEN); +} + +int main() { + const size_t num = 10000000; + size_t tmp = 0; + + { + CTimer t("alloca"); + + for (size_t i = 0; i < num; ++i) { + tmp += (size_t)allocaFunc(); + } + } + + { + CTimer t("log buffer"); + + for (size_t i = 0; i < num; ++i) { + TTempBuf buf(LEN); + + tmp += (size_t)buf.Data(); + } + } + + { + CTimer t("malloc"); + + for (size_t i = 0; i < num; ++i) { + void* ptr = malloc(LEN); + + tmp += (size_t)ptr; + + free(ptr); + } + } + + return 0; +} +#endif diff --git a/util/memory/tempbuf.h b/util/memory/tempbuf.h index 02c376f658..334670eb1e 100644 --- a/util/memory/tempbuf.h +++ b/util/memory/tempbuf.h @@ -1,103 +1,103 @@ #pragma once - + #include <util/system/defaults.h> #include <util/generic/ptr.h> - -/* - * This is really fast buffer for temporary data. - * For small sizes it works almost fast as pure alloca() - * (by using perthreaded list of free blocks), - * for big sizes it works as fast as malloc()/operator new()/... - */ -class TTempBuf { -public: - /* - * we do not want many friends for this class :) - */ - class TImpl; - - TTempBuf(); - TTempBuf(size_t len); + +/* + * This is really fast buffer for temporary data. + * For small sizes it works almost fast as pure alloca() + * (by using perthreaded list of free blocks), + * for big sizes it works as fast as malloc()/operator new()/... + */ +class TTempBuf { +public: + /* + * we do not want many friends for this class :) + */ + class TImpl; + + TTempBuf(); + TTempBuf(size_t len); TTempBuf(const TTempBuf& b) noexcept; TTempBuf(TTempBuf&& b) noexcept; ~TTempBuf(); - + TTempBuf& operator=(const TTempBuf& b) noexcept; TTempBuf& operator=(TTempBuf&& b) noexcept; - - Y_PURE_FUNCTION char* Data() noexcept; - Y_PURE_FUNCTION const char* Data() const noexcept; + Y_PURE_FUNCTION char* Data() noexcept; + + Y_PURE_FUNCTION const char* Data() const noexcept; - Y_PURE_FUNCTION char* Current() noexcept; + Y_PURE_FUNCTION char* Current() noexcept; - Y_PURE_FUNCTION const char* Current() const noexcept; + Y_PURE_FUNCTION const char* Current() const noexcept; - Y_PURE_FUNCTION size_t Size() const noexcept; + Y_PURE_FUNCTION size_t Size() const noexcept; - Y_PURE_FUNCTION size_t Filled() const noexcept; + Y_PURE_FUNCTION size_t Filled() const noexcept; - Y_PURE_FUNCTION size_t Left() const noexcept; + Y_PURE_FUNCTION size_t Left() const noexcept; void Reset() noexcept; - void SetPos(size_t off); + void SetPos(size_t off); char* Proceed(size_t off); - void Append(const void* data, size_t len); - - Y_PURE_FUNCTION bool IsNull() const noexcept; - -private: - TIntrusivePtr<TImpl> Impl_; -}; - -template <typename T> + void Append(const void* data, size_t len); + + Y_PURE_FUNCTION bool IsNull() const noexcept; + +private: + TIntrusivePtr<TImpl> Impl_; +}; + +template <typename T> class TTempArray: private TTempBuf { -private: +private: static T* TypedPointer(char* pointer) noexcept { - return reinterpret_cast<T*>(pointer); - } + return reinterpret_cast<T*>(pointer); + } static const T* TypedPointer(const char* pointer) noexcept { - return reinterpret_cast<const T*>(pointer); - } + return reinterpret_cast<const T*>(pointer); + } static constexpr size_t RawSize(const size_t size) noexcept { - return size * sizeof(T); - } + return size * sizeof(T); + } static constexpr size_t TypedSize(const size_t size) noexcept { - return size / sizeof(T); - } + return size / sizeof(T); + } -public: +public: TTempArray() = default; - TTempArray(size_t len) - : TTempBuf(RawSize(len)) - { - } - + TTempArray(size_t len) + : TTempBuf(RawSize(len)) + { + } + T* Data() noexcept { - return TypedPointer(TTempBuf::Data()); - } + return TypedPointer(TTempBuf::Data()); + } const T* Data() const noexcept { - return TypedPointer(TTempBuf::Data()); - } + return TypedPointer(TTempBuf::Data()); + } T* Current() noexcept { - return TypedPointer(TTempBuf::Current()); - } - + return TypedPointer(TTempBuf::Current()); + } + const T* Current() const noexcept { - return TypedPointer(TTempBuf::Current()); - } + return TypedPointer(TTempBuf::Current()); + } size_t Size() const noexcept { - return TypedSize(TTempBuf::Size()); - } + return TypedSize(TTempBuf::Size()); + } size_t Filled() const noexcept { - return TypedSize(TTempBuf::Filled()); - } - + return TypedSize(TTempBuf::Filled()); + } + T* Proceed(size_t off) { return (T*)TTempBuf::Proceed(RawSize(off)); - } + } }; diff --git a/util/memory/tempbuf_ut.cpp b/util/memory/tempbuf_ut.cpp index 3c6dc5a221..d6bcf9d546 100644 --- a/util/memory/tempbuf_ut.cpp +++ b/util/memory/tempbuf_ut.cpp @@ -1,69 +1,69 @@ -#include "tempbuf.h" - +#include "tempbuf.h" + #include <utility> #include <library/cpp/testing/unittest/registar.h> - -class TTempBufTest: public TTestBase { - UNIT_TEST_SUITE(TTempBufTest); - UNIT_TEST(TestCreate); - UNIT_TEST(TestOps); + +class TTempBufTest: public TTestBase { + UNIT_TEST_SUITE(TTempBufTest); + UNIT_TEST(TestCreate); + UNIT_TEST(TestOps); UNIT_TEST(TestMoveCtor); - UNIT_TEST(TestAppend); + UNIT_TEST(TestAppend); UNIT_TEST(TestProceed); - UNIT_TEST_SUITE_END(); - -public: - void TestCreate(); - void TestOps(); + UNIT_TEST_SUITE_END(); + +public: + void TestCreate(); + void TestOps(); void TestMoveCtor(); void TestProceed(); - - void TestAppend() { - TTempBuf tmp; - - tmp.Append("a", 1); - tmp.Append("bc", 2); - tmp.Append("def", 3); - - UNIT_ASSERT_EQUAL(tmp.Filled(), 6); + + void TestAppend() { + TTempBuf tmp; + + tmp.Append("a", 1); + tmp.Append("bc", 2); + tmp.Append("def", 3); + + UNIT_ASSERT_EQUAL(tmp.Filled(), 6); UNIT_ASSERT_EQUAL(TString(tmp.Data(), tmp.Filled()), "abcdef"); - } -}; - -UNIT_TEST_SUITE_REGISTRATION(TTempBufTest); - -void TTempBufTest::TestCreate() { - const size_t num = 1000000; - size_t tmp = 0; - const size_t len = 4096; - - for (size_t i = 0; i < num; ++i) { - TTempBuf buf(len); - - tmp += (size_t)buf.Data(); - } - - UNIT_ASSERT(tmp != 0); -} - -void TTempBufTest::TestOps() { - TTempBuf tmp(201); - - tmp.Proceed(100); - - UNIT_ASSERT_EQUAL(tmp.Current() - tmp.Data(), 100); - UNIT_ASSERT(tmp.Left() >= 101); - UNIT_ASSERT(tmp.Size() >= 201); - UNIT_ASSERT_EQUAL(tmp.Filled(), 100); - - tmp.Reset(); - - UNIT_ASSERT_EQUAL(tmp.Current(), tmp.Data()); - UNIT_ASSERT(tmp.Left() >= 201); - UNIT_ASSERT(tmp.Size() >= 201); - UNIT_ASSERT_EQUAL(tmp.Filled(), 0); -} + } +}; + +UNIT_TEST_SUITE_REGISTRATION(TTempBufTest); + +void TTempBufTest::TestCreate() { + const size_t num = 1000000; + size_t tmp = 0; + const size_t len = 4096; + + for (size_t i = 0; i < num; ++i) { + TTempBuf buf(len); + + tmp += (size_t)buf.Data(); + } + + UNIT_ASSERT(tmp != 0); +} + +void TTempBufTest::TestOps() { + TTempBuf tmp(201); + + tmp.Proceed(100); + + UNIT_ASSERT_EQUAL(tmp.Current() - tmp.Data(), 100); + UNIT_ASSERT(tmp.Left() >= 101); + UNIT_ASSERT(tmp.Size() >= 201); + UNIT_ASSERT_EQUAL(tmp.Filled(), 100); + + tmp.Reset(); + + UNIT_ASSERT_EQUAL(tmp.Current(), tmp.Data()); + UNIT_ASSERT(tmp.Left() >= 201); + UNIT_ASSERT(tmp.Size() >= 201); + UNIT_ASSERT_EQUAL(tmp.Filled(), 0); +} void TTempBufTest::TestMoveCtor() { TTempBuf src; diff --git a/util/memory/ut/ya.make b/util/memory/ut/ya.make index 2cff8d8cd0..d3a988617d 100644 --- a/util/memory/ut/ya.make +++ b/util/memory/ut/ya.make @@ -1,14 +1,14 @@ -UNITTEST_FOR(util) +UNITTEST_FOR(util) OWNER(g:util) SUBSCRIBER(g:util-subscribers) SRCS( - memory/addstorage_ut.cpp - memory/blob_ut.cpp - memory/pool_ut.cpp - memory/smallobj_ut.cpp - memory/tempbuf_ut.cpp + memory/addstorage_ut.cpp + memory/blob_ut.cpp + memory/pool_ut.cpp + memory/smallobj_ut.cpp + memory/tempbuf_ut.cpp ) INCLUDE(${ARCADIA_ROOT}/util/tests/ya_util_tests.inc) |