Re: [patch] fix libstdc++/56267 - local iterator requirements

2014-01-21 Thread Jonathan Wakely
On 20 January 2014 21:11, François Dumont frs.dum...@gmail.com wrote:
 On 01/20/2014 04:53 PM, Jonathan Wakely wrote:

 With this new design couldn't we change the conditions that are used to
 decide when to cache the hash code. I haven't study it in detail but it
 looks like the default constructible constraint could be removed, no ?

Ah yes, I forgot about that part, I'll update the __cache_default
definition. Thanks.


Re: [patch] fix libstdc++/56267 - local iterator requirements

2014-01-21 Thread Jonathan Wakely
On 21 January 2014 10:00, Jonathan Wakely wrote:
 On 20 January 2014 21:11, François Dumont frs.dum...@gmail.com wrote:
 On 01/20/2014 04:53 PM, Jonathan Wakely wrote:

 With this new design couldn't we change the conditions that are used to
 decide when to cache the hash code. I haven't study it in detail but it
 looks like the default constructible constraint could be removed, no ?

 Ah yes, I forgot about that part, I'll update the __cache_default
 definition. Thanks.

Like so. Tested x86_64-linux, committed to trunk.

2014-01-21  Jonathan Wakely  jwak...@redhat.com

PR libstdc++/56267
* include/bits/hashtable.h (__cache_default): Do not depend on
whether the hash function is DefaultConstructible or CopyAssignable.
(_Hashtable): Adjust static assertions.
* doc/xml/manual/containers.xml (containers.unordered.cache): Update.
* testsuite/23_containers/unordered_set/instantiation_neg.cc: Adjust
dg-error line number.
* testsuite/23_containers/unordered_set/
not_default_constructible_hash_neg.cc: Remove.
commit 0efc402079788226108bce180c478d4c85924fd4
Author: Jonathan Wakely jwak...@redhat.com
Date:   Tue Jan 21 18:20:24 2014 +

PR libstdc++/56267
* include/bits/hashtable.h (__cache_default): Do not depend on
whether the hash function is DefaultConstructible or CopyAssignable.
(_Hashtable): Adjust static assertions.
* doc/xml/manual/containers.xml (containers.unordered.cache): Update.
* testsuite/23_containers/unordered_set/instantiation_neg.cc: Adjust
dg-error line number.
* testsuite/23_containers/unordered_set/
not_default_constructible_hash_neg.cc: Remove.

diff --git a/libstdc++-v3/doc/xml/manual/containers.xml 
b/libstdc++-v3/doc/xml/manual/containers.xml
index 9791953..653033d 100644
--- a/libstdc++-v3/doc/xml/manual/containers.xml
+++ b/libstdc++-v3/doc/xml/manual/containers.xml
@@ -420,7 +420,7 @@
   the hash code every time it's needed can improve performance, but the
   additional memory overhead can also reduce performance, so whether an
   unordered associative container caches the hash code or not depends on
-  a number of factors. The caching policy for GCC 4.8 is described below.
+  the properties described below.
 /para
 para
   The C++ standard requires that codeerase/code and codeswap/code
@@ -432,23 +432,8 @@
   or codethrow()/code.
 /para
 para
-  Secondly, libstdc++ also needs the hash code in the implementation of
-  codelocal_iterator/code and codeconst_local_iterator/code in
-  order to know when the iterator has reached the end of the bucket.
-  This means that the local iterator types will embed a copy of the hash
-  function when possible.
-  Because the local iterator types must be DefaultConstructible and
-  CopyAssignable, if the hash function type does not model those concepts
-  then it cannot be embedded and so the hash code must be cached.
-  Note that a hash function might not be safe to use when
-  default-constructed (e.g if it a function pointer) so a hash
-  function that is contained in a local iterator won't be used until
-  the iterator is valid, so the hash function has been copied from a
-  correctly-initialized object.
-/para
-para
-  If the hash function is non-throwing, DefaultConstructible and
-  CopyAssignable then libstdc++ doesn't need to cache the hash code for
+  If the hash function is non-throwing then libstdc++ doesn't need to
+  cache the hash code for
   correctness, but might still do so for performance if computing a
   hash code is an expensive operation, as it may be for arbitrarily
   long strings.
diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index e427c7f..4297c5f 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -42,10 +42,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 using __cache_default
   =  __not___and_// Do not cache for fast hasher.
   __is_fast_hash_Hash,
-  // Mandatory to make local_iterator default
-  // constructible and assignable.
-  is_default_constructible_Hash,
-  is_copy_assignable_Hash,
   // Mandatory to have erase not throwing.
   __detail::__is_noexcept_hash_Tp, _Hash;
 
@@ -282,22 +278,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
Functor used to map hash code to bucket index
 must be default constructible);
 
-  // When hash codes are not cached local iterator inherits from
-  // __hash_code_base above to compute node bucket index so it has to be
-  // default constructible.
-  static_assert(__if_hash_not_cached
-   

Re: [patch] fix libstdc++/56267 - local iterator requirements

2014-01-20 Thread Jonathan Wakely
On 17 January 2014 15:11, Jonathan Wakely wrote:
 The issue in PR 56267 is that unordered_xxx::local_iterator sometimes
 inherits from the user-defined hash function (via _Hash_code_base,
 which inherits from the hash function to use the EBO), and
 local_iterator must be DefaultConstructible and Assignable, even when
 the hash function isn't.

 My solution is to remove the inheritance from _Hash_code_base, and
 instead construct/destroy the _Hash_code_base in a block of
 uninitialized memory (via __gnu_cxx::__aligned_buffer). This would
 mean we can't use the EBO and increase the size of local_iterator, and
 past measurements have shown that the unordered containers'
 performance is sensitive to such changes, so there's a partial
 specialization that doesn't have the __aligned_buffer member for the
 case where the _Hash_code_base is empty and needs no storage.

 François, do you have any comments on this? Can you see a better solution?

 While working on this I decided I didn't like everything in
 _Local_iterator_base being public, so I added some accessors to the
 only members that are needed by unrelated types.

Tested x86_64-linux and committed to trunk.

2014-01-20  Jonathan Wakely  jwak...@redhat.com

PR libstdc++/56267
* include/bits/hashtable_policy.h (_Hash_code_base... false): Grant
friendship to _Local_iterator_base..., false.
(_Local_iterator_base): Give protected access to all existing members.
(_Local_iterator_base::_M_curr()): New public accessor.
(_Local_iterator_base::_M_get_bucket()): New public accessor.
(_Local_iterator_base..., false::_M_init()): New function to manage
the lifetime of the _Hash_code_base explicitly.
(_Local_iterator_base..., false::_M_destroy()): Likewise.
(_Local_iterator_base..., false): Define copy constructor and copy
assignment operator that use new functions to manage _Hash_code_base.
(operator==(const _Local_iterator_base, const _Local_iterator_base),
operator==(const _Local_iterator_base, const _Local_iterator_base)):
Use public API for _Local_iterator_base.
* include/debug/safe_local_iterator.h (_Safe_local_iterator): Likewise.
* include/debug/unordered_map (__debug::unordered_map::erase(),
__debug::unordered_multimap::erase()): Likewise.
* include/debug/unordered_set (__debug::unordered_set::erase(),
__debug::unordered_multiset::erase()): Likewise.
* testsuite/23_containers/unordered_set/56267-2.cc: New test.


Re: [patch] fix libstdc++/56267 - local iterator requirements

2014-01-20 Thread François Dumont

On 01/20/2014 04:53 PM, Jonathan Wakely wrote:

On 17 January 2014 15:11, Jonathan Wakely wrote:

The issue in PR 56267 is that unordered_xxx::local_iterator sometimes
inherits from the user-defined hash function (via _Hash_code_base,
which inherits from the hash function to use the EBO), and
local_iterator must be DefaultConstructible and Assignable, even when
the hash function isn't.

My solution is to remove the inheritance from _Hash_code_base, and
instead construct/destroy the _Hash_code_base in a block of
uninitialized memory (via __gnu_cxx::__aligned_buffer). This would
mean we can't use the EBO and increase the size of local_iterator, and
past measurements have shown that the unordered containers'
performance is sensitive to such changes, so there's a partial
specialization that doesn't have the __aligned_buffer member for the
case where the _Hash_code_base is empty and needs no storage.

François, do you have any comments on this? Can you see a better solution?

While working on this I decided I didn't like everything in
_Local_iterator_base being public, so I added some accessors to the
only members that are needed by unrelated types.

Tested x86_64-linux and committed to trunk.

2014-01-20  Jonathan Wakely  jwak...@redhat.com

 PR libstdc++/56267
 * include/bits/hashtable_policy.h (_Hash_code_base... false): Grant
 friendship to _Local_iterator_base..., false.
 (_Local_iterator_base): Give protected access to all existing members.
 (_Local_iterator_base::_M_curr()): New public accessor.
 (_Local_iterator_base::_M_get_bucket()): New public accessor.
 (_Local_iterator_base..., false::_M_init()): New function to manage
 the lifetime of the _Hash_code_base explicitly.
 (_Local_iterator_base..., false::_M_destroy()): Likewise.
 (_Local_iterator_base..., false): Define copy constructor and copy
 assignment operator that use new functions to manage _Hash_code_base.
 (operator==(const _Local_iterator_base, const _Local_iterator_base),
 operator==(const _Local_iterator_base, const _Local_iterator_base)):
 Use public API for _Local_iterator_base.
 * include/debug/safe_local_iterator.h (_Safe_local_iterator): Likewise.
 * include/debug/unordered_map (__debug::unordered_map::erase(),
 __debug::unordered_multimap::erase()): Likewise.
 * include/debug/unordered_set (__debug::unordered_set::erase(),
 __debug::unordered_multiset::erase()): Likewise.
 * testsuite/23_containers/unordered_set/56267-2.cc: New test.



I considered that it was an acceptable constraint on the hash functor 
but if it is not Standard compliant then the solution is good and I 
cannot think about another one.


With this new design couldn't we change the conditions that are used to 
decide when to cache the hash code. I haven't study it in detail but it 
looks like the default constructible constraint could be removed, no ?


François



[patch] fix libstdc++/56267 - local iterator requirements

2014-01-17 Thread Jonathan Wakely
The issue in PR 56267 is that unordered_xxx::local_iterator sometimes
inherits from the user-defined hash function (via _Hash_code_base,
which inherits from the hash function to use the EBO), and
local_iterator must be DefaultConstructible and Assignable, even when
the hash function isn't.

My solution is to remove the inheritance from _Hash_code_base, and
instead construct/destroy the _Hash_code_base in a block of
uninitialized memory (via __gnu_cxx::__aligned_buffer). This would
mean we can't use the EBO and increase the size of local_iterator, and
past measurements have shown that the unordered containers'
performance is sensitive to such changes, so there's a partial
specialization that doesn't have the __aligned_buffer member for the
case where the _Hash_code_base is empty and needs no storage.

François, do you have any comments on this? Can you see a better solution?

While working on this I decided I didn't like everything in
_Local_iterator_base being public, so I added some accessors to the
only members that are needed by unrelated types.

2014-01-17  Jonathan Wakely  jwak...@redhat.com

PR libstdc++/56267
* include/bits/hashtable_policy.h (_Local_iterator_base): Give
protected access to all existing members.
(_Local_iterator_base::_M_curr()): New public accessor.
(_Local_iterator_base::_M_get_bucket()): New public accessor.
(_Local_iterator_base..., false::_M_init()): New function to manage
the lifetime of the _Hash_code_base explicitly.
(_Local_iterator_base..., false::_M_destroy()): Likewise.
(_Local_iterator_base..., false): Define copy constructor and copy
assignment operator that use new functions to manage _Hash_code_base.
(operator==(const _Local_iterator_base, const _Local_iterator_base),
operator==(const _Local_iterator_base, const _Local_iterator_base)):
Use public API for _Local_iterator_base.
* include/debug/safe_local_iterator.h (_Safe_local_iterator): Likewise.
* include/debug/unordered_map (__debug::unordered_map::erase(),
__debug::unordered_multimap::erase()): Likewise.
* include/debug/unordered_set (__debug::unordered_set::erase(),
__debug::unordered_multiset::erase()): Likewise.
* testsuite/23_containers/unordered_set/56267-2.cc: New test.
commit f9c852223230da4e4fc761f72905c7acacfa4399
Author: Jonathan Wakely jwak...@redhat.com
Date:   Fri Jan 17 15:10:48 2014 +

PR libstdc++/56267
* include/bits/hashtable_policy.h (_Local_iterator_base): Give
protected access to all existing members.
(_Local_iterator_base::_M_curr()): New public accessor.
(_Local_iterator_base::_M_get_bucket()): New public accessor.
(operator==(const _Local_iterator_base, const _Local_iterator_base),
operator==(const _Local_iterator_base, const _Local_iterator_base)):
Use public API for _Local_iterator_base.
* include/debug/safe_local_iterator.h (_Safe_local_iterator): Likewise.
* include/debug/unordered_map (__debug::unordered_map::erase(),
__debug::unordered_multimap::erase()): Likewise.
* include/debug/unordered_set (__debug::unordered_set::erase(),
__debug::unordered_multiset::erase()): Likewise.
* testsuite/23_containers/unordered_set/56267-2.cc: New test.

diff --git a/libstdc++-v3/include/bits/hashtable_policy.h 
b/libstdc++-v3/include/bits/hashtable_policy.h
index f64d2d3..817b190 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -1145,6 +1145,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   using __ebo_h1 = _Hashtable_ebo_helper1, _H1;
   using __ebo_h2 = _Hashtable_ebo_helper2, _H2;
 
+  // Gives the local iterator implementation access to _M_bucket_index().
+  friend struct _Local_iterator_base_Key, _Value, _ExtractKey, _H1, _H2,
+_Default_ranged_hash, false;
+
 public:
   typedef _H1  hasher;
 
@@ -1225,7 +1229,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   private _Hashtable_ebo_helper2, _H2
 {
 private:
-  // Gives access to _M_h2() to the local iterator implementation.
+  // Gives the local iterator implementation access to _M_h2().
   friend struct _Local_iterator_base_Key, _Value, _ExtractKey, _H1, _H2,
 _Default_ranged_hash, true;
 
@@ -1331,7 +1335,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   };
 
 
-  /// Specialization.
+  /// Partial specialization used when nodes contain a cached hash code.
   templatetypename _Key, typename _Value, typename _ExtractKey,
   typename _H1, typename _H2, typename _Hash
 struct _Local_iterator_base_Key, _Value, _ExtractKey,
@@ -1343,7 +1347,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   using __hash_code_base = _Hash_code_base_Key, _Value, _ExtractKey,
   _H1, _H2, _Hash, true;
 
-public: