diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2022-04-01 10:37:45 +0200 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2022-04-06 16:46:59 +0200 |
commit | 7c9afa8d00cc2bbc1b102eef6e76c23e07c7833f (patch) | |
tree | b881550074308a9df8d9bb24ae5144a6eb2fbd70 /src/corelib/tools | |
parent | d11941db41f00525f907417bbcd6ac5ee30d8485 (diff) |
Q[Multi]Hash: fix squeeze()
When calling QHash::reserve(), or when creating the
internal QHashPrivate::Data structure, the value 0
for the size parameter is reserved for performing
the squeeze operation.
However commit 8a984ab772dd194e39094e728b869e65912912a7
broke it, by using the 0 value in QHashPrivate::Data
constructors as a mark that no resizing needs to be done.
This patch reverts the problematic commit (also applying
some later fixes to the code), and adds the missing
tests for Q[Multi]Hash::squeeze().
Pick-to: 6.3 6.2
Change-Id: Id644df7b2beb008e6a37b2c89b709adfbd893e25
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools')
-rw-r--r-- | src/corelib/tools/qhash.h | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 6a545988d4..07e2f2d355 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -565,7 +565,6 @@ struct Data } }; - Data(size_t reserve = 0) { numBuckets = GrowthPolicy::bucketsForCapacity(reserve); @@ -573,25 +572,16 @@ struct Data spans = new Span[nSpans]; seed = QHashSeed::globalSeed(); } - Data(const Data &other, size_t reserved = 0) - : size(other.size), - numBuckets(other.numBuckets), - seed(other.seed) - { - if (reserved) - numBuckets = GrowthPolicy::bucketsForCapacity(qMax(size, reserved)); - bool resized = numBuckets != other.numBuckets; - size_t nSpans = numBuckets >> SpanConstants::SpanShift; - spans = new Span[nSpans]; - size_t otherNSpans = other.numBuckets >> SpanConstants::SpanShift; - for (size_t s = 0; s < otherNSpans; ++s) { + void reallocationHelper(const Data &other, size_t nSpans, bool resized) + { + for (size_t s = 0; s < nSpans; ++s) { const Span &span = other.spans[s]; for (size_t index = 0; index < SpanConstants::NEntries; ++index) { if (!span.hasNode(index)) continue; const Node &n = span.at(index); - auto it = resized ? findBucket(n.key) : Bucket{ spans + s, index }; + auto it = resized ? findBucket(n.key) : Bucket { spans + s, index }; Q_ASSERT(it.isUnused()); Node *newNode = it.insert(); new (newNode) Node(n); @@ -599,7 +589,31 @@ struct Data } } - static Data *detached(Data *d, size_t size = 0) + Data(const Data &other) : size(other.size), numBuckets(other.numBuckets), seed(other.seed) + { + size_t nSpans = numBuckets >> SpanConstants::SpanShift; + spans = new Span[nSpans]; + reallocationHelper(other, nSpans, false); + } + Data(const Data &other, size_t reserved) : size(other.size), seed(other.seed) + { + numBuckets = GrowthPolicy::bucketsForCapacity(qMax(size, reserved)); + size_t nSpans = numBuckets >> SpanConstants::SpanShift; + spans = new Span[nSpans]; + size_t otherNSpans = other.numBuckets >> SpanConstants::SpanShift; + reallocationHelper(other, otherNSpans, true); + } + + static Data *detached(Data *d) + { + if (!d) + return new Data; + Data *dd = new Data(*d); + if (!d->ref.deref()) + delete d; + return dd; + } + static Data *detached(Data *d, size_t size) { if (!d) return new Data(size); |