diff options
author | Geir Storli <geirst@yahoo-inc.com> | 2017-01-05 14:16:05 +0100 |
---|---|---|
committer | Geir Storli <geirst@yahoo-inc.com> | 2017-01-05 14:16:05 +0100 |
commit | e3c7468a6744d9f979bf98c3a7b74592dedf672a (patch) | |
tree | 7430fa2d40f83eeb72b1420d15153eaaf9990b3b /vespalib/src | |
parent | c872abddea00836006c2fd402a6c2b6654d8a6b9 (diff) |
Implement try_unreserve() on Array to reduce underlying memory buffer inplace.
Diffstat (limited to 'vespalib/src')
-rw-r--r-- | vespalib/src/tests/array/array_test.cpp | 29 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/array.h | 6 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/array.hpp | 12 |
3 files changed, 47 insertions, 0 deletions
diff --git a/vespalib/src/tests/array/array_test.cpp b/vespalib/src/tests/array/array_test.cpp index b7357512d89..13e46111bfb 100644 --- a/vespalib/src/tests/array/array_test.cpp +++ b/vespalib/src/tests/array/array_test.cpp @@ -320,4 +320,33 @@ TEST("test move assignment") } } +struct UnreserveFixture { + Array<int> arr; + UnreserveFixture() : arr(1025, 7, alloc::Alloc::allocMMap(0)) + { + EXPECT_EQUAL(1025u, arr.size()); + EXPECT_EQUAL(2048u, arr.capacity()); + } +}; + +TEST_F("require that try_unreserve() fails if wanted capacity >= current capacity", UnreserveFixture) +{ + EXPECT_FALSE(f.arr.try_unreserve(2048)); +} + +TEST_F("require that try_unreserve() fails if wanted capacity < current size", UnreserveFixture) +{ + EXPECT_FALSE(f.arr.try_unreserve(1024)); +} + +TEST_F("require that try_unreserve() succeedes if mmap can be shrinked", UnreserveFixture) +{ + int *oldPtr = &f.arr[0]; + f.arr.resize(512); + EXPECT_TRUE(f.arr.try_unreserve(1023)); + EXPECT_EQUAL(1024u, f.arr.capacity()); + int *newPtr = &f.arr[0]; + EXPECT_EQUAL(oldPtr, newPtr); +} + TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/vespalib/src/vespa/vespalib/util/array.h b/vespalib/src/vespa/vespalib/util/array.h index 269bf67bc26..4ca09bd093a 100644 --- a/vespalib/src/vespa/vespalib/util/array.h +++ b/vespalib/src/vespa/vespalib/util/array.h @@ -106,6 +106,12 @@ public: void resize(size_t n); void assign(const_iterator begin_, const_iterator end_); void reserve(size_t n); + /** + * Try to unreserve memory from the underlying memory buffer inplace down to the given limit. + * The existing memory buffer is unmodified up to the new size (no copying occurs). + * Returns true if it was possible to unreserve memory, false if not. + */ + bool try_unreserve(size_t n); void push_back(const T & v) { std::_Construct(push_back(), v); } iterator push_back() { extend(size()+1); return array(_sz++); } iterator push_back_fast() { return array(_sz++); } diff --git a/vespalib/src/vespa/vespalib/util/array.hpp b/vespalib/src/vespa/vespalib/util/array.hpp index dbdda73ad66..ec418d7d566 100644 --- a/vespalib/src/vespa/vespalib/util/array.hpp +++ b/vespalib/src/vespa/vespalib/util/array.hpp @@ -94,6 +94,18 @@ void Array<T>::reserve(size_t n) { } template <typename T> +bool Array<T>::try_unreserve(size_t n) +{ + if (n >= capacity()) { + return false; + } + if (n < size()) { + return false; + } + return _array.resize_inplace(n * sizeof(T)); +} + +template <typename T> void Array<T>::resize(size_t n) { if (n > capacity()) { |