summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qbytearray.cpp
diff options
context:
space:
mode:
authorJoão Abecasis <joao.abecasis@nokia.com>2012-02-16 19:59:07 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-17 21:23:06 +0100
commitfb8be9905d5f3216edc3fbb72b8ce1c380737eac (patch)
tree87139503e92ad8aac60bcdc59242610884f37573 /src/corelib/tools/qbytearray.cpp
parent5d593da3d31a0c6adffb449db3ceb65328b87cd6 (diff)
qAllocMore: Always grow exponentially
qAllocMore is used by growing containers to allocate additional memory for future growth. The previous algorithm would grow linearly in increments of 8 up to 64 and then progress exponentially in powers of two. The new (constant time) algorithm does away with the linear segment and always progresses exponentially. It also has the nice benefit of cleanly avoiding undefined behaviour that the old implementation tried hard to circumvent. Besides always progressing exponentially, the next-power-of-two algorithm was tweaked to always include space for growth. Previously queries at boundary values (powers of two) would return the same value. The test was updated to verify sanity of results. As the algorithm is well behaved, testing of bogus data was dropped. Whatever happens in those cases is irrelevant, anyway: the bug lives elsewhere. Change-Id: I4def473cce4b438734887084e3c3bd8da0ff466b Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Diffstat (limited to 'src/corelib/tools/qbytearray.cpp')
-rw-r--r--src/corelib/tools/qbytearray.cpp37
1 files changed, 19 insertions, 18 deletions
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 90069b112d..559ba193d1 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -69,24 +69,25 @@ int qFindByteArray(
int qAllocMore(int alloc, int extra)
{
- if (alloc == 0 && extra == 0)
- return 0;
- const int page = 1 << 12;
- int nalloc;
- alloc += extra;
- if (alloc < 1<<6) {
- nalloc = (1<<3) + ((alloc >>3) << 3);
- } else {
- // don't do anything if the loop will overflow signed int.
- if (alloc >= INT_MAX/2)
- return INT_MAX;
- nalloc = (alloc < page) ? 1 << 3 : page;
- while (nalloc < alloc) {
- if (nalloc <= 0)
- return INT_MAX;
- nalloc *= 2;
- }
- }
+ Q_ASSERT(alloc >= 0 && extra >= 0);
+ Q_ASSERT(alloc < (1 << 30) - extra);
+
+ unsigned nalloc = alloc + extra;
+
+ // Round up to next power of 2
+
+ // Assuming container is growing, always overshoot
+ //--nalloc;
+
+ nalloc |= nalloc >> 1;
+ nalloc |= nalloc >> 2;
+ nalloc |= nalloc >> 4;
+ nalloc |= nalloc >> 8;
+ nalloc |= nalloc >> 16;
+ ++nalloc;
+
+ Q_ASSERT(nalloc > unsigned(alloc + extra));
+
return nalloc - extra;
}