From 1e2c29f2632c378843c5a3c9ad401a7bcacc4de0 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Wed, 13 Apr 2016 10:09:16 -0700 Subject: prevector: destroy elements only via erase() Fixes a bug in which pop_back did not call the deleted item's destructor. Using the most general erase() implementation to implement all the others prevents similar bugs because the coupling between deallocation and destructor invocation only needs to be maintained in one place. Also reduces duplication of complex memmove logic. --- src/prevector.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/prevector.h b/src/prevector.h index 1da459bcfe..16b2f8dca7 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -298,9 +298,8 @@ public: } void resize(size_type new_size) { - while (size() > new_size) { - item_ptr(size() - 1)->~T(); - _size--; + if (size() > new_size) { + erase(item_ptr(new_size), end()); } if (new_size > capacity()) { change_capacity(new_size); @@ -368,10 +367,7 @@ public: } iterator erase(iterator pos) { - (*pos).~T(); - memmove(&(*pos), &(*pos) + 1, ((char*)&(*end())) - ((char*)(1 + &(*pos)))); - _size--; - return pos; + return erase(pos, pos + 1); } iterator erase(iterator first, iterator last) { @@ -396,7 +392,7 @@ public: } void pop_back() { - _size--; + erase(end() - 1, end()); } T& front() { -- cgit v1.2.3 From 4ed41a2b611dfd328fe6f72312d6c596650f03f8 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Sat, 16 Apr 2016 06:49:38 -0700 Subject: test prevector::swap - add a swap operation to prevector tests (fails due to broken prevector::swap) - fix 2 prevector test operation conditions that were impossible --- src/test/prevector_tests.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 01a45b540d..b39b903530 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -19,9 +19,11 @@ template class prevector_tester { typedef std::vector realtype; realtype real_vector; + realtype real_vector_alt; typedef prevector pretype; pretype pre_vector; + pretype pre_vector_alt; typedef typename pretype::size_type Size; @@ -149,6 +151,12 @@ public: pre_vector.shrink_to_fit(); test(); } + + void swap() { + real_vector.swap(real_vector_alt); + pre_vector.swap(pre_vector_alt); + test(); + } }; BOOST_AUTO_TEST_CASE(PrevectorTestInt) @@ -204,12 +212,15 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) if (test.size() > 0) { test.update(insecure_rand() % test.size(), insecure_rand()); } - if (((r >> 11) & 1024) == 11) { + if (((r >> 11) % 1024) == 11) { test.clear(); } - if (((r >> 21) & 512) == 12) { + if (((r >> 21) % 512) == 12) { test.assign(insecure_rand() % 32, insecure_rand()); } + if (((r >> 15) % 64) == 3) { + test.swap(); + } } } } -- cgit v1.2.3 From a7af72a697a8decab364792230153f114be3919c Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Thu, 14 Apr 2016 09:26:32 -0700 Subject: prevector::swap: fix (unreached) data corruption swap was using an incorrect condition to determine when to apply an optimization (not swapping the full direct[] when swapping two indirect prevectors). Rather than correct the optimization I'm removing it for simplicity. Removing this optimization minutely improves performance in the typical (currently only) usage of member swap(), which is swapping with a freshly value-initialized object. --- src/prevector.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/prevector.h b/src/prevector.h index 16b2f8dca7..a0e1e140b4 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -412,12 +412,7 @@ public: } void swap(prevector& other) { - if (_size & other._size & 1) { - std::swap(_union.capacity, other._union.capacity); - std::swap(_union.indirect, other._union.indirect); - } else { - std::swap(_union, other._union); - } + std::swap(_union, other._union); std::swap(_size, other._size); } -- cgit v1.2.3