123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026 |
- #ifndef COMPACT_VECTOR_INL_H_
- #error "Direct inclusion of this file is not allowed, include compact_vector.h"
- // For the sake of sane code completion.
- #include "compact_vector.h"
- #endif
- #undef COMPACT_VECTOR_INL_H_
- #include <library/cpp/yt/assert/assert.h>
- #include <library/cpp/yt/malloc/malloc.h>
- #include <library/cpp/yt/misc/hash.h>
- #include <util/system/compiler.h>
- #include <algorithm>
- #include <bit>
- #include <string.h>
- namespace NYT {
- ////////////////////////////////////////////////////////////////////////////////
- static_assert(sizeof(uintptr_t) == 8);
- static_assert(std::endian::native == std::endian::little);
- ////////////////////////////////////////////////////////////////////////////////
- template <class T>
- struct TCompactVectorOnHeapStorage
- {
- T* End;
- T* Capacity;
- T Elements[0];
- };
- ////////////////////////////////////////////////////////////////////////////////
- template <class TVector, class TPtr>
- class TCompactVectorReallocationPtrAdjuster
- {
- public:
- TCompactVectorReallocationPtrAdjuster(TVector* vector, TPtr& ptr)
- : Vector_(vector)
- , Ptr_(ptr)
- , Index_(ptr >= Vector_->begin() && ptr <= Vector_->end()
- ? std::distance(Vector_->begin(), const_cast<typename TVector::iterator>(ptr))
- : -1)
- { }
- ~TCompactVectorReallocationPtrAdjuster()
- {
- if (Index_ >= 0) {
- Ptr_ = Vector_->begin() + Index_;
- }
- }
- private:
- TVector* const Vector_;
- TPtr& Ptr_;
- const ptrdiff_t Index_;
- };
- template <class TVector>
- class TCompactVectorReallocationPtrAdjuster<TVector, std::nullptr_t>
- {
- public:
- TCompactVectorReallocationPtrAdjuster(TVector* /*vector*/, std::nullptr_t /*ptr*/)
- { }
- };
- ////////////////////////////////////////////////////////////////////////////////
- template <class T, size_t N>
- TCompactVector<T, N>::TCompactVector() noexcept
- {
- InlineMeta_.SizePlusOne = 1;
- }
- template <class T, size_t N>
- TCompactVector<T, N>::TCompactVector(const TCompactVector& other)
- : TCompactVector()
- {
- assign(other.begin(), other.end());
- }
- template <class T, size_t N>
- template <size_t OtherN>
- TCompactVector<T, N>::TCompactVector(const TCompactVector<T, OtherN>& other)
- : TCompactVector()
- {
- assign(other.begin(), other.end());
- }
- template <class T, size_t N>
- TCompactVector<T, N>::TCompactVector(TCompactVector&& other) noexcept(std::is_nothrow_move_constructible_v<T>)
- : TCompactVector()
- {
- swap(other);
- }
- template <class T, size_t N>
- template <size_t OtherN>
- TCompactVector<T, N>::TCompactVector(TCompactVector<T, OtherN>&& other)
- : TCompactVector()
- {
- swap(other);
- }
- template <class T, size_t N>
- TCompactVector<T, N>::TCompactVector(size_type count)
- : TCompactVector()
- {
- assign(count, T());
- }
- template <class T, size_t N>
- TCompactVector<T, N>::TCompactVector(size_type count, const T& value)
- : TCompactVector()
- {
- assign(count, value);
- }
- template <class T, size_t N>
- template <class TIterator>
- TCompactVector<T, N>::TCompactVector(TIterator first, TIterator last)
- : TCompactVector()
- {
- assign(first, last);
- }
- template <class T, size_t N>
- TCompactVector<T, N>::TCompactVector(std::initializer_list<T> list)
- : TCompactVector()
- {
- assign(list.begin(), list.end());
- }
- template <class T, size_t N>
- TCompactVector<T, N>::~TCompactVector()
- {
- if (Y_LIKELY(IsInline())) {
- Destroy(&InlineElements_[0], &InlineElements_[InlineMeta_.SizePlusOne - 1]);
- } else {
- auto* storage = OnHeapMeta_.Storage;
- Destroy(storage->Elements, storage->End);
- ::free(storage);
- }
- }
- template <class T, size_t N>
- bool TCompactVector<T, N>::empty() const
- {
- if (Y_LIKELY(IsInline())) {
- return InlineMeta_.SizePlusOne == 1;
- } else {
- const auto* storage = OnHeapMeta_.Storage;
- return storage->Elements == storage->End;
- }
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::begin() -> iterator
- {
- return Y_LIKELY(IsInline()) ? &InlineElements_[0] : OnHeapMeta_.Storage->Elements;
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::begin() const -> const_iterator
- {
- return const_cast<TCompactVector*>(this)->begin();
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::end() -> iterator
- {
- return Y_LIKELY(IsInline()) ? &InlineElements_[InlineMeta_.SizePlusOne - 1] : OnHeapMeta_.Storage->End;
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::end() const -> const_iterator
- {
- return const_cast<TCompactVector*>(this)->end();
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::rbegin() -> reverse_iterator
- {
- return static_cast<reverse_iterator>(end());
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::rbegin() const -> const_reverse_iterator
- {
- return static_cast<const_reverse_iterator>(end());
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::rend() -> reverse_iterator
- {
- return static_cast<reverse_iterator>(begin());
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::rend() const -> const_reverse_iterator
- {
- return static_cast<const_reverse_iterator>(begin());
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::size() const -> size_type
- {
- if (Y_LIKELY(IsInline())) {
- return InlineMeta_.SizePlusOne - 1;
- } else {
- const auto* storage = OnHeapMeta_.Storage;
- return storage->End - storage->Elements;
- }
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::capacity() const -> size_type
- {
- if (Y_LIKELY(IsInline())) {
- return N;
- } else {
- const auto* storage = OnHeapMeta_.Storage;
- return storage->Capacity - storage->Elements;
- }
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::max_size() const -> size_type
- {
- return static_cast<size_type>(-1) / sizeof(T);
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::data() -> pointer
- {
- return static_cast<pointer>(begin());
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::data() const -> const_pointer
- {
- return static_cast<const_pointer>(begin());
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::operator[](size_type index) -> reference
- {
- YT_ASSERT(index < size());
- return begin()[index];
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::operator[](size_type index) const -> const_reference
- {
- return const_cast<TCompactVector*>(this)->operator[](index);
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::front() -> reference
- {
- YT_ASSERT(!empty());
- return begin()[0];
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::front() const -> const_reference
- {
- return const_cast<TCompactVector*>(this)->front();
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::back() -> reference
- {
- YT_ASSERT(!empty());
- return end()[-1];
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::back() const -> const_reference
- {
- return const_cast<TCompactVector*>(this)->back();
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::push_back(const T& value)
- {
- PushBackImpl(
- &value,
- [&] (T* dst, const T* value) {
- ::new(dst) T(*value);
- });
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::push_back(T&& value)
- {
- PushBackImpl(
- &value,
- [&] (T* dst, T* value) {
- ::new(dst) T(std::move(*value));
- });
- }
- template <class T, size_t N>
- template <class... TArgs>
- auto TCompactVector<T, N>::emplace(const_iterator pos, TArgs&&... args) -> iterator
- {
- return InsertOneImpl(
- pos,
- nullptr,
- [&] (auto* dst, std::nullptr_t) {
- ::new(dst) T(std::forward<TArgs>(args)...);
- },
- [&] (auto* dst, std::nullptr_t) {
- *dst = T(std::forward<TArgs>(args)...);
- });
- }
- template <class T, size_t N>
- template <class... TArgs>
- auto TCompactVector<T, N>::emplace_back(TArgs&&... args) -> reference
- {
- return PushBackImpl(
- nullptr,
- [&] (T* dst, std::nullptr_t) {
- ::new(dst) T(std::forward<TArgs>(args)...);
- });
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::pop_back()
- {
- YT_ASSERT(!empty());
- if (Y_LIKELY(IsInline())) {
- InlineElements_[InlineMeta_.SizePlusOne - 2].T::~T();
- --InlineMeta_.SizePlusOne;
- } else {
- auto* storage = OnHeapMeta_.Storage;
- storage->End[-1].T::~T();
- --storage->End;
- }
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::erase(const_iterator pos) -> iterator
- {
- YT_ASSERT(pos >= begin());
- YT_ASSERT(pos < end());
- auto* mutablePos = const_cast<iterator>(pos);
- Move(mutablePos + 1, end(), mutablePos);
- pop_back();
- return mutablePos;
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::erase(const_iterator first, const_iterator last) -> iterator
- {
- YT_ASSERT(first >= begin());
- YT_ASSERT(last <= end());
- auto* mutableFirst = const_cast<iterator>(first);
- auto* mutableLast = const_cast<iterator>(last);
- auto count = std::distance(mutableFirst, mutableLast);
- if (Y_LIKELY(IsInline())) {
- auto* end = &InlineElements_[0] + InlineMeta_.SizePlusOne - 1;
- Move(mutableLast, end, mutableFirst);
- Destroy(end - count, end);
- InlineMeta_.SizePlusOne -= count;
- } else {
- auto* storage = OnHeapMeta_.Storage;
- auto* end = storage->End;
- Move(mutableLast, storage->End, mutableFirst);
- Destroy(end - count, end);
- storage->End -= count;
- }
- return mutableFirst;
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::clear()
- {
- if (Y_LIKELY(IsInline())) {
- Destroy(&InlineElements_[0], &InlineElements_[InlineMeta_.SizePlusOne - 1]);
- InlineMeta_.SizePlusOne = 1;
- } else {
- auto* storage = OnHeapMeta_.Storage;
- Destroy(storage->Elements, storage->End);
- storage->End = storage->Elements;
- }
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::resize(size_type newSize)
- {
- ResizeImpl(
- newSize,
- [] (auto* dst) {
- ::new(dst) T();
- });
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::resize(size_type newSize, const T& value)
- {
- ResizeImpl(
- newSize,
- [&] (auto* dst) {
- ::new(dst) T(value);
- });
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::reserve(size_t newCapacity)
- {
- if (Y_UNLIKELY(newCapacity > N)) {
- EnsureOnHeapCapacity(newCapacity, /*incremental*/ false);
- }
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::swap(TCompactVector& other)
- {
- if (this == &other) {
- return;
- }
- if (!IsInline() && !other.IsInline()) {
- std::swap(OnHeapMeta_.Storage, other.OnHeapMeta_.Storage);
- return;
- }
- auto* lhs = this;
- auto* rhs = &other;
- if (lhs->size() < rhs->size()) {
- std::swap(lhs, rhs);
- }
- size_t rhsSize = rhs->size();
- size_t lhsSize = lhs->size();
- if (lhsSize > rhs->capacity()) {
- rhs->EnsureOnHeapCapacity(lhs->size(), /*incremental*/ false);
- }
- for (size_t index = 0; index < rhsSize; ++index) {
- std::swap((*lhs)[index], (*rhs)[index]);
- }
- UninitializedMove(lhs->begin() + rhsSize, lhs->end(), rhs->end());
- Destroy(lhs->begin() + rhsSize, lhs->end());
- rhs->SetSize(lhsSize);
- lhs->SetSize(rhsSize);
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::assign(size_type count, const T& value)
- {
- clear();
- if (Y_UNLIKELY(count > capacity())) {
- EnsureOnHeapCapacity(count, /*incremental*/ false);
- }
- auto* dst = begin();
- std::uninitialized_fill(dst, dst + count, value);
- SetSize(count);
- }
- template <class T, size_t N>
- template <class TIterator>
- void TCompactVector<T, N>::assign(TIterator first, TIterator last)
- {
- clear();
- auto count = std::distance(first, last);
- if (Y_UNLIKELY(count > static_cast<ptrdiff_t>(capacity()))) {
- EnsureOnHeapCapacity(count, /*incremental*/ false);
- }
- std::uninitialized_copy(first, last, begin());
- SetSize(count);
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::assign(std::initializer_list<T> list)
- {
- assign(list.begin(), list.end());
- }
- template <class T, size_t N>
- template <size_t OtherN>
- void TCompactVector<T, N>::assign(const TCompactVector<T, OtherN>& other)
- {
- if constexpr(N == OtherN) {
- if (this == &other) {
- return;
- }
- }
- auto otherSize = other.size();
- auto otherBegin = other.begin();
- if (capacity() >= otherSize) {
- const auto* src = other.begin();
- auto* dst = begin();
- auto thisSize = size();
- auto copySize = std::min(thisSize, otherSize);
- Copy(src, src + copySize, dst);
- src += copySize;
- dst += copySize;
- auto uninitializedCopySize = otherSize - copySize;
- UninitializedCopy(src, src + uninitializedCopySize, dst);
- // NB: src += uninitializedCopySize is not needed.
- dst += uninitializedCopySize;
- if (thisSize > otherSize) {
- Destroy(dst, end());
- }
- SetSize(otherSize);
- return;
- }
- clear();
- EnsureOnHeapCapacity(otherSize, /*incremental*/ false);
- YT_ASSERT(!IsInline());
- auto* storage = OnHeapMeta_.Storage;
- UninitializedCopy(otherBegin, otherBegin + otherSize, storage->Elements);
- storage->End = storage->Elements + otherSize;
- }
- template <class T, size_t N>
- template <size_t OtherN>
- void TCompactVector<T, N>::assign(TCompactVector<T, OtherN>&& other)
- {
- if constexpr(N == OtherN) {
- if (this == &other) {
- return;
- }
- }
- clear();
- if (!other.IsInline()) {
- if (Y_UNLIKELY(!IsInline())) {
- ::free(OnHeapMeta_.Storage);
- }
- OnHeapMeta_.Storage = other.OnHeapMeta_.Storage;
- other.InlineMeta_.SizePlusOne = 1;
- return;
- }
- auto otherSize = other.size();
- if (Y_UNLIKELY(otherSize > capacity())) {
- EnsureOnHeapCapacity(otherSize, /*incremental*/ false);
- }
- auto* otherBegin = other.begin();
- UninitializedMove(otherBegin, otherBegin + otherSize, begin());
- SetSize(otherSize);
- other.clear();
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::operator=(const TCompactVector& other) -> TCompactVector&
- {
- assign(other);
- return *this;
- }
- template <class T, size_t N>
- template <size_t OtherN>
- auto TCompactVector<T, N>::operator=(const TCompactVector<T, OtherN>& other) -> TCompactVector&
- {
- assign(other);
- return *this;
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::operator=(TCompactVector&& other) -> TCompactVector&
- {
- assign(std::move(other));
- return *this;
- }
- template <class T, size_t N>
- template <size_t OtherN>
- auto TCompactVector<T, N>::operator=(TCompactVector<T, OtherN>&& other) -> TCompactVector&
- {
- assign(std::move(other));
- return *this;
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::operator=(std::initializer_list<T> list) -> TCompactVector&
- {
- assign(list);
- return *this;
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::insert(const_iterator pos, const T& value) -> iterator
- {
- return InsertOneImpl(
- pos,
- &value,
- [&] (auto* dst, const auto* value) {
- ::new(dst) T(*value);
- },
- [&] (auto* dst, const auto* value) {
- *dst = *value;
- });
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::insert(const_iterator pos, T&& value) -> iterator
- {
- return InsertOneImpl(
- pos,
- &value,
- [&] (auto* dst, auto* value) {
- ::new(dst) T(std::move(*value));
- },
- [&] (auto* dst, auto* value) {
- *dst = std::move(*value);
- });
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::insert(const_iterator pos, size_type count, const T& value) -> iterator
- {
- return InsertManyImpl(
- pos,
- count,
- [&] (auto* dstFirst, auto* dstLast) {
- for (auto* dst = dstFirst; dst != dstLast; ++dst) {
- ::new(dst) T(value);
- }
- },
- [&] (auto* dstFirst, auto* dstLast) {
- for (auto* dst = dstFirst; dst != dstLast; ++dst) {
- *dst = value;
- }
- });
- }
- template <class T, size_t N>
- template <class TIterator>
- auto TCompactVector<T, N>::insert(const_iterator pos, TIterator first, TIterator last) -> iterator
- {
- auto current = first;
- return InsertManyImpl(
- pos,
- std::distance(first, last),
- [&] (auto* dstFirst, auto* dstLast) {
- for (auto* dst = dstFirst; dst != dstLast; ++dst) {
- ::new(dst) T(*current++);
- }
- },
- [&] (auto* dstFirst, auto* dstLast) {
- for (auto* dst = dstFirst; dst != dstLast; ++dst) {
- *dst = *current++;
- }
- });
- }
- template <class T, size_t N>
- auto TCompactVector<T, N>::insert(const_iterator pos, std::initializer_list<T> list) -> iterator
- {
- return insert(pos, list.begin(), list.end());
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::shrink_to_small()
- {
- if (Y_LIKELY(IsInline())) {
- return;
- }
- auto size = this->size();
- if (size > N) {
- return;
- }
- auto* storage = OnHeapMeta_.Storage;
- UninitializedMove(storage->Elements, storage->End, &InlineElements_[0]);
- Destroy(storage->Elements, storage->End);
- ::free(storage);
- InlineMeta_.SizePlusOne = size + 1;
- }
- template <class T, size_t N>
- bool TCompactVector<T, N>::IsInline() const
- {
- return InlineMeta_.SizePlusOne != 0;
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::SetSize(size_t newSize)
- {
- if (Y_LIKELY(IsInline())) {
- InlineMeta_.SizePlusOne = newSize + 1;
- } else {
- auto* storage = OnHeapMeta_.Storage;
- storage->End = storage->Elements + newSize;
- }
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::EnsureOnHeapCapacity(size_t newCapacity, bool incremental)
- {
- newCapacity = std::max(newCapacity, N + 1);
- if (incremental) {
- newCapacity = std::max(newCapacity, capacity() * 2);
- }
- auto byteSize = sizeof(TOnHeapStorage) + newCapacity * sizeof(T);
- byteSize = nallocx(byteSize, 0);
- newCapacity = (byteSize - sizeof(TOnHeapStorage)) / sizeof(T);
- auto* newStorage = static_cast<TOnHeapStorage*>(::malloc(byteSize));
- YT_VERIFY((reinterpret_cast<uintptr_t>(newStorage) >> 56) == 0);
- newStorage->Capacity = newStorage->Elements + newCapacity;
- size_t size;
- if (IsInline()) {
- size = InlineMeta_.SizePlusOne - 1;
- UninitializedMove(&InlineElements_[0], &InlineElements_[0] + size, newStorage->Elements);
- Destroy(&InlineElements_[0], &InlineElements_[0] + size);
- } else {
- auto* storage = OnHeapMeta_.Storage;
- size = storage->End - storage->Elements;
- UninitializedMove(storage->Elements, storage->End, newStorage->Elements);
- Destroy(storage->Elements, storage->End);
- ::free(storage);
- }
- newStorage->End = newStorage->Elements + size;
- OnHeapMeta_.Storage = newStorage;
- }
- template <class T, size_t N>
- template <class TPtr, class F>
- auto TCompactVector<T, N>::PushBackImpl(TPtr valuePtr, F&& func) -> reference
- {
- auto sizePlusOne = InlineMeta_.SizePlusOne;
- if (Y_LIKELY(sizePlusOne != 0 && sizePlusOne != N + 1)) {
- auto* dst = &InlineElements_[sizePlusOne - 1];
- func(dst, valuePtr);
- ++InlineMeta_.SizePlusOne;
- return *dst;
- }
- auto hasSpareOnHeapCapacity = [&] {
- if (sizePlusOne != 0) {
- return false;
- }
- auto* storage = OnHeapMeta_.Storage;
- return storage->End < storage->Capacity;
- };
- if (Y_UNLIKELY(!hasSpareOnHeapCapacity())) {
- TCompactVectorReallocationPtrAdjuster<TCompactVector, TPtr> valuePtrAdjuster(this, valuePtr);
- EnsureOnHeapCapacity(0, /*incremental*/ true);
- }
- YT_ASSERT(!IsInline());
- auto* storage = OnHeapMeta_.Storage;
- auto* dst = storage->End++;
- func(dst, valuePtr);
- return *dst;
- }
- template <class T, size_t N>
- template <class F>
- void TCompactVector<T, N>::ResizeImpl(size_type newSize, F&& func)
- {
- auto size = this->size();
- if (newSize > size) {
- if (Y_UNLIKELY(newSize > capacity())) {
- EnsureOnHeapCapacity(newSize, /*incremental*/ false);
- }
- auto* first = end();
- auto* last = first + newSize - size;
- for (auto* current = first; current != last; ++current) {
- func(current);
- }
- } else if (newSize < size) {
- Destroy(begin() + newSize, end());
- }
- SetSize(newSize);
- }
- template <class T, size_t N>
- template <class TPtr, class UninitializedF, class InitializedF>
- auto TCompactVector<T, N>::InsertOneImpl(const_iterator pos, TPtr valuePtr, UninitializedF&& uninitializedFunc, InitializedF&& initializedFunc) -> iterator
- {
- YT_ASSERT(pos >= begin());
- YT_ASSERT(pos <= end());
- auto* mutablePos = const_cast<iterator>(pos);
- auto newSize = size() + 1;
- if (Y_UNLIKELY(newSize > capacity())) {
- TCompactVectorReallocationPtrAdjuster<TCompactVector, iterator> mutablePosAdjuster(this, mutablePos);
- TCompactVectorReallocationPtrAdjuster<TCompactVector, TPtr> valuePtrAdjuster(this, valuePtr);
- EnsureOnHeapCapacity(newSize, /*incremental*/ true);
- }
- auto* end = this->end();
- if constexpr(!std::is_same_v<TPtr, std::nullptr_t>) {
- if (valuePtr >= mutablePos && valuePtr < end) {
- ++valuePtr;
- }
- }
- auto moveCount = std::distance(mutablePos, end);
- if (moveCount == 0) {
- uninitializedFunc(end, valuePtr);
- } else {
- if constexpr(std::is_trivially_copyable_v<T>) {
- ::memmove(mutablePos + 1, mutablePos, moveCount * sizeof(T));
- } else {
- ::new(end) T(std::move(end[-1]));
- MoveBackward(mutablePos, end - 1, mutablePos + 1);
- }
- initializedFunc(mutablePos, valuePtr);
- }
- SetSize(newSize);
- return mutablePos;
- }
- template <class T, size_t N>
- template <class UninitializedF, class InitializedF>
- auto TCompactVector<T, N>::InsertManyImpl(const_iterator pos, size_t insertCount, UninitializedF&& uninitializedFunc, InitializedF&& initializedFunc) -> iterator
- {
- YT_ASSERT(pos >= begin());
- YT_ASSERT(pos <= end());
- auto* mutablePos = const_cast<iterator>(pos);
- if (insertCount == 0) {
- return mutablePos;
- }
- auto size = this->size();
- auto newSize = size + insertCount;
- if (Y_UNLIKELY(newSize > capacity())) {
- auto index = std::distance(begin(), mutablePos);
- EnsureOnHeapCapacity(newSize, /*incremental*/ true);
- mutablePos = begin() + index;
- }
- auto* end = this->end();
- auto moveCount = std::distance(mutablePos, end);
- if constexpr(std::is_trivially_copyable_v<T>) {
- ::memmove(mutablePos + insertCount, mutablePos, moveCount * sizeof(T));
- initializedFunc(mutablePos, mutablePos + insertCount);
- } else {
- if (static_cast<ptrdiff_t>(insertCount) >= moveCount) {
- UninitializedMove(mutablePos, end, mutablePos + insertCount);
- initializedFunc(mutablePos, end);
- uninitializedFunc(end, end + insertCount - moveCount);
- } else {
- auto overlapCount = moveCount - insertCount;
- UninitializedMove(mutablePos + overlapCount, end, mutablePos + overlapCount + insertCount);
- MoveBackward(mutablePos, mutablePos + overlapCount, mutablePos + insertCount);
- initializedFunc(mutablePos, mutablePos + insertCount);
- }
- }
- SetSize(newSize);
- return mutablePos;
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::Destroy(T* first, T* last)
- {
- if constexpr(!std::is_trivially_destructible_v<T>) {
- for (auto* current = first; current != last; ++current) {
- current->T::~T();
- }
- }
- }
- template <class T, size_t N>
- template <class T1, class T2>
- void TCompactVector<T, N>::Copy(const T1* srcFirst, const T1* srcLast, T2* dst)
- {
- if constexpr(std::is_trivially_copyable_v<T1> && std::is_same_v<T1, T2>) {
- ::memcpy(dst, srcFirst, (srcLast - srcFirst) * sizeof(T));
- } else {
- std::copy(srcFirst, srcLast, dst);
- }
- }
- template <class T, size_t N>
- template <class T1, class T2>
- void TCompactVector<T, N>::UninitializedCopy(const T1* srcFirst, const T1* srcLast, T2* dst)
- {
- if constexpr(std::is_trivially_copyable_v<T1> && std::is_same_v<T1, T2>) {
- ::memcpy(dst, srcFirst, (srcLast - srcFirst) * sizeof(T));
- } else {
- std::uninitialized_copy(srcFirst, srcLast, dst);
- }
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::Move(T* srcFirst, T* srcLast, T* dst)
- {
- if constexpr(std::is_trivially_copyable_v<T>) {
- ::memmove(dst, srcFirst, (srcLast - srcFirst) * sizeof(T));
- } else {
- std::move(srcFirst, srcLast, dst);
- }
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::UninitializedMove(T* srcFirst, T* srcLast, T* dst)
- {
- if constexpr(std::is_trivially_copyable_v<T>) {
- ::memcpy(dst, srcFirst, (srcLast - srcFirst) * sizeof(T));
- } else {
- std::uninitialized_move(srcFirst, srcLast, dst);
- }
- }
- template <class T, size_t N>
- void TCompactVector<T, N>::MoveBackward(T* srcFirst, T* srcLast, T* dst)
- {
- auto* src = srcLast;
- dst += std::distance(srcFirst, srcLast);
- while (src > srcFirst) {
- *--dst = std::move(*--src);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- template <class T, size_t LhsN, size_t RhsN>
- bool operator==(const TCompactVector<T, LhsN>& lhs, const TCompactVector<T, RhsN>& rhs)
- {
- if constexpr(LhsN == RhsN) {
- if (&lhs == &rhs) {
- return true;
- }
- }
- if (lhs.size() != rhs.size()) {
- return false;
- }
- return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
- }
- template <class T, size_t LhsN, size_t RhsN>
- bool operator!=(const TCompactVector<T, LhsN>& lhs, const TCompactVector<T, RhsN>& rhs)
- {
- return !(lhs == rhs);
- }
- template <class T, size_t LhsN, size_t RhsN>
- bool operator<(const TCompactVector<T, LhsN>& lhs, const TCompactVector<T, RhsN>& rhs)
- {
- return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
- }
- ////////////////////////////////////////////////////////////////////////////////
- template <class T, size_t N>
- void swap(TCompactVector<T, N>& lhs, TCompactVector<T, N>& rhs) // NOLINT
- {
- lhs.swap(rhs);
- }
- /////////////////////////////////////////////////////////////////////////////
- } // namespace NYT
- namespace std {
- ////////////////////////////////////////////////////////////////////////////////
- template <class T, size_t N>
- struct hash<NYT::TCompactVector<T, N>>
- {
- size_t operator()(const NYT::TCompactVector<T, N>& container) const
- {
- size_t result = 0;
- for (const auto& element : container) {
- NYT::HashCombine(result, element);
- }
- return result;
- }
- };
- ////////////////////////////////////////////////////////////////////////////////
- } // namespace std
|