463 RemoveLink_ (keyLinkInfo.fLink, keyLinkInfo.fLinksPointingToReturnedLink);
464 if constexpr (TRAITS::kCostlyInvariants) {
468 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
473 LinkAndInfoAboutBackPointers keyLinkInfo = FindNearest_ (i);
475 Link_* after = keyLinkInfo.fLink->fNext[0];
476 RemoveLink_ (keyLinkInfo.fLink, keyLinkInfo.fLinksPointingToReturnedLink);
477 if constexpr (TRAITS::kCostlyInvariants) {
480 return after ==
nullptr ? end () : ForwardIterator{
this, after};
482 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
485 AssertExternallySynchronizedMutex::WriteContext declareContext{*
this};
486 if constexpr (TRAITS::kCostlyInvariants) {
489 LinkAndInfoAboutBackPointers keyLinkInfo = FindNearest_ (key);
490 if (keyLinkInfo.fLink !=
nullptr) {
491 RemoveLink_ (keyLinkInfo.fLink, keyLinkInfo.fLinksPointingToReturnedLink);
492 if constexpr (TRAITS::kCostlyInvariants) {
501 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
504 AssertExternallySynchronizedMutex::WriteContext declareContext{*
this};
505 for (
auto it = links.begin (); it != links.end (); ++it) {
506 size_t index = it - links.begin ();
507 Link_** patchLink = (*it ==
nullptr) ? &fHead_[index] : &(*it)->fNext[index];
508 if (*patchLink == n) {
509 if constexpr (same_as<SkipList_Support::Stats_Basic, StatsType>) {
510 ++fStats_.fRotations;
512 *patchLink = n->fNext[index];
518 if (n->fNext.size () == fHead_.size ()) {
519 ShrinkHeadLinksIfNeeded_ ();
524 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
525 size_t SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::DetermineLinkHeight_ ()
const
527 constexpr size_t kMaxNewGrowth = 1;
528 size_t linkHeight = 1;
529 size_t maxHeight = min (fHead_.size () + kMaxNewGrowth, size_t (kMaxLinkHeight_));
530 while ((linkHeight < maxHeight) and (Private_::RandomSize_t (1, 100) <= GetLinkHeightProbability ())) {
535 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
536 void SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::GrowHeadLinksIfNeeded_ (
size_t newSize, Link_* linkToPointTo)
538 if (newSize > fHead_.size ()) {
539 fHead_.resize (newSize, linkToPointTo);
540 Assert (fHead_[newSize - 1] == linkToPointTo);
543 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
544 void SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ShrinkHeadLinksIfNeeded_ ()
546 Require (fHead_.size () >= 1);
547 for (
size_t i = fHead_.size () - 1; i >= 1; --i) {
548 if (fHead_[i] ==
nullptr) {
552 Ensure (fHead_.size () >= 1);
554 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
557 AssertExternallySynchronizedMutex::WriteContext declareContext{*
this};
558 Link_* link = (fHead_.size () == 0) ?
nullptr : fHead_[0];
559 while (link !=
nullptr) {
560 Link_* nextLink = link->fNext[0];
567 Ensure (size () == 0);
569 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
572 LinkVector_ linksPointingToReturnedLink;
573 key_type key = std::get_if<key_type> (&keyOrI) ? std::get<key_type> (keyOrI) : get<ForwardIterator> (keyOrI).fCurrent_->fEntry.fKey;
575 Assert (fHead_.size () > 0);
576 linksPointingToReturnedLink = fHead_;
577 Link_* newOverShotLink =
nullptr;
578 Link_* foundLink =
nullptr;
579 Assert (not linksPointingToReturnedLink.empty ());
580 size_t linkIndex = linksPointingToReturnedLink.size () - 1;
582 Link_* n = linksPointingToReturnedLink[linkIndex];
586 Link_* overShotLink = newOverShotLink;
587 Assert (n ==
nullptr or overShotLink ==
nullptr or
588 (fKeyThreeWayComparer_ (n->fEntry.fKey, overShotLink->fEntry.fKey) != strong_ordering::greater));
590 linksPointingToReturnedLink[linkIndex] =
nullptr;
591 while (n != overShotLink) {
592 if constexpr (same_as<SkipList_Support::Stats_Basic, StatsType>) {
595 switch (ToInt (fKeyThreeWayComparer_ (n->fEntry.fKey, key))) {
596 case ToInt (strong_ordering::equal):
597 if (
std::get_if<key_type> (&keyOrI) or n == get<ForwardIterator> (keyOrI).fCurrent_) {
599 newOverShotLink = foundLink;
603 linksPointingToReturnedLink[linkIndex] = n;
604 n = n->fNext[linkIndex];
608 case ToInt (strong_ordering::less):
609 linksPointingToReturnedLink[linkIndex] = n;
610 n = n->fNext[linkIndex];
613 case ToInt (strong_ordering::greater):
624 if (linkIndex > 0 and linksPointingToReturnedLink[linkIndex] !=
nullptr) {
625 linksPointingToReturnedLink[linkIndex - 1] = linksPointingToReturnedLink[linkIndex];
627 }
while (linkIndex-- != 0);
629 Ensure (foundLink ==
nullptr or fKeyThreeWayComparer_ (foundLink->fEntry.fKey, key) == strong_ordering::equal);
634 return LinkAndInfoAboutBackPointers{foundLink, move (linksPointingToReturnedLink)};
637 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
638 auto SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::GetFirst_ () const -> Link_*
640 Require (fHead_.size () >= 1);
643 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
644 auto SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::GetLast_ () const -> Link_*
646 Require (fHead_.size () >= 1);
647 size_t linkIndex = fHead_.size () - 1;
648 Link_* n = fHead_[linkIndex];
652 while (n !=
nullptr) {
654 n = n->fNext[linkIndex];
657 if (linkIndex == 0) {
665 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
666 template <qCompilerAndStdLib_RequiresNotMatchXXXDefined_1_BWA (invocable<
typename SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::value_type>) FUNCTION>
667 inline void SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::Apply (FUNCTION&& doToElement)
const
669 Debug::AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
670 std::for_each (begin (), end (), forward<FUNCTION> (doToElement));
672 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
675 LinkAndInfoAboutBackPointers keyLinkInfo = FindNearest_ (key);
676 if (keyLinkInfo.fLink !=
nullptr and keyLinkInfo.fLink->fNext.size () <= fHead_.size ()) {
677 if (keyLinkInfo.fLink->fNext.size () == fHead_.size ()) {
678 GrowHeadLinksIfNeeded_ (fHead_.size () + 1, keyLinkInfo.fLink);
679 keyLinkInfo.fLinksPointingToReturnedLink.resize (fHead_.size (), keyLinkInfo.fLink);
681 size_t oldLinkHeight = keyLinkInfo.fLink->fNext.size ();
682 keyLinkInfo.fLink->fNext.resize (fHead_.size (),
nullptr);
683 size_t newLinkHeight = keyLinkInfo.fLink->fNext.size ();
684 Assert (oldLinkHeight < newLinkHeight);
685 for (
size_t i = oldLinkHeight; i <= newLinkHeight - 1; ++i) {
686 if (keyLinkInfo.fLinksPointingToReturnedLink[i] ==
nullptr) {
687 fHead_[i] = keyLinkInfo.fLink;
689 else if (keyLinkInfo.fLinksPointingToReturnedLink[i] == keyLinkInfo.fLink) {
693 if constexpr (same_as<SkipList_Support::Stats_Basic, StatsType>) {
694 ++fStats_.fRotations;
696 Link_* oldLink = keyLinkInfo.fLinksPointingToReturnedLink[i];
698 Assert (oldLink->fNext.size () > i);
699 Link_* nextL = oldLink->fNext[i];
700 oldLink->fNext[i] = keyLinkInfo.fLink;
701 keyLinkInfo.fLink->fNext[i] = nextL;
706 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
707 template <
typename CHECKED_T>
709 requires (not same_as<MAPPED_TYPE, void>)
711 const_cast<ForwardIterator&
> (it).UpdateValue (newValue);
713 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
716 if (empty ()) [[unlikely]] {
722 double indexBase = (GetLinkHeightProbability () == 0) ? 0 : 1 / (GetLinkHeightProbability () / 100.0);
723 size_t height[kMaxLinkHeight_];
724 size_t lastValidHeight = 0;
725 for (
size_t i = 0; i <
sizeof (height) /
sizeof (
size_t); ++i) {
726 height[i] = size_t (pow (indexBase,
double (i)));
727 if (height[i] == 0 or height[i] > size ()) {
734 Link_* link = fHead_[0];
736 fHead_.resize (kMaxLinkHeight_);
738 Link_** patchLinks[kMaxLinkHeight_];
739 for (
size_t i = 0; i <
sizeof (patchLinks) /
sizeof (
size_t); ++i) {
740 patchLinks[i] = &fHead_[i];
744 while (link !=
nullptr) {
745 Link_* next = link->fNext[0];
746 link->fNext.clear ();
747#if qStroika_Foundation_Debug_AssertionsChecked
748 bool patched =
false;
750 for (
size_t hIndex = lastValidHeight + 1; hIndex-- > 0;) {
751 if (index >= height[hIndex] and (index % height[hIndex] == 0)) {
752 link->fNext.resize (hIndex + 1,
nullptr);
753 for (
size_t patchIndex = link->fNext.size (); patchIndex-- > 0;) {
754 *patchLinks[patchIndex] = link;
755 patchLinks[patchIndex] = &link->fNext[patchIndex];
757#if qStroika_Foundation_Debug_AssertionsChecked
763#if qStroika_Foundation_Debug_AssertionsChecked
770 Assert (index == size () + 1);
771 ShrinkHeadLinksIfNeeded_ ();
773 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
776 if (totalHeight !=
nullptr) {
778 size_t maxLinkHeight = 0;
779 Link_* n = fHead_[0];
780 while (n !=
nullptr) {
781 maxLinkHeight = max (maxLinkHeight, n->fNext.size ());
782 *totalHeight += n->fNext.size ();
785 Assert (maxLinkHeight == fHead_.size ());
787 return fHead_.size ();
789 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
792#if qStroika_Foundation_Debug_AssertionsChecked
796#if qStroika_Foundation_Debug_AssertionsChecked
797 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
798 void SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::Invariant_ () const noexcept
801 const Link_* n = fHead_[0];
802 while (n !=
nullptr) {
804 KEY_TYPE oldKey = n->fEntry.fKey;
805 for (
size_t i = 1; i < n->fNext.size (); ++i) {
806 const Link_* newN = n->fNext[i];
808 Assert (newN ==
nullptr);
812 Assert (newN ==
nullptr or fKeyThreeWayComparer_ (oldKey, newN->fEntry.fKey) != strong_ordering::greater);
815 Assert (not n->fNext.empty ());
817 Assert (n ==
nullptr or fKeyThreeWayComparer_ (n->fEntry.fKey, oldKey) != strong_ordering::less);
819 Assert (sz == this->fLength_);
828 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
829 constexpr SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::ForwardIterator (
const SkipList* data, UnderlyingIteratorRep startAt) noexcept
831#if qStroika_Foundation_Debug_AssertionsChecked
838 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
839 constexpr SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::ForwardIterator (
const SkipList* data) noexcept
843#if qStroika_Foundation_Debug_AssertionsChecked
844 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
845 SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::~ForwardIterator ()
850 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
851 inline SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::operator bool ()
const
855 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
856 inline auto SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::Done () const noexcept ->
bool
858 return fCurrent_ ==
nullptr;
860 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
861 inline auto SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::operator* () const -> const value_type&
864 return fCurrent_->fEntry;
866 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
867 inline auto SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::operator->() const -> const value_type*
870 return &fCurrent_->fEntry;
872 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
873 inline auto SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::CurrentIndex (
const SkipList* data)
const ->
size_t
875 Require (not Done ());
876#if qStroika_Foundation_Debug_AssertionsChecked
878 Require (fData_ == data);
882 for (
const Link_* l = data->fHead_;; l = l->fNext[0], ++i) {
884 if (l == fCurrent_) [[unlikely]] {
891 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
892 inline constexpr bool SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::operator== (
const ForwardIterator& rhs)
const
894#if qStroika_Foundation_Debug_AssertionsChecked
895 Require (fData_ ==
nullptr or rhs.fData_ ==
nullptr or fData_ == rhs.fData_);
897 return fCurrent_ == rhs.fCurrent_;
899 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
900 constexpr auto SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::GetUnderlyingIteratorRep () const -> UnderlyingIteratorRep
904 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
905 inline void SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::SetUnderlyingIteratorRep (
const UnderlyingIteratorRep l)
909 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
910 constexpr void SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::AssertDataMatches ([[maybe_unused]]
const SkipList* data)
const
912#if qStroika_Foundation_Debug_AssertionsChecked
913 Require (data == fData_);
916 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
917 auto SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::operator++ () -> ForwardIterator&
919 fCurrent_ = fCurrent_->fNext[0];
922 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
923 auto SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::operator++ (
int) -> ForwardIterator
925 ForwardIterator result = *
this;
929 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
930 template <
typename CHECKED_T>
931 void SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::UpdateValue (ArgByValueType<CHECKED_T> newValue)
932 requires (not same_as<MAPPED_TYPE, void>)
934 Link_* link2Update =
const_cast<Link_*
> (fCurrent_);
935 link2Update->fEntry.fValue = newValue;
937 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
938 constexpr void SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::Invariant () const noexcept
940#if qStroika_Foundation_Debug_AssertionsChecked
944#if qStroika_Foundation_Debug_AssertionsChecked
945 template <
typename KEY_TYPE,
typename MAPPED_TYPE, SkipList_Support::IVal
idTraits<KEY_TYPE> TRAITS>
946 void SkipList<KEY_TYPE, MAPPED_TYPE, TRAITS>::ForwardIterator::Invariant_ () const noexcept
949 Require (Done () or fData_ !=
nullptr);
950 if (fData_ !=
nullptr) {
951 fData_->Invariant ();