123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- #pragma once
- #include <yql/essentials/minikql/defs.h>
- #include <yql/essentials/minikql/mkql_alloc.h>
- #include <yql/essentials/public/udf/udf_value.h>
- namespace NKikimr {
- namespace NMiniKQL {
- template <typename T>
- struct TListChunk {
- private:
- using TSelf = TListChunk<T>;
- static void PlacementNew(T* ptr, ui64 count) {
- T* end = ptr + count;
- for (; ptr != end; ptr++) {
- new (ptr) T;
- }
- }
- public:
- void CheckMagic() {
- Y_DEBUG_ABORT_UNLESS(Magic_ == TListChunkMagic);
- }
- static TSelf* AllocateChunk(ui64 length) {
- const auto block = TWithDefaultMiniKQLAlloc::AllocWithSize(length * sizeof(T) + sizeof(TListChunk));
- const auto ptr = new (block) TListChunk(length);
- PlacementNew(reinterpret_cast<T*>(ptr + 1), length);
- return ptr;
- }
- TListChunk(ui64 size)
- : Magic_(TListChunkMagic)
- , Refs_(1)
- , DataEnd_(DataBegin() + size)
- {
- }
- ~TListChunk() {
- CheckMagic();
- for (auto it = DataBegin(); it != DataEnd(); it++) {
- it->~T();
- }
- TWithDefaultMiniKQLAlloc::FreeWithSize(
- static_cast<void*>(this), sizeof(TListChunk) + sizeof(T) * (DataEnd() - DataBegin()));
- }
- inline T* DataBegin() {
- CheckMagic();
- return reinterpret_cast<T*>(this + 1);
- }
- inline const T* DataEnd() {
- CheckMagic();
- return DataEnd_;
- }
- ui64 Size() {
- CheckMagic();
- return DataEnd() - DataBegin();
- }
- void Ref() {
- CheckMagic();
- Refs_++;
- }
- void UnRef() {
- CheckMagic();
- if (--Refs_ == 0) {
- this->~TListChunk();
- }
- }
- private:
- static const ui32 TListChunkMagic = 12322846;
- const ui32 Magic_;
- ui32 Refs_;
- const T* DataEnd_;
- };
- template <typename T, ui64 MinChunkSize = 48>
- class TListRepresentation {
- public:
- using TSelf = TListRepresentation<T, MinChunkSize>;
- using TChunk = TListChunk<T>;
- private:
- enum Type {
- Normal,
- Freezed
- };
- void NewNormal(const T* begin1, const T* end1, const T* begin2, const T* end2) {
- Type_ = Type::Normal;
- ui64 oldLength = (end1 - begin1) + (end2 - begin2);
- ui64 newLength = std::max((oldLength << 1) - 1, (MinChunkSize + sizeof(T) - 1) / sizeof(T) + 1);
- Chunk_ = TChunk::AllocateChunk(newLength);
- Begin_ = Chunk_->DataBegin() + ((newLength - oldLength) >> 2);
- End_ = std::copy(begin2, end2, std::copy(begin1, end1, Begin_));
- }
- TListRepresentation(TChunk* chunk, T* begin, T* end, Type type)
- : Chunk_(chunk)
- , Begin_(begin)
- , End_(end)
- , Type_(type)
- {
- if (Chunk_) {
- Chunk_->Ref();
- }
- }
- TListRepresentation(T* begin1, T* end1, T* begin2, T* end2)
- {
- NewNormal(begin1, end1, begin2, end2);
- }
- public:
- struct TIterator {
- TIterator()
- : Owner_(nullptr)
- , Position_(nullptr)
- {}
- TIterator(const TListRepresentation& owner)
- : Owner_(&owner)
- , Position_(owner.Begin_)
- {
- }
- TIterator(const TIterator& other)
- : Owner_(other.Owner_)
- , Position_(other.Position_)
- {}
- TIterator& operator=(const TIterator& other)
- {
- Owner_ = other.Owner_;
- Position_ = other.Position_;
- return *this;
- }
- bool AtEnd() const {
- return Position_ == Owner_->End_;
- }
- const T& Current() const {
- return *Position_;
- }
- // use with care, list may be shared
- T& MutableCurrent() {
- return *Position_;
- }
- void Next() {
- Position_++;
- }
- const TListRepresentation* Owner_;
- T* Position_;
- };
- struct TReverseIterator {
- TReverseIterator()
- : Owner_(nullptr)
- , Position_(nullptr)
- {
- }
- TReverseIterator(const TListRepresentation& owner)
- : Owner_(&owner)
- , Position_(owner.End_)
- {
- }
- TReverseIterator(const TIterator& other)
- : Owner_(other.Owner_)
- , Position_(other.Position_)
- {
- }
- TReverseIterator& operator=(const TReverseIterator& other)
- {
- Owner_ = other.Owner_;
- Position_ = other.Position_;
- return *this;
- }
- bool AtEnd() const {
- return Position_ == Owner_->Begin_;
- }
- const T& Current() const {
- return *(Position_ - 1);
- }
- // use with care, list may be shared
- T& MutableCurrent() {
- return *(Position_ - 1);
- }
- void Next() {
- Position_--;
- }
- private:
- const TListRepresentation* Owner_;
- T* Position_;
- };
- TListRepresentation()
- : Chunk_(nullptr)
- , Begin_(nullptr)
- , End_(nullptr)
- , Type_(Type::Freezed)
- {
- }
- ~TListRepresentation() {
- if (Chunk_) {
- Chunk_->UnRef();
- }
- }
- TListRepresentation(const TSelf& other)
- : Chunk_(other.Chunk_)
- , Begin_(other.Begin_)
- , End_(other.End_)
- , Type_(other.Type_)
- {
- other.Type_ = Type::Freezed;
- if (Chunk_) {
- Chunk_->Ref();
- }
- }
- TListRepresentation(TSelf&& other)
- : Chunk_(other.Chunk_)
- , Begin_(other.Begin_)
- , End_(other.End_)
- , Type_(other.Type_)
- {
- other.Chunk_ = nullptr;
- other.Begin_ = nullptr;
- other.End_ = nullptr;
- other.Type_ = Type::Freezed;
- }
- void operator=(const TSelf& other) {
- if (this != &other) {
- if (other.Chunk_) {
- other.Chunk_->Ref();
- }
- if (Chunk_) {
- Chunk_->UnRef();
- }
- Chunk_ = other.Chunk_;
- Begin_ = other.Begin_;
- End_ = other.End_;
- Type_ = other.Type_;
- other.Type_ = Type::Freezed;
- }
- }
- void operator=(TSelf&& other) {
- if (Chunk_) {
- Chunk_->UnRef();
- }
- Chunk_ = other.Chunk_;
- Begin_ = other.Begin_;
- End_ = other.End_;
- Type_ = other.Type_;
- other.Chunk_ = nullptr;
- other.Begin_ = nullptr;
- other.End_ = nullptr;
- other.Type_ = Type::Freezed;
- }
- inline void FromSingleElement(T&& element) {
- Type_ = Type::Normal;
- ui64 chunkLength = (MinChunkSize + sizeof(T) - 1) / sizeof(T);
- Chunk_ = TChunk::AllocateChunk(chunkLength);
- Begin_ = Chunk_->DataBegin() + (chunkLength >> 2);
- End_ = Begin_ + 1;
- *Begin_ = std::move(element);
- }
- TListRepresentation(T&& element)
- {
- FromSingleElement(std::move(element));
- }
- TListRepresentation(T&& element, const TSelf& that)
- {
- if (!that.Chunk_) {
- FromSingleElement(std::move(element));
- return;
- }
- if ((that.Type_ == Type::Normal) && (that.Begin_ != that.Chunk_->DataBegin())) {
- Type_ = Type::Normal;
- that.Type_ = Type::Freezed;
- Chunk_ = that.Chunk_;
- Chunk_->Ref();
- Begin_ = that.Begin_;
- End_ = that.End_;
- *(--Begin_) = std::move(element);
- } else {
- NewNormal(&element, &element + 1, that.Begin_, that.End_);
- }
- }
- TListRepresentation(const TSelf& that, T&& element)
- {
- if (!that.Chunk_) {
- FromSingleElement(std::move(element));
- return;
- }
- if ((that.Type_ == Type::Normal) && (that.End_ != that.Chunk_->DataEnd())) {
- Type_ = Type::Normal;
- that.Type_ = Type::Freezed;
- Chunk_ = that.Chunk_;
- Chunk_->Ref();
- Begin_ = that.Begin_;
- End_ = that.End_ + 1;
- *(that.End_) = std::move(element);
- } else {
- NewNormal(that.Begin_, that.End_, &element, &element + 1);
- }
- }
- ui64 GetLength() const {
- return End_ - Begin_;
- }
- TIterator GetIterator() const {
- return TIterator(*this);
- }
- TReverseIterator GetReverseIterator() const {
- return TReverseIterator(*this);
- }
- TSelf Append(T&& right) const {
- return TSelf(*this, std::move(right));
- }
- TSelf Prepend(T&& left) const {
- return TSelf(std::move(left), *this);
- }
- TSelf MassPrepend(T* begin, T* end) const {
- if ((Type_ == Type::Normal) && (Chunk_->DataBegin() + (end - begin) <= Begin_)) {
- Type_ = Type::Freezed;
- return TSelf(Chunk_, std::copy_backward(begin, end, Begin_), End_, Type::Normal);
- } else {
- return TSelf(begin, end, Begin_, End_);
- }
- }
- TSelf MassAppend(T* begin, T* end) const {
- if ((Type_ == Type::Normal) && (End_ + (end - begin) <= Chunk_->DataEnd())) {
- Type_ = Type::Freezed;
- return TSelf(Chunk_, Begin_, std::copy(begin, end, End_), Type::Normal);
- } else {
- return TSelf(Begin_, End_, begin, end);
- }
- }
- TSelf Extend(const TSelf& right) const {
- ui64 thisLength = GetLength();
- ui64 rightLength = right.GetLength();
- if (!thisLength)
- return TSelf(right);
- if (!rightLength)
- return TSelf(*this);
- if (Type_ == Type::Freezed) {
- if (right.Type_ == Type::Freezed) {
- return TSelf(Begin_, End_, right.Begin_, right.End_);
- } else {
- return right.MassPrepend(Begin_, End_);
- }
- } else if ((right.Type_ == Type::Freezed) || (thisLength > rightLength)) {
- return MassAppend(right.Begin_, right.End_);
- } else {
- return right.MassPrepend(Begin_, End_);
- }
- }
- TSelf SkipFromBegin(ui64 count) const {
- Y_DEBUG_ABORT_UNLESS((count > 0) && (count < GetLength()));
- return TSelf(Chunk_, Begin_ + count, End_, Type::Freezed);
- }
- TSelf SkipFromEnd(ui64 count) const {
- Y_DEBUG_ABORT_UNLESS((count > 0) && (count < GetLength()));
- return TSelf(Chunk_, Begin_, End_ - count, Type::Freezed);
- }
- T GetItemByIndex(ui64 index) const {
- Y_DEBUG_ABORT_UNLESS((index >= 0) && (index < GetLength()));
- return Begin_[index];
- }
- T* GetItems() const {
- return Begin_;
- }
- private:
- TChunk* Chunk_;
- T* Begin_;
- T* End_;
- mutable Type Type_;
- };
- using TDefaultListRepresentation = TListRepresentation<NUdf::TUnboxedValue>;
- }
- }
|