debug.cc: Include debug/vector.
2016-09-25 François Dumont <fdumont@gcc.gnu.org> * 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
This commit is contained in:
parent
5d04532430
commit
d8bbd665a1
@ -1,5 +1,10 @@
|
||||
2016-09-25 François Dumont <fdumont@gcc.gnu.org>
|
||||
|
||||
* 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
|
||||
|
@ -30,12 +30,13 @@
|
||||
#include <debug/safe_unordered_base.h>
|
||||
#include <debug/safe_iterator.h>
|
||||
#include <debug/safe_local_iterator.h>
|
||||
#include <debug/vector>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cctype> // for std::isspace
|
||||
|
||||
#include <algorithm> // for std::min
|
||||
#include <functional> // for _Hash_impl
|
||||
|
||||
#include <cxxabi.h> // 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<int> as the container giving
|
||||
// alignment of debug containers.
|
||||
const auto alignbits = __builtin_ctz(alignof(__gnu_debug::vector<int>));
|
||||
const size_t index
|
||||
= (reinterpret_cast<std::size_t>(address) >> alignbits) & mask;
|
||||
return safe_base_mutex[index];
|
||||
}
|
||||
|
||||
@ -70,7 +76,7 @@ namespace
|
||||
}
|
||||
|
||||
void
|
||||
swap_seq(__gnu_debug::_Safe_sequence_base& __lhs,
|
||||
swap_seq_single(__gnu_debug::_Safe_sequence_base& __lhs,
|
||||
__gnu_debug::_Safe_sequence_base& __rhs)
|
||||
{
|
||||
swap(__lhs._M_version, __rhs._M_version);
|
||||
@ -80,17 +86,58 @@ namespace
|
||||
__rhs, __rhs._M_const_iterators);
|
||||
}
|
||||
|
||||
template<typename _Action>
|
||||
void
|
||||
swap_ucont(__gnu_debug::_Safe_unordered_container_base& __lhs,
|
||||
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_seq(__gnu_cxx::__mutex& lhs_mutex,
|
||||
__gnu_debug::_Safe_sequence_base& lhs,
|
||||
__gnu_cxx::__mutex& rhs_mutex,
|
||||
__gnu_debug::_Safe_sequence_base& 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(__lhs, __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::
|
||||
|
@ -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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#include <set>
|
||||
#include <debug/vector>
|
||||
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
class container : public __gnu_debug::_Safe_sequence<container>
|
||||
{
|
||||
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 );
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user