From 5feb5fe821a7b9db366fcc56b9ce4a4ea3500c03 Mon Sep 17 00:00:00 2001 From: pechatnov Date: Fri, 3 Jul 2026 08:57:28 +0300 Subject: Optimize TLogger::WithTag/WithRawTag Make TLogger::WithTag use a compile-time format string commit_hash:0a119b8eb278bceb411b7d071bbefe0b41e6233d --- library/cpp/yt/logging/benchmark/logger_tag.cpp | 32 +++++++++++++++++++++++++ library/cpp/yt/logging/benchmark/ya.make | 14 +++++++++++ library/cpp/yt/logging/logger-inl.h | 8 +++---- library/cpp/yt/logging/logger.cpp | 8 +++---- library/cpp/yt/logging/logger.h | 12 +++++----- library/cpp/yt/logging/ya.make | 1 + 6 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 library/cpp/yt/logging/benchmark/logger_tag.cpp create mode 100644 library/cpp/yt/logging/benchmark/ya.make (limited to 'library/cpp') diff --git a/library/cpp/yt/logging/benchmark/logger_tag.cpp b/library/cpp/yt/logging/benchmark/logger_tag.cpp new file mode 100644 index 00000000000..cb6208db2a3 --- /dev/null +++ b/library/cpp/yt/logging/benchmark/logger_tag.cpp @@ -0,0 +1,32 @@ +#include + +#include + +#include + +#include + +namespace NYT::NLogging { +namespace { + +//////////////////////////////////////////////////////////////////////////////// + +const TGuid RequestId(0x12345678, 0x9abcdef0, 0x11223344, 0x55667788); +const std::string User = "robot-benchmark-user"; +const std::string Realm = "some-realm"; + +void BM_WithTag(benchmark::State& state) +{ + TLogger logger("Benchmark"); + for (auto _ : state) { + auto tagged = logger.WithTag("RequestId: %v, User: %v, Realm: %v", RequestId, User, Realm); + benchmark::DoNotOptimize(tagged); + } +} + +BENCHMARK(BM_WithTag); + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace +} // namespace NYT::NLogging diff --git a/library/cpp/yt/logging/benchmark/ya.make b/library/cpp/yt/logging/benchmark/ya.make new file mode 100644 index 00000000000..61fd0b49276 --- /dev/null +++ b/library/cpp/yt/logging/benchmark/ya.make @@ -0,0 +1,14 @@ +G_BENCHMARK() + +INCLUDE(${ARCADIA_ROOT}/library/cpp/yt/ya_cpp.make.inc) + +SRCS( + logger_tag.cpp +) + +PEERDIR( + library/cpp/yt/logging + library/cpp/yt/string +) + +END() diff --git a/library/cpp/yt/logging/logger-inl.h b/library/cpp/yt/logging/logger-inl.h index e54952822c8..87672ec6f6a 100644 --- a/library/cpp/yt/logging/logger-inl.h +++ b/library/cpp/yt/logging/logger-inl.h @@ -22,9 +22,9 @@ inline bool TLogger::IsAnchorUpToDate(const TLoggingAnchor& anchor) const } template -void TLogger::AddTag(const char* format, TArgs&&... args) +void TLogger::AddTag(TFormatString format, TArgs&&... args) { - AddRawTag(Format(TRuntimeFormat{format}, std::forward(args)...)); + AddRawTag(Format(format, std::forward(args)...)); } template @@ -35,7 +35,7 @@ void TLogger::AddStructuredTag(TStringBuf key, TType value) } template -TLogger TLogger::WithTag(const char* format, TArgs&&... args) const & +TLogger TLogger::WithTag(TFormatString format, TArgs&&... args) const & { auto result = *this; result.AddTag(format, std::forward(args)...); @@ -43,7 +43,7 @@ TLogger TLogger::WithTag(const char* format, TArgs&&... args) const & } template -TLogger TLogger::WithTag(const char* format, TArgs&&... args) && +TLogger TLogger::WithTag(TFormatString format, TArgs&&... args) && { AddTag(format, std::forward(args)...); return std::move(*this); diff --git a/library/cpp/yt/logging/logger.cpp b/library/cpp/yt/logging/logger.cpp index 458d01d8133..64d8b06fa7e 100644 --- a/library/cpp/yt/logging/logger.cpp +++ b/library/cpp/yt/logging/logger.cpp @@ -220,23 +220,23 @@ void TLogger::Write(TLogEvent&& event) const LogManager_->Enqueue(std::move(event)); } -void TLogger::AddRawTag(const std::string& tag) +void TLogger::AddRawTag(TStringBuf tag) { auto* state = GetMutableCoWState(); if (!state->Tag.empty()) { state->Tag += ", "; } - state->Tag += tag; + state->Tag.append(tag.data(), tag.size()); } -TLogger TLogger::WithRawTag(const std::string& tag) const & +TLogger TLogger::WithRawTag(TStringBuf tag) const & { auto result = *this; result.AddRawTag(tag); return result; } -TLogger TLogger::WithRawTag(const std::string& tag) && +TLogger TLogger::WithRawTag(TStringBuf tag) && { AddRawTag(tag); return std::move(*this); diff --git a/library/cpp/yt/logging/logger.h b/library/cpp/yt/logging/logger.h index cab385bf676..d781326e88d 100644 --- a/library/cpp/yt/logging/logger.h +++ b/library/cpp/yt/logging/logger.h @@ -227,21 +227,21 @@ public: void Write(TLogEvent&& event) const; - void AddRawTag(const std::string& tag); + void AddRawTag(TStringBuf tag); template - void AddTag(const char* format, TArgs&&... args); + void AddTag(TFormatString format, TArgs&&... args); template void AddStructuredTag(TStringBuf key, TType value); void AddStructuredValidator(TStructuredValidator validator); - TLogger WithRawTag(const std::string& tag) const &; - TLogger WithRawTag(const std::string& tag) &&; + TLogger WithRawTag(TStringBuf tag) const &; + TLogger WithRawTag(TStringBuf tag) &&; template - TLogger WithTag(const char* format, TArgs&&... args) const &; + TLogger WithTag(TFormatString format, TArgs&&... args) const &; template - TLogger WithTag(const char* format, TArgs&&... args) &&; + TLogger WithTag(TFormatString format, TArgs&&... args) &&; template TLogger WithStructuredTag(TStringBuf key, TType value) const &; diff --git a/library/cpp/yt/logging/ya.make b/library/cpp/yt/logging/ya.make index 8b338ed3b77..b9cf5c6e715 100644 --- a/library/cpp/yt/logging/ya.make +++ b/library/cpp/yt/logging/ya.make @@ -18,6 +18,7 @@ END() RECURSE( backends + benchmark plain_text_formatter ) -- cgit v1.3 From b417cd406eb074848724b1d0d4c796ff1274be8c Mon Sep 17 00:00:00 2001 From: tobo Date: Fri, 3 Jul 2026 10:15:19 +0300 Subject: apply style fixes to TPagedVector No behaviuor changes, just style fixes commit_hash:0d251b393424c70c7c26c563b08d2746c756c7ad --- library/cpp/containers/paged_vector/paged_vector.h | 120 +++++++++++---------- .../containers/paged_vector/ut/paged_vector_ut.cpp | 14 +-- 2 files changed, 72 insertions(+), 62 deletions(-) (limited to 'library/cpp') diff --git a/library/cpp/containers/paged_vector/paged_vector.h b/library/cpp/containers/paged_vector/paged_vector.h index 96be0042e0a..f12a465478a 100644 --- a/library/cpp/containers/paged_vector/paged_vector.h +++ b/library/cpp/containers/paged_vector/paged_vector.h @@ -15,36 +15,36 @@ namespace NPagedVector { struct TPagedVectorIterator { private: friend class TPagedVector; - typedef TPagedVector TVec; - typedef TPagedVectorIterator TSelf; - size_t Offset; - TVec* Vector; + using TVec = TPagedVector; + using TSelf = TPagedVectorIterator; + size_t Offset_; + TVec* Vector_; template friend struct TPagedVectorIterator; public: TPagedVectorIterator() - : Offset() - , Vector() + : Offset_() + , Vector_() { } TPagedVectorIterator(TVec* vector, size_t offset) - : Offset(offset) - , Vector(vector) + : Offset_(offset) + , Vector_(vector) { } template TPagedVectorIterator(const TPagedVectorIterator& it) - : Offset(it.Offset) - , Vector(it.Vector) + : Offset_(it.Offset_) + , Vector_(it.Vector_) { } T& operator*() const { - return (*Vector)[Offset]; + return (*Vector_)[Offset_]; } T* operator->() const { @@ -53,7 +53,7 @@ namespace NPagedVector { template bool operator==(const TPagedVectorIterator& it) const { - return Offset == it.Offset; + return Offset_ == it.Offset_; } template @@ -63,12 +63,12 @@ namespace NPagedVector { template bool operator<(const TPagedVectorIterator& it) const { - return Offset < it.Offset; + return Offset_ < it.Offset_; } template bool operator<=(const TPagedVectorIterator& it) const { - return Offset <= it.Offset; + return Offset_ <= it.Offset_; } template @@ -83,11 +83,11 @@ namespace NPagedVector { template ptrdiff_t operator-(const TPagedVectorIterator& it) const { - return Offset - it.Offset; + return Offset_ - it.Offset_; } TSelf& operator+=(ptrdiff_t off) { - Offset += off; + Offset_ += off; return *this; } @@ -126,44 +126,44 @@ namespace NPagedVector { } size_t GetOffset() const { - return Offset; + return Offset_; } }; - } -} + } // namespace NPrivate +} // namespace NPagedVector namespace std { template struct iterator_traits> { - typedef ptrdiff_t difference_type; - typedef T value_type; - typedef T* pointer; - typedef T& reference; - typedef random_access_iterator_tag iterator_category; + using difference_type = ptrdiff_t; + using value_type = T; + using pointer = T*; + using reference = T&; + using iterator_category = random_access_iterator_tag; }; -} +} // namespace std namespace NPagedVector { - //2-level radix tree + // 2-level radix tree template class TPagedVector { static_assert(PageSize, "expect PageSize"); - typedef TVector TPage; - typedef TVector, A> TPages; - typedef TPagedVector TSelf; + using TPage = TVector; + using TPages = TVector, A>; + using TSelf = TPagedVector; TPages Pages_; public: - typedef NPrivate::TPagedVectorIterator iterator; - typedef NPrivate::TPagedVectorIterator const_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef T value_type; - typedef value_type& reference; - typedef const value_type& const_reference; + using iterator = NPrivate::TPagedVectorIterator; + using const_iterator = NPrivate::TPagedVectorIterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using value_type = T; + using reference = value_type&; + using const_reference = const value_type&; TPagedVector() = default; TPagedVector(TPagedVector&& other) noexcept = default; @@ -266,8 +266,9 @@ namespace NPagedVector { } void PrepareAppend() { - if (Pages_.empty() || CurrentPage().size() + 1 > PageSize) + if (Pages_.empty() || CurrentPage().size() + 1 > PageSize) { AllocateNewPage(); + } } public: @@ -283,7 +284,7 @@ namespace NPagedVector { return !empty(); } - template + template reference emplace_back(Args&&... args) { PrepareAppend(); return CurrentPage().emplace_back(std::forward(args)...); @@ -295,8 +296,9 @@ namespace NPagedVector { } void pop_back() { - if (CurrentPage().empty()) + if (CurrentPage().empty()) { Pages_.pop_back(); + } CurrentPage().pop_back(); } @@ -327,11 +329,12 @@ namespace NPagedVector { } iterator erase(iterator it) { - size_t pnum = PageNumber(it.Offset); - size_t pidx = InPageIndex(it.Offset); + size_t pnum = PageNumber(it.Offset_); + size_t pidx = InPageIndex(it.Offset_); - if (CurrentPage().empty()) + if (CurrentPage().empty()) { Pages_.pop_back(); + } for (size_t p = NPages() - 1; p > pnum; --p) { PageAt(p - 1).push_back(PageAt(p).front()); @@ -353,8 +356,8 @@ namespace NPagedVector { } iterator insert(iterator it, const value_type& v) { - size_t pnum = PageNumber(it.Offset); - size_t pidx = InPageIndex(it.Offset); + size_t pnum = PageNumber(it.Offset_); + size_t pidx = InPageIndex(it.Offset_); PrepareAppend(); @@ -370,8 +373,9 @@ namespace NPagedVector { template void insert(iterator it, TIter b, TIter e) { // todo : suboptimal! - for (; b != e; ++b, ++it) + for (; b != e; ++b, ++it) { it = insert(it, *b); + } } reference front() { @@ -395,25 +399,30 @@ namespace NPagedVector { } void resize(size_t sz) { - if (sz == size()) + if (sz == size()) { return; + } const size_t npages = NPages(); const size_t newwholepages = sz / PageSize; const size_t pagepart = sz % PageSize; const size_t newpages = newwholepages + bool(pagepart); - if (npages && newwholepages >= npages) + if (npages && newwholepages >= npages) { CurrentPage().resize(PageSize); + } - if (newpages < npages) + if (newpages < npages) { Pages_.resize(newpages); - else - for (size_t i = npages; i < newpages; ++i) + } else { + for (size_t i = npages; i < newpages; ++i) { MakeNewPage(); + } + } - if (pagepart) + if (pagepart) { CurrentPage().resize(pagepart); + } Y_ABORT_UNLESS(sz == size(), "%" PRIu64 " %" PRIu64, (ui64)sz, (ui64)size()); } @@ -444,10 +453,9 @@ namespace NPagedVector { }; namespace NPrivate { - typedef std::is_same::iterator>::iterator_category> - TIteratorCheck; + using TIteratorCheck = std::is_same::iterator>::iterator_category>; static_assert(TIteratorCheck::value, "expect TIteratorCheck::Result"); - } + } // namespace NPrivate -} +} // namespace NPagedVector diff --git a/library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp b/library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp index 54e4b71fa70..7f93676a3c2 100644 --- a/library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp +++ b/library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp @@ -126,8 +126,9 @@ private: TPagedVector v2; v2.resize(v1.size()); - for (size_t i = 0; i < v1.size(); ++i) + for (size_t i = 0; i < v1.size(); ++i) { v2[i] = v1[i]; + } v2[1] = 'o'; // Replace second character. @@ -336,14 +337,14 @@ private: UNIT_ASSERT(vint.rbegin() == vint.rbegin()); // Not Standard: - //UNIT_ASSERT(vint.rbegin() == crvint.rbegin()); - //UNIT_ASSERT(crvint.rbegin() == vint.rbegin()); + // UNIT_ASSERT(vint.rbegin() == crvint.rbegin()); + // UNIT_ASSERT(crvint.rbegin() == vint.rbegin()); UNIT_ASSERT(crvint.rbegin() == crvint.rbegin()); UNIT_ASSERT(vint.rbegin() != vint.rend()); // Not Standard: - //UNIT_ASSERT(vint.rbegin() != crvint.rend()); - //UNIT_ASSERT(crvint.rbegin() != vint.rend()); + // UNIT_ASSERT(vint.rbegin() != crvint.rend()); + // UNIT_ASSERT(crvint.rbegin() != vint.rend()); UNIT_ASSERT(crvint.rbegin() != crvint.rend()); } @@ -505,8 +506,9 @@ private: V* pv2 = new V; pv2->resize(10); - for (int i = 0; i < 10; ++i) + for (int i = 0; i < 10; ++i) { pv2->at(i) = 2; + } pv1->swap(*pv2); -- cgit v1.3 From a754ea45596eab7bb1193dd5ae9b9dc1d30eb4e7 Mon Sep 17 00:00:00 2001 From: Taras Pashkin <32797206+tpashkin@users.noreply.github.com> Date: Fri, 3 Jul 2026 13:54:50 +0300 Subject: Correctly fork orbits with multiple active shuttles in LWTrace lib Original fix merged to the nbs repo a while ago: https://github.com/ydb-platform/nbs/pull/4479 Can you bring to the upstream? --- Pull Request resolved: https://github.com/ytsaurus/ytsaurus/pull/1771 Co-authored-by: Alexander Smirnov commit_hash:5bf628be8a9c7b591f290ed05754e206b23efc34 --- library/cpp/lwtrace/log_shuttle.cpp | 4 +++- library/cpp/lwtrace/shuttle.h | 4 +++- library/cpp/lwtrace/trace_ut.cpp | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'library/cpp') diff --git a/library/cpp/lwtrace/log_shuttle.cpp b/library/cpp/lwtrace/log_shuttle.cpp index 695aa90b316..a6563efb5b9 100644 --- a/library/cpp/lwtrace/log_shuttle.cpp +++ b/library/cpp/lwtrace/log_shuttle.cpp @@ -22,7 +22,9 @@ namespace NLWTrace { template bool TLogShuttle::DoFork(TShuttlePtr& child) { - if (child = Executor->RentShuttle()) { + if (auto shuttle = Executor->RentShuttle()) { + shuttle->SetNext(child); + child = shuttle; child->SetParentSpanId(GetSpanId()); Executor->Cast(child)->SetIgnore(true); TParams params; diff --git a/library/cpp/lwtrace/shuttle.h b/library/cpp/lwtrace/shuttle.h index 6950b3877a4..c4519cbb876 100644 --- a/library/cpp/lwtrace/shuttle.h +++ b/library/cpp/lwtrace/shuttle.h @@ -309,7 +309,9 @@ namespace NLWTrace { if (shuttle->IsDead()) { *ref = shuttle->Drop(); } else { - result = result && shuttle->Fork(cHead); + if (Y_UNLIKELY(!shuttle->Fork(cHead))) { + result = false; + } ref = &shuttle->GetNext(); } } diff --git a/library/cpp/lwtrace/trace_ut.cpp b/library/cpp/lwtrace/trace_ut.cpp index 9a29923e28c..5c81a6419a7 100644 --- a/library/cpp/lwtrace/trace_ut.cpp +++ b/library/cpp/lwtrace/trace_ut.cpp @@ -789,6 +789,7 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) { UNIT_ASSERT(parsed); mngr.New("Query1", q); + mngr.New("Query2", q); { TOrbit a, b, c, d; @@ -849,6 +850,7 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) { } } reader; mngr.ReadDepot("Query1", reader); + mngr.ReadDepot("Query2", reader); } Y_UNIT_TEST(TrackForkError) { -- cgit v1.3 From 137013265ea10fd8a99ae76e9d075592bc05d953 Mon Sep 17 00:00:00 2001 From: babenko Date: Fri, 3 Jul 2026 16:17:12 +0300 Subject: Add TAnyObject::Holds and rename IsCurrentlyStored to HoldsType commit_hash:5f0c248f2c24b501b04777fb0300693b0e942c89 --- library/cpp/yt/memory/type_erasure.h | 18 ++++++++++++---- library/cpp/yt/memory/type_erasure_detail.h | 6 +++--- .../cpp/yt/memory/unittests/type_erasure_ut.cpp | 24 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) (limited to 'library/cpp') diff --git a/library/cpp/yt/memory/type_erasure.h b/library/cpp/yt/memory/type_erasure.h index 8d87a347b45..3b2dbe34015 100644 --- a/library/cpp/yt/memory/type_erasure.h +++ b/library/cpp/yt/memory/type_erasure.h @@ -94,7 +94,7 @@ public: T& AnyCast() & { const auto& vtable = GetVTable(); - if (!vtable.IsValid() || !vtable.template IsCurrentlyStored()) { + if (!vtable.IsValid() || !vtable.template HoldsType()) { throw TBadAnyCast{}; } @@ -106,7 +106,7 @@ public: const T& AnyCast() const & { const auto& vtable = Holder_.GetVTable(); - if (!vtable.IsValid() || !vtable.template IsCurrentlyStored()) { + if (!vtable.IsValid() || !vtable.template HoldsType()) { throw TBadAnyCast{}; } @@ -306,7 +306,7 @@ public: using TWrapped = TOwningWrapper; const auto& vtable = GetVTable(); - if (!vtable.IsValid() || !vtable.template IsCurrentlyStored()) { + if (!vtable.IsValid() || !vtable.template HoldsType()) { throw TBadAnyCast{}; } @@ -320,13 +320,23 @@ public: using TWrapped = TOwningWrapper; const auto& vtable = GetVTable(); - if (!vtable.IsValid() || !vtable.template IsCurrentlyStored()) { + if (!vtable.IsValid() || !vtable.template HoldsType()) { throw TBadAnyCast{}; } return Storage_.template As().Unwrap(); } + template + Y_FORCE_INLINE bool Holds() const + { + using TDecayed = std::remove_cvref_t; + using TWrapped = TOwningWrapper; + + const auto& vtable = GetVTable(); + return vtable.IsValid() && vtable.template HoldsType(); + } + Y_FORCE_INLINE bool IsValid() const { return Holder_.IsValid(); diff --git a/library/cpp/yt/memory/type_erasure_detail.h b/library/cpp/yt/memory/type_erasure_detail.h index 92904573d01..76b611a2d67 100644 --- a/library/cpp/yt/memory/type_erasure_detail.h +++ b/library/cpp/yt/memory/type_erasure_detail.h @@ -304,7 +304,7 @@ public: // NB(arkady-e1ppa): This method may or may not work correctly // for dynamically-linked libraries. template - Y_FORCE_INLINE bool IsCurrentlyStored() const noexcept + Y_FORCE_INLINE bool HoldsType() const noexcept { return Function_ == &TVTableEntry::StaticInvoke; } @@ -358,9 +358,9 @@ public: } template - Y_FORCE_INLINE bool IsCurrentlyStored() const noexcept + Y_FORCE_INLINE bool HoldsType() const noexcept { - return TVTableEntry::template IsCurrentlyStored(); + return TVTableEntry::template HoldsType(); } private: diff --git a/library/cpp/yt/memory/unittests/type_erasure_ut.cpp b/library/cpp/yt/memory/unittests/type_erasure_ut.cpp index b33ab368023..c923ec29a11 100644 --- a/library/cpp/yt/memory/unittests/type_erasure_ut.cpp +++ b/library/cpp/yt/memory/unittests/type_erasure_ut.cpp @@ -23,6 +23,14 @@ struct TCustomized } }; +struct TOtherCustomized +{ + friend int TagInvoke(TTagInvokeTag, const TOtherCustomized&) + { + return 0; + } +}; + //////////////////////////////////////////////////////////////////////////////// // 2 CPOs won't trigger static vtable. @@ -253,6 +261,22 @@ TEST(TAnyObjectTest, EmptyAny) EXPECT_EQ(conc.Value, 11); } +TEST(TAnyObjectTest, Holds) +{ + using TAnyObject = TAnyObject>; + + TAnyObject any{TCustomized{.Value = 42}}; + EXPECT_TRUE(any.Holds()); + EXPECT_FALSE(any.Holds()); + + TAnyObject other{TOtherCustomized{}}; + EXPECT_TRUE(other.Holds()); + EXPECT_FALSE(other.Holds()); + + TAnyObject empty; + EXPECT_FALSE(empty.Holds()); +} + TEST(TAnyObjectTest, CvRefCorrectness) { using TAnyObject = TAnyObject< -- cgit v1.3 From 29831c0924cc2568ee528fe8af122b7dc03ece52 Mon Sep 17 00:00:00 2001 From: tobo Date: Sat, 4 Jul 2026 01:13:25 +0300 Subject: optimize TPagedVector - erase() method erases element from pages first, then pushes back a new one - make size() a bit faster commit_hash:2dd667908f10f03c976c53002e1a9c51cb3be8f6 --- library/cpp/containers/paged_vector/paged_vector.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'library/cpp') diff --git a/library/cpp/containers/paged_vector/paged_vector.h b/library/cpp/containers/paged_vector/paged_vector.h index f12a465478a..a03404c688e 100644 --- a/library/cpp/containers/paged_vector/paged_vector.h +++ b/library/cpp/containers/paged_vector/paged_vector.h @@ -266,14 +266,14 @@ namespace NPagedVector { } void PrepareAppend() { - if (Pages_.empty() || CurrentPage().size() + 1 > PageSize) { + if (Pages_.empty() || CurrentPage().size() >= PageSize) { AllocateNewPage(); } } public: size_t size() const { - return empty() ? 0 : (NPages() - 1) * PageSize + CurrentPage().size(); + return Pages_.empty() ? 0 : (NPages() - 1) * PageSize + CurrentPage().size(); } bool empty() const { @@ -329,19 +329,22 @@ namespace NPagedVector { } iterator erase(iterator it) { - size_t pnum = PageNumber(it.Offset_); - size_t pidx = InPageIndex(it.Offset_); + const size_t pnum = PageNumber(it.Offset_); + const size_t pidx = InPageIndex(it.Offset_); if (CurrentPage().empty()) { Pages_.pop_back(); } - for (size_t p = NPages() - 1; p > pnum; --p) { - PageAt(p - 1).push_back(PageAt(p).front()); - PageAt(p).erase(PageAt(p).begin()); + auto currentPageIt = Pages_.begin() + pnum; + + (*currentPageIt)->erase((*currentPageIt)->begin() + pidx); + + for (auto nextPageIt = currentPageIt + 1; nextPageIt != Pages_.end(); currentPageIt = nextPageIt, ++nextPageIt) { + (*currentPageIt)->push_back(std::move((**nextPageIt)[0])); + (*nextPageIt)->erase((*nextPageIt)->begin()); } - PageAt(pnum).erase(PageAt(pnum).begin() + pidx); return it; } -- cgit v1.3