From: François Dumont Date: Sun, 12 Jun 2011 15:51:36 +0000 (+0200) Subject: allocator.h (__shrink_to_fit): Rename to __shrink_to_fit_aux, fix. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8a752dfea6f512ecb19a7f2fd535b8862ef3dbe2;p=gcc.git allocator.h (__shrink_to_fit): Rename to __shrink_to_fit_aux, fix. 2011-06-12 François Dumont Paolo Carlini * include/bits/allocator.h (__shrink_to_fit): Rename to __shrink_to_fit_aux, fix. * include/bits/stl_vector.h (_M_shrink_to_fit): Declare. (shrink_to_fit): Use the latter. * include/debug/vector (shrink_to_fit): Likewise. * include/bits/vector.tcc (_M_shrink_to_fit): Define. * include/bits/stl_deque.h (_M_shrink_to_fit): Declare. (shrink_to_fit): Use the latter. * include/debug/deque (shrink_to_fit): Likewise. * include/bits/deque.tcc (_M_shrink_to_fit): Define. * include/bits/vector.tcc (vector::_M_reallocate): Add. * include/bits/stl_bvector.h (_M_shrink_to_fit): Declare. (shrink_to_fit): Use the latter. (reserve): Use _M_reallocate, move inline. (_Bvector_base<>::_S_nword): Add, use it throughout. * include/debug/string (shrink_to_fit): Redo. * include/ext/vstring.h (shrink_to_fit): Optimize. * include/bits/basic_string.h (shrink_to_fit): Likewise. * testsuite/21_strings/debug/shrink_to_fit.cc: New. * testsuite/23_containers/vector/debug/shrink_to_fit.cc: Likewise. * testsuite/23_containers/vector/debug/bool/shrink_to_fit.cc: Likewise. * testsuite/23_containers/vector/bool/capacity/shrink_to_fit.cc: Likewise. * testsuite/23_containers/deque/debug/shrink_to_fit.cc: Likewise. Co-Authored-By: Paolo Carlini From-SVN: r174967 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 33087235cd3..9462c08c15d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,32 @@ +2011-06-12 François Dumont + Paolo Carlini + + * include/bits/allocator.h (__shrink_to_fit): Rename to + __shrink_to_fit_aux, fix. + * include/bits/stl_vector.h (_M_shrink_to_fit): Declare. + (shrink_to_fit): Use the latter. + * include/debug/vector (shrink_to_fit): Likewise. + * include/bits/vector.tcc (_M_shrink_to_fit): Define. + * include/bits/stl_deque.h (_M_shrink_to_fit): Declare. + (shrink_to_fit): Use the latter. + * include/debug/deque (shrink_to_fit): Likewise. + * include/bits/deque.tcc (_M_shrink_to_fit): Define. + * include/bits/vector.tcc (vector::_M_reallocate): Add. + * include/bits/stl_bvector.h (_M_shrink_to_fit): Declare. + (shrink_to_fit): Use the latter. + (reserve): Use _M_reallocate, move inline. + (_Bvector_base<>::_S_nword): Add, use it throughout. + * include/debug/string (shrink_to_fit): Redo. + * include/ext/vstring.h (shrink_to_fit): Optimize. + * include/bits/basic_string.h (shrink_to_fit): Likewise. + * testsuite/21_strings/debug/shrink_to_fit.cc: New. + * testsuite/23_containers/vector/debug/shrink_to_fit.cc: Likewise. + * testsuite/23_containers/vector/debug/bool/shrink_to_fit.cc: + Likewise. + * testsuite/23_containers/vector/bool/capacity/shrink_to_fit.cc: + Likewise. + * testsuite/23_containers/deque/debug/shrink_to_fit.cc: Likewise. + 2011-06-11 Jonathan Wakely * include/ext/extptr_allocator.h (construct, destroy): Fix for C++0x diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h index 7067fa09bd4..680195082da 100644 --- a/libstdc++-v3/include/bits/allocator.h +++ b/libstdc++-v3/include/bits/allocator.h @@ -184,18 +184,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #ifdef __GXX_EXPERIMENTAL_CXX0X__ + template, + is_nothrow_move_constructible>::value> + struct __shrink_to_fit_aux + { static bool _S_do_it(_Tp&) { return false; } }; + template - bool - __shrink_to_fit(_Tp& __v) + struct __shrink_to_fit_aux<_Tp, true> { - __try - { - _Tp(__v).swap(__v); - return true; - } - __catch(...) - { return false; } - } + static bool + _S_do_it(_Tp& __c) + { + __try + { + _Tp(__make_move_if_noexcept_iterator(__c.begin()), + __make_move_if_noexcept_iterator(__c.end())).swap(__c); + return true; + } + __catch(...) + { return false; } + } + }; template class __alloctr_rebind_helper diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 9279a38cf4c..1022ce08e5a 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -753,10 +753,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void shrink_to_fit() { - __try - { reserve(0); } - __catch(...) - { } + if (capacity() > size()) + { + __try + { reserve(0); } + __catch(...) + { } + } } #endif diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc index 389fc80d945..fab79157cdb 100644 --- a/libstdc++-v3/include/bits/deque.tcc +++ b/libstdc++-v3/include/bits/deque.tcc @@ -325,6 +325,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } } } + + template + bool + deque<_Tp, _Alloc>:: + _M_shrink_to_fit() + { + const difference_type __front_capacity + = (this->_M_impl._M_start._M_cur - this->_M_impl._M_start._M_first); + if (__front_capacity == 0) + return false; + + const difference_type __back_capacity + = (this->_M_impl._M_finish._M_last - this->_M_impl._M_finish._M_cur); + if (__front_capacity + __back_capacity < _S_buffer_size()) + return false; + + return std::__shrink_to_fit_aux::_S_do_it(*this); + } #endif template diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index 30e7b2d9675..22443f4a4c1 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -443,8 +443,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Bit_type* _M_allocate(size_t __n) - { return _M_impl.allocate((__n + int(_S_word_bit) - 1) - / int(_S_word_bit)); } + { return _M_impl.allocate(_S_nword(__n)); } void _M_deallocate() @@ -453,6 +452,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_impl.deallocate(_M_impl._M_start._M_p, _M_impl._M_end_of_storage - _M_impl._M_start._M_p); } + + static size_t + _S_nword(size_t __n) + { return (__n + int(_S_word_bit) - 1) / int(_S_word_bit); } }; _GLIBCXX_END_NAMESPACE_CONTAINER @@ -511,6 +514,7 @@ template protected: using _Base::_M_allocate; using _Base::_M_deallocate; + using _Base::_S_nword; using _Base::_M_get_Bit_allocator; public: @@ -724,7 +728,13 @@ template { _M_range_check(__n); return (*this)[__n]; } void - reserve(size_type __n); + reserve(size_type __n) + { + if (__n > max_size()) + __throw_length_error(__N("vector::reserve")); + if (capacity() < __n) + _M_reallocate(__n); + } reference front() @@ -844,7 +854,7 @@ template #ifdef __GXX_EXPERIMENTAL_CXX0X__ void shrink_to_fit() - { std::__shrink_to_fit(*this); } + { _M_shrink_to_fit(); } #endif void @@ -875,13 +885,19 @@ template _M_initialize(size_type __n) { _Bit_type* __q = this->_M_allocate(__n); - this->_M_impl._M_end_of_storage = (__q - + ((__n + int(_S_word_bit) - 1) - / int(_S_word_bit))); + this->_M_impl._M_end_of_storage = __q + _S_nword(__n); this->_M_impl._M_start = iterator(__q, 0); this->_M_impl._M_finish = this->_M_impl._M_start + difference_type(__n); } + void + _M_reallocate(size_type __n); + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + bool + _M_shrink_to_fit(); +#endif + // Check whether it's an integral type. If so, it's not an iterator. // _GLIBCXX_RESOLVE_LIB_DEFECTS diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index fab63f130c8..6d7a18ca343 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -1196,7 +1196,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** A non-binding request to reduce memory use. */ void shrink_to_fit() - { std::__shrink_to_fit(*this); } + { _M_shrink_to_fit(); } #endif /** @@ -1847,6 +1847,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called by resize(sz). void _M_default_append(size_type __n); + + bool + _M_shrink_to_fit(); #endif //@{ diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 4f617861e8f..929bcbe7ba1 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -646,7 +646,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** A non-binding request to reduce capacity() to size(). */ void shrink_to_fit() - { std::__shrink_to_fit(*this); } + { _M_shrink_to_fit(); } #endif /** @@ -1229,6 +1229,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called by resize(n). void _M_default_append(size_type __n); + + bool + _M_shrink_to_fit(); #endif // Called by insert(p,x) diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index 5b6a8d791ae..fd576dbd2df 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -509,6 +509,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } } } + + template + bool + vector<_Tp, _Alloc>:: + _M_shrink_to_fit() + { + if (capacity() == size()) + return false; + return std::__shrink_to_fit_aux::_S_do_it(*this); + } #endif template @@ -609,24 +619,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // vector - template void vector:: - reserve(size_type __n) + _M_reallocate(size_type __n) { - if (__n > this->max_size()) - __throw_length_error(__N("vector::reserve")); - if (this->capacity() < __n) - { - _Bit_type* __q = this->_M_allocate(__n); - this->_M_impl._M_finish = _M_copy_aligned(begin(), end(), - iterator(__q, 0)); - this->_M_deallocate(); - this->_M_impl._M_start = iterator(__q, 0); - this->_M_impl._M_end_of_storage = (__q + (__n + int(_S_word_bit) - 1) - / int(_S_word_bit)); - } + _Bit_type* __q = this->_M_allocate(__n); + this->_M_impl._M_finish = _M_copy_aligned(begin(), end(), + iterator(__q, 0)); + this->_M_deallocate(); + this->_M_impl._M_start = iterator(__q, 0); + this->_M_impl._M_end_of_storage = __q + _S_nword(__n); } template @@ -654,9 +657,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_finish = std::copy(__position, end(), __i + difference_type(__n)); this->_M_deallocate(); - this->_M_impl._M_end_of_storage = (__q + ((__len - + int(_S_word_bit) - 1) - / int(_S_word_bit))); + this->_M_impl._M_end_of_storage = __q + _S_nword(__len); this->_M_impl._M_start = iterator(__q, 0); } } @@ -689,10 +690,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __i = std::copy(__first, __last, __i); this->_M_impl._M_finish = std::copy(__position, end(), __i); this->_M_deallocate(); - this->_M_impl._M_end_of_storage = (__q - + ((__len - + int(_S_word_bit) - 1) - / int(_S_word_bit))); + this->_M_impl._M_end_of_storage = __q + _S_nword(__len); this->_M_impl._M_start = iterator(__q, 0); } } @@ -720,13 +718,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER *__i++ = __x; this->_M_impl._M_finish = std::copy(__position, end(), __i); this->_M_deallocate(); - this->_M_impl._M_end_of_storage = (__q + ((__len - + int(_S_word_bit) - 1) - / int(_S_word_bit))); + this->_M_impl._M_end_of_storage = __q + _S_nword(__len); this->_M_impl._M_start = iterator(__q, 0); } } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template + bool + vector:: + _M_shrink_to_fit() + { + if (capacity() - size() < int(_S_word_bit)) + return false; + __try + { + _M_reallocate(size()); + return true; + } + __catch(...) + { return false; } + } +#endif + _GLIBCXX_END_NAMESPACE_CONTAINER } // namespace std diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque index 749fc2e6cab..5b6bdeb544a 100644 --- a/libstdc++-v3/include/debug/deque +++ b/libstdc++-v3/include/debug/deque @@ -277,7 +277,12 @@ namespace __debug #endif #ifdef __GXX_EXPERIMENTAL_CXX0X__ - using _Base::shrink_to_fit; + void + shrink_to_fit() + { + if (_Base::_M_shrink_to_fit()) + this->_M_invalidate_all(); + } #endif using _Base::empty; diff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string index b6d2b4b34ea..9e0ad61bdef 100644 --- a/libstdc++-v3/include/debug/string +++ b/libstdc++-v3/include/debug/string @@ -237,7 +237,20 @@ namespace __gnu_debug { this->resize(__n, _CharT()); } #ifdef __GXX_EXPERIMENTAL_CXX0X__ - using _Base::shrink_to_fit; + void + shrink_to_fit() + { + if (capacity() > size()) + { + __try + { + reserve(0); + this->_M_invalidate_all(); + } + __catch(...) + { } + } + } #endif using _Base::capacity; diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector index 6072515dac3..1b80974d38c 100644 --- a/libstdc++-v3/include/debug/vector +++ b/libstdc++-v3/include/debug/vector @@ -280,7 +280,15 @@ namespace __debug #endif #ifdef __GXX_EXPERIMENTAL_CXX0X__ - using _Base::shrink_to_fit; + void + shrink_to_fit() + { + if (_Base::_M_shrink_to_fit()) + { + _M_guaranteed_capacity = _Base::capacity(); + this->_M_invalidate_all(); + } + } #endif size_type diff --git a/libstdc++-v3/include/ext/vstring.h b/libstdc++-v3/include/ext/vstring.h index a84336861a7..b0b3e2efa53 100644 --- a/libstdc++-v3/include/ext/vstring.h +++ b/libstdc++-v3/include/ext/vstring.h @@ -465,10 +465,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void shrink_to_fit() { - __try - { this->reserve(0); } - __catch(...) - { } + if (capacity() > size()) + { + __try + { this->reserve(0); } + __catch(...) + { } + } } #endif diff --git a/libstdc++-v3/testsuite/21_strings/debug/shrink_to_fit.cc b/libstdc++-v3/testsuite/21_strings/debug/shrink_to_fit.cc new file mode 100644 index 00000000000..e2c85be268c --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/debug/shrink_to_fit.cc @@ -0,0 +1,39 @@ +// Copyright (C) 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . +// +// { dg-options "-std=gnu++0x" } +// { dg-do run { xfail *-*-* } } + +#include + +void test01() +{ + using __gnu_debug::string; + string s; + s.reserve(2); + s.push_back('a'); + string::iterator it = s.begin(); + s.shrink_to_fit(); + // Following line should assert + *it = 'z'; +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/deque/debug/shrink_to_fit.cc b/libstdc++-v3/testsuite/23_containers/deque/debug/shrink_to_fit.cc new file mode 100644 index 00000000000..4cce4bd3739 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/debug/shrink_to_fit.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . +// +// { dg-require-debug-mode "" } +// { dg-options "-std=gnu++0x" } +// { dg-do run { xfail *-*-* } } + +#include + +void test01() +{ + using std::deque; + deque d; + // Lets generate a hole at the begining of the deque: + d.push_back(0); + d.push_back(1); + d.pop_front(); + deque::iterator it; + do + { + d.push_back(2); + it = d.begin(); + auto old_abegin = &*d.begin(); + d.shrink_to_fit(); + if (&*d.begin() != old_abegin) + break; + } + while (true); + // Following line should assert + *it = 2; +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/shrink_to_fit.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/shrink_to_fit.cc new file mode 100644 index 00000000000..c3ae90e981a --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/shrink_to_fit.cc @@ -0,0 +1,40 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + std::vector vb(__CHAR_BIT__ * sizeof(unsigned long) + 1); + vb.pop_back(); + + auto old_capacity = vb.capacity(); + vb.shrink_to_fit(); + VERIFY( vb.capacity() < old_capacity ); + VERIFY( vb.size() == vb.capacity() ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/bool/shrink_to_fit.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/bool/shrink_to_fit.cc new file mode 100644 index 00000000000..8206e0e567b --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/bool/shrink_to_fit.cc @@ -0,0 +1,42 @@ +// Copyright (C) 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . +// +// { dg-require-debug-mode "" } +// { dg-options "-std=gnu++0x" } +// { dg-do run { xfail *-*-* } } + +#include + +void test01() +{ + using std::vector; + + vector vb(__CHAR_BIT__ * sizeof(unsigned long) + 1); + vb.pop_back(); + + vector::iterator it = vb.begin(); + vb.shrink_to_fit(); + + // Following line should assert + *it = true; +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/shrink_to_fit.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/shrink_to_fit.cc new file mode 100644 index 00000000000..969c79a283e --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/shrink_to_fit.cc @@ -0,0 +1,40 @@ +// Copyright (C) 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . +// +// { dg-require-debug-mode "" } +// { dg-options "-std=gnu++0x" } +// { dg-do run { xfail *-*-* } } + +#include + +void test01() +{ + using std::vector; + vector v; + v.reserve(2); + v.push_back(0); + vector::iterator it = v.begin(); + v.shrink_to_fit(); + // Following line should assert + *it = 1; +} + +int main() +{ + test01(); + return 0; +}