From d8bbd665a18c584a2d7f7b8a20582b4426ac3739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Dumont?= Date: Sun, 25 Sep 2016 20:26:02 +0000 Subject: [PATCH] debug.cc: Include debug/vector. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2016-09-25 François Dumont * src/c++11/debug.cc: Include debug/vector. Include cctype. Remove functional. (get_safe_base_mutex): Get mutex based on address lowest non nil bits. * testsuite/23_containers/vector/debug/mutex_association.cc: New. From-SVN: r240479 --- libstdc++-v3/ChangeLog | 5 + libstdc++-v3/src/c++11/debug.cc | 105 ++++++++++-------- .../vector/debug/mutex_association.cc | 42 +++++++ 3 files changed, 105 insertions(+), 47 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 47a52b52656..6f134cbe2e2 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,10 @@ 2016-09-25 François Dumont + * src/c++11/debug.cc: Include debug/vector. Include cctype. Remove + functional. + (get_safe_base_mutex): Get mutex based on address lowest non nil bits. + * testsuite/23_containers/vector/debug/mutex_association.cc: New. + * include/debug/bitset (bitset::reference::reference(const _Base_ref&, bitset*)): Remove __unused__ attribute. * include/debug/safe_base.h (_Safe_iterator_base): Make diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc index f25304c5310..f58e829c47a 100644 --- a/libstdc++-v3/src/c++11/debug.cc +++ b/libstdc++-v3/src/c++11/debug.cc @@ -30,12 +30,13 @@ #include #include #include +#include #include #include +#include // for std::isspace #include // for std::min -#include // for _Hash_impl #include // for __cxa_demangle @@ -47,11 +48,16 @@ namespace * in order to limit contention without breaking current library binary * compatibility. */ __gnu_cxx::__mutex& - get_safe_base_mutex(void* __address) + get_safe_base_mutex(void* address) { const size_t mask = 0xf; static __gnu_cxx::__mutex safe_base_mutex[mask + 1]; - const size_t index = _Hash_impl::hash(__address) & mask; + + // Use arbitrarily __gnu_debug::vector as the container giving + // alignment of debug containers. + const auto alignbits = __builtin_ctz(alignof(__gnu_debug::vector)); + const size_t index + = (reinterpret_cast(address) >> alignbits) & mask; return safe_base_mutex[index]; } @@ -70,8 +76,8 @@ namespace } void - swap_seq(__gnu_debug::_Safe_sequence_base& __lhs, - __gnu_debug::_Safe_sequence_base& __rhs) + swap_seq_single(__gnu_debug::_Safe_sequence_base& __lhs, + __gnu_debug::_Safe_sequence_base& __rhs) { swap(__lhs._M_version, __rhs._M_version); swap_its(__lhs, __lhs._M_iterators, @@ -80,17 +86,58 @@ namespace __rhs, __rhs._M_const_iterators); } + template + void + lock_and_run(__gnu_cxx::__mutex& lhs_mutex, __gnu_cxx::__mutex& rhs_mutex, + _Action action) + { + // We need to lock both sequences to run action. + if (&lhs_mutex == &rhs_mutex) + { + __gnu_cxx::__scoped_lock sentry(lhs_mutex); + action(); + } + else + { + __gnu_cxx::__scoped_lock sentry1(&lhs_mutex < &rhs_mutex + ? lhs_mutex : rhs_mutex); + __gnu_cxx::__scoped_lock sentry2(&lhs_mutex < &rhs_mutex + ? rhs_mutex : lhs_mutex); + action(); + } + } + void - swap_ucont(__gnu_debug::_Safe_unordered_container_base& __lhs, - __gnu_debug::_Safe_unordered_container_base& __rhs) + swap_seq(__gnu_cxx::__mutex& lhs_mutex, + __gnu_debug::_Safe_sequence_base& lhs, + __gnu_cxx::__mutex& rhs_mutex, + __gnu_debug::_Safe_sequence_base& rhs) { - swap_seq(__lhs, __rhs); + lock_and_run(lhs_mutex, rhs_mutex, + [&lhs, &rhs]() { swap_seq_single(lhs, rhs); }); + } + + void + swap_ucont_single(__gnu_debug::_Safe_unordered_container_base& __lhs, + __gnu_debug::_Safe_unordered_container_base& __rhs) + { + swap_seq_single(__lhs, __rhs); swap_its(__lhs, __lhs._M_local_iterators, __rhs, __rhs._M_local_iterators); swap_its(__lhs, __lhs._M_const_local_iterators, __rhs, __rhs._M_const_local_iterators); } + void + swap_ucont(__gnu_cxx::__mutex& lhs_mutex, + __gnu_debug::_Safe_unordered_container_base& lhs, + __gnu_cxx::__mutex& rhs_mutex, + __gnu_debug::_Safe_unordered_container_base& rhs) + { + lock_and_run(lhs_mutex, rhs_mutex, + [&lhs, &rhs]() { swap_ucont_single(lhs, rhs); }); + } + void detach_all(__gnu_debug::_Safe_iterator_base* __iter) { @@ -242,25 +289,7 @@ namespace __gnu_debug void _Safe_sequence_base:: _M_swap(_Safe_sequence_base& __x) noexcept - { - // We need to lock both sequences to swap - using namespace __gnu_cxx; - __mutex *__this_mutex = &_M_get_mutex(); - __mutex *__x_mutex = &__x._M_get_mutex(); - if (__this_mutex == __x_mutex) - { - __scoped_lock __lock(*__this_mutex); - swap_seq(*this, __x); - } - else - { - __scoped_lock __l1(__this_mutex < __x_mutex - ? *__this_mutex : *__x_mutex); - __scoped_lock __l2(__this_mutex < __x_mutex - ? *__x_mutex : *__this_mutex); - swap_seq(*this, __x); - } - } + { swap_seq(_M_get_mutex(), *this, __x._M_get_mutex(), __x); } __gnu_cxx::__mutex& _Safe_sequence_base:: @@ -384,7 +413,7 @@ namespace __gnu_debug __gnu_cxx::__mutex& _Safe_iterator_base:: _M_get_mutex() throw () - { return get_safe_base_mutex(_M_sequence); } + { return _M_sequence->_M_get_mutex(); } _Safe_unordered_container_base* _Safe_local_iterator_base:: @@ -462,25 +491,7 @@ namespace __gnu_debug void _Safe_unordered_container_base:: _M_swap(_Safe_unordered_container_base& __x) noexcept - { - // We need to lock both containers to swap - using namespace __gnu_cxx; - __mutex *__this_mutex = &_M_get_mutex(); - __mutex *__x_mutex = &__x._M_get_mutex(); - if (__this_mutex == __x_mutex) - { - __scoped_lock __lock(*__this_mutex); - swap_ucont(*this, __x); - } - else - { - __scoped_lock __l1(__this_mutex < __x_mutex - ? *__this_mutex : *__x_mutex); - __scoped_lock __l2(__this_mutex < __x_mutex - ? *__x_mutex : *__this_mutex); - swap_ucont(*this, __x); - } - } + { swap_ucont(_M_get_mutex(), *this, __x._M_get_mutex(), __x); } void _Safe_unordered_container_base:: diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc new file mode 100644 index 00000000000..a3c56e2ca5d --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc @@ -0,0 +1,42 @@ +// Copyright (C) 2016 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 + +#include + +class container : public __gnu_debug::_Safe_sequence +{ +public: + __gnu_cxx::__mutex& + get_mutex() + { return this->_M_get_mutex(); } +}; + +int +main() +{ + std::set<__gnu_cxx::__mutex*> mutexes; + container conts[17]; + + for (int i = 0; i != 16; ++i) + VERIFY( mutexes.insert(&conts[i].get_mutex()).second ); + + VERIFY( !mutexes.insert(&conts[16].get_mutex()).second ); +}