[PATCH][Hashtable 0/6] Code review

2019-11-17 Thread François Dumont

This is the begining of a patch series for _Hashtable

Initial patch to clarify code. I was tired to see true/false or 
true_type/false_type without knowing what was true/false.


I also made code more consistent by chosing to specialize methods 
through usage of __unique_keys_t/__multi_keys_t rather than calling them 
_M_[multi]_XXX.



    * include/bits/hashtable_policy.h (__detail::__unique_keys_t): New.
    (__detail::__multi_keys_t): New.
    (__detail::__constant_iterators_t): New.
    (__detail::__mutable_iterators_t): New.
    (__detail::__hash_cached_t): New.
    (__detail::__hash_not_cached_t): New.
    (_Hash_node<>): Change _Cache_hash_code template parameter from bool to
    typename. Adapt partial specializations.
    (_Node_iterator_base<>): Likewise.
    (operator==(const _Node_iterator_base<>&,const 
_Node_iterator_base<>&)):

    Adapt.
    (operator!=(const _Node_iterator_base<>&,const 
_Node_iterator_base<>&)):

    Adapt.
    (_Node_iterator<>): Change __constant_iterators and __cache template
    parameters from bool to typename.
    (_Node_const_iterator<>): Likewise.
    (_Map_base<>): Change _Unique_keys template parameter from bool to
    typename. Adapt partial specializations.
    (_Insert<>): Change _Constant_iterators template parameter from bool to
    typename. Adapt partial specializations.
    (_Local_iterator_base<>): Change __cache_hash_code template parameter
    from bool to typename. Adapt partial specialization.
    (_Hash_code_base<>): Likewise.
    (operator==(const _Local_iterator_base<>&,
    const _Local_iterator_base<>&)): Adapt.
    (operator!=(const _Local_iterator_base<>&,
    const _Local_iterator_base<>&)):
    Adapt.
    (_Local_iterator<>): Change __constant_iterators and __cache template
    parameters from bool to typename.
    (_Local_const_iterator<>): Likewise.
    (_Hashtable_base<>): Adapt.
    (_Equal_hash_code<>): Adapt.
    (_Equality<>): Adapt.
    * include/bits/hashtable.h (_Hashtable<>): Replace occurences of
    true_type/false_type by respoectively __unique_type_t/__multi_type_t.
    (_M_insert_unique_node(const key_type&, size_t, __hash_code,
    __node_type*, size_t)): Replace by...
    (_M_insert_node(__unique_keys_t, size_t, __hash_code, __node_type*,
    size_t)): ...this.
    (_M_insert_muti_node(__node_type*, const key_type&, __hash_code,
    __node_type*)): Replace by...
    (_M_insert_node(__multi_keys_t, __node_type*, __hash_code,
    __node_type*)): ...this.
    (_M_reinsert_node(node_type&&)): Replace by...
    (_M_reinsert_node(node_type&&, __unique_keys_t)): ...this.
    (_M_reinsert_node(const_iterator, node_type&&, __unique_keys_t)): New,
    forward to latter.
    (_M_reinsert_node_multi(const_iterator, node_type&&)): Replace by...
    (_M_reinsert_node(const_iterator, node_type&&, __multi_keys_t)):
    ...this.
    (_M_reinsert_node(node_type&&, __multi_keys_t)): New, forward to 
latter.

    (_M_reinsert_node(node_type&&)): New, use latters.
    (_M_reinsert_node(const_iterator, node_type&&)): Likewise.
    (_M_merge_unique(_Compatible_Hashtable&)): Replace by...
    (_M_merge(__unique_keys_t, _Compatible_Hashtable&)): ...this.
    (_M_merge_multi(_Compatible_Hashtable&)): Replace by...
    (_M_merge(__multi_keys_t, _Compatible_Hashtable&)): ...this.
    (_M_merge(_Compatible_Hashtable&)): New, use latters.
    * include/bits/unordered_map.h
    (unordered_map<>::insert(const_iterator, node_type&&)): Adapt.
    (unordered_map<>::merge(unordered_map<>&)): Adapt.
(unordered_map<>::merge(unordered_multimap<>&)): Adapt.
    (unordered_multimap<>::insert(node_type&&)): Adapt.
    (unordered_multimap<>::insert(const_iterator, node_type&&)): Adapt.
(unordered_multimap<>::merge(unordered_multimap<>&)): Adapt.
(unordered_multimap<>::merge(unordered_map<>&)): Adapt.
    * include/bits/unordered_set.h
    (unordered_set<>::insert(const_iterator, node_type&&)): Adapt.
    (unordered_set<>::merge(unordered_set<>&)): Adapt.
(unordered_set<>::merge(unordered_multiset<>&)): Adapt.
    (unordered_multiset<>::insert(node_type&&)): Adapt.
    (unordered_multiset<>::insert(const_iterator, node_type&&)): Adapt.
(unordered_multiset<>::merge(unordered_multiset<>&)): Adapt.
(unordered_multiset<>::merge(unordered_set<>&)): Adapt.

Tested under Linux x86_64.

François

diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index c2b2219d471..ef71c090f3b 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -184,7 +184,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   private __detail::_Hashtable_alloc<
 	__alloc_rebind<_Alloc,
 		   __detail::_Hash_node<_Value,
-	_Traits::__hash_cached::value>>>
+	typename _Traits::__hash_cached>>>
 {
   static_assert(is_same::type, _Value>::value,
 	  "unordered container must have a non-const, non-volatile value_type");
@@ -195,7 +195,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   using __traits_type = _Tra

Re: [PATCH][Hashtable 0/6] Code review

2019-12-09 Thread François Dumont

This patch also require an update of the printers.py file.

Here is an updated version.

François

On 11/17/19 9:42 PM, François Dumont wrote:

This is the begining of a patch series for _Hashtable

Initial patch to clarify code. I was tired to see true/false or 
true_type/false_type without knowing what was true/false.


I also made code more consistent by chosing to specialize methods 
through usage of __unique_keys_t/__multi_keys_t rather than calling 
them _M_[multi]_XXX.



    * include/bits/hashtable_policy.h (__detail::__unique_keys_t): New.
    (__detail::__multi_keys_t): New.
    (__detail::__constant_iterators_t): New.
    (__detail::__mutable_iterators_t): New.
    (__detail::__hash_cached_t): New.
    (__detail::__hash_not_cached_t): New.
    (_Hash_node<>): Change _Cache_hash_code template parameter from 
bool to

    typename. Adapt partial specializations.
    (_Node_iterator_base<>): Likewise.
    (operator==(const _Node_iterator_base<>&,const 
_Node_iterator_base<>&)):

    Adapt.
    (operator!=(const _Node_iterator_base<>&,const 
_Node_iterator_base<>&)):

    Adapt.
    (_Node_iterator<>): Change __constant_iterators and __cache template
    parameters from bool to typename.
    (_Node_const_iterator<>): Likewise.
    (_Map_base<>): Change _Unique_keys template parameter from bool to
    typename. Adapt partial specializations.
    (_Insert<>): Change _Constant_iterators template parameter from 
bool to

    typename. Adapt partial specializations.
    (_Local_iterator_base<>): Change __cache_hash_code template parameter
    from bool to typename. Adapt partial specialization.
    (_Hash_code_base<>): Likewise.
    (operator==(const _Local_iterator_base<>&,
    const _Local_iterator_base<>&)): Adapt.
    (operator!=(const _Local_iterator_base<>&,
    const _Local_iterator_base<>&)):
    Adapt.
    (_Local_iterator<>): Change __constant_iterators and __cache template
    parameters from bool to typename.
    (_Local_const_iterator<>): Likewise.
    (_Hashtable_base<>): Adapt.
    (_Equal_hash_code<>): Adapt.
    (_Equality<>): Adapt.
    * include/bits/hashtable.h (_Hashtable<>): Replace occurences of
    true_type/false_type by respoectively __unique_type_t/__multi_type_t.
    (_M_insert_unique_node(const key_type&, size_t, __hash_code,
    __node_type*, size_t)): Replace by...
    (_M_insert_node(__unique_keys_t, size_t, __hash_code, __node_type*,
    size_t)): ...this.
    (_M_insert_muti_node(__node_type*, const key_type&, __hash_code,
    __node_type*)): Replace by...
    (_M_insert_node(__multi_keys_t, __node_type*, __hash_code,
    __node_type*)): ...this.
    (_M_reinsert_node(node_type&&)): Replace by...
    (_M_reinsert_node(node_type&&, __unique_keys_t)): ...this.
    (_M_reinsert_node(const_iterator, node_type&&, __unique_keys_t)): 
New,

    forward to latter.
    (_M_reinsert_node_multi(const_iterator, node_type&&)): Replace by...
    (_M_reinsert_node(const_iterator, node_type&&, __multi_keys_t)):
    ...this.
    (_M_reinsert_node(node_type&&, __multi_keys_t)): New, forward to 
latter.

    (_M_reinsert_node(node_type&&)): New, use latters.
    (_M_reinsert_node(const_iterator, node_type&&)): Likewise.
    (_M_merge_unique(_Compatible_Hashtable&)): Replace by...
    (_M_merge(__unique_keys_t, _Compatible_Hashtable&)): ...this.
    (_M_merge_multi(_Compatible_Hashtable&)): Replace by...
    (_M_merge(__multi_keys_t, _Compatible_Hashtable&)): ...this.
    (_M_merge(_Compatible_Hashtable&)): New, use latters.
    * include/bits/unordered_map.h
    (unordered_map<>::insert(const_iterator, node_type&&)): Adapt.
    (unordered_map<>::merge(unordered_map<>&)): Adapt.
(unordered_map<>::merge(unordered_multimap<>&)): Adapt.
    (unordered_multimap<>::insert(node_type&&)): Adapt.
    (unordered_multimap<>::insert(const_iterator, node_type&&)): Adapt.
(unordered_multimap<>::merge(unordered_multimap<>&)): Adapt.
(unordered_multimap<>::merge(unordered_map<>&)): Adapt.
    * include/bits/unordered_set.h
    (unordered_set<>::insert(const_iterator, node_type&&)): Adapt.
    (unordered_set<>::merge(unordered_set<>&)): Adapt.
(unordered_set<>::merge(unordered_multiset<>&)): Adapt.
    (unordered_multiset<>::insert(node_type&&)): Adapt.
    (unordered_multiset<>::insert(const_iterator, node_type&&)): Adapt.
(unordered_multiset<>::merge(unordered_multiset<>&)): Adapt.
(unordered_multiset<>::merge(unordered_set<>&)): Adapt.

Tested under Linux x86_64.

François



diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index c2b2219d471..ef71c090f3b 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -184,7 +184,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   private __detail::_Hashtable_alloc<
 	__alloc_rebind<_Alloc,
 		   __detail::_Hash_node<_Value,
-	_Traits::__hash_cached::value>>>
+	typename _Traits::__hash_cached>>>
 {
   static_assert(is_same::type, _Value>::value,
 	  "unorde

Re: [PATCH][Hashtable 0/6] Code review

2019-12-19 Thread François Dumont
After further work on pretty printers I prefer to stay closer to what is 
done currently. It works better with another patch I'll submit one day.


The drawback is that I needed to consider versioned namespace in 
template parameters passed to lookup_templ_spec.


François


On 12/9/19 10:15 PM, François Dumont wrote:

This patch also require an update of the printers.py file.

Here is an updated version.

François

On 11/17/19 9:42 PM, François Dumont wrote:

This is the begining of a patch series for _Hashtable

Initial patch to clarify code. I was tired to see true/false or 
true_type/false_type without knowing what was true/false.


I also made code more consistent by chosing to specialize methods 
through usage of __unique_keys_t/__multi_keys_t rather than calling 
them _M_[multi]_XXX.



    * include/bits/hashtable_policy.h (__detail::__unique_keys_t): New.
    (__detail::__multi_keys_t): New.
    (__detail::__constant_iterators_t): New.
    (__detail::__mutable_iterators_t): New.
    (__detail::__hash_cached_t): New.
    (__detail::__hash_not_cached_t): New.
    (_Hash_node<>): Change _Cache_hash_code template parameter from 
bool to

    typename. Adapt partial specializations.
    (_Node_iterator_base<>): Likewise.
    (operator==(const _Node_iterator_base<>&,const 
_Node_iterator_base<>&)):

    Adapt.
    (operator!=(const _Node_iterator_base<>&,const 
_Node_iterator_base<>&)):

    Adapt.
    (_Node_iterator<>): Change __constant_iterators and __cache template
    parameters from bool to typename.
    (_Node_const_iterator<>): Likewise.
    (_Map_base<>): Change _Unique_keys template parameter from bool to
    typename. Adapt partial specializations.
    (_Insert<>): Change _Constant_iterators template parameter from 
bool to

    typename. Adapt partial specializations.
    (_Local_iterator_base<>): Change __cache_hash_code template 
parameter

    from bool to typename. Adapt partial specialization.
    (_Hash_code_base<>): Likewise.
    (operator==(const _Local_iterator_base<>&,
    const _Local_iterator_base<>&)): Adapt.
    (operator!=(const _Local_iterator_base<>&,
    const _Local_iterator_base<>&)):
    Adapt.
    (_Local_iterator<>): Change __constant_iterators and __cache 
template

    parameters from bool to typename.
    (_Local_const_iterator<>): Likewise.
    (_Hashtable_base<>): Adapt.
    (_Equal_hash_code<>): Adapt.
    (_Equality<>): Adapt.
    * include/bits/hashtable.h (_Hashtable<>): Replace occurences of
    true_type/false_type by respoectively 
__unique_type_t/__multi_type_t.

    (_M_insert_unique_node(const key_type&, size_t, __hash_code,
    __node_type*, size_t)): Replace by...
    (_M_insert_node(__unique_keys_t, size_t, __hash_code, __node_type*,
    size_t)): ...this.
    (_M_insert_muti_node(__node_type*, const key_type&, __hash_code,
    __node_type*)): Replace by...
    (_M_insert_node(__multi_keys_t, __node_type*, __hash_code,
    __node_type*)): ...this.
    (_M_reinsert_node(node_type&&)): Replace by...
    (_M_reinsert_node(node_type&&, __unique_keys_t)): ...this.
    (_M_reinsert_node(const_iterator, node_type&&, __unique_keys_t)): 
New,

    forward to latter.
    (_M_reinsert_node_multi(const_iterator, node_type&&)): Replace by...
    (_M_reinsert_node(const_iterator, node_type&&, __multi_keys_t)):
    ...this.
    (_M_reinsert_node(node_type&&, __multi_keys_t)): New, forward to 
latter.

    (_M_reinsert_node(node_type&&)): New, use latters.
    (_M_reinsert_node(const_iterator, node_type&&)): Likewise.
    (_M_merge_unique(_Compatible_Hashtable&)): Replace by...
    (_M_merge(__unique_keys_t, _Compatible_Hashtable&)): ...this.
    (_M_merge_multi(_Compatible_Hashtable&)): Replace by...
    (_M_merge(__multi_keys_t, _Compatible_Hashtable&)): ...this.
    (_M_merge(_Compatible_Hashtable&)): New, use latters.
    * include/bits/unordered_map.h
    (unordered_map<>::insert(const_iterator, node_type&&)): Adapt.
    (unordered_map<>::merge(unordered_map<>&)): Adapt.
(unordered_map<>::merge(unordered_multimap<>&)): Adapt.
    (unordered_multimap<>::insert(node_type&&)): Adapt.
    (unordered_multimap<>::insert(const_iterator, node_type&&)): Adapt.
(unordered_multimap<>::merge(unordered_multimap<>&)): Adapt.
(unordered_multimap<>::merge(unordered_map<>&)): Adapt.
    * include/bits/unordered_set.h
    (unordered_set<>::insert(const_iterator, node_type&&)): Adapt.
    (unordered_set<>::merge(unordered_set<>&)): Adapt.
(unordered_set<>::merge(unordered_multiset<>&)): Adapt.
    (unordered_multiset<>::insert(node_type&&)): Adapt.
    (unordered_multiset<>::insert(const_iterator, node_type&&)): Adapt.
(unordered_multiset<>::merge(unordered_multiset<>&)): Adapt.
(unordered_multiset<>::merge(unordered_set<>&)): Adapt.

Tested under Linux x86_64.

François





diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index c2b2219d471..f57e9ac0638 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/ha

Re: [PATCH][Hashtable 0/6] Code review

2020-07-17 Thread Jonathan Wakely via Gcc-patches

N.B. the 0/6 entry of a patch series is supposed to be a cover letter
describing the changes in the series, not one of the patches.

If you have patches 0/6, 1/6, 2/6 ... 6/6 then you actually have seven
patches, not six!

Anyway ...

On 19/12/19 20:17 +0100, François Dumont wrote:

diff --git a/libstdc++-v3/include/bits/hashtable_policy.h 
b/libstdc++-v3/include/bits/hashtable_policy.h
index f5809c7443a..b9320506bb2 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -172,6 +172,14 @@ namespace __detail

  // Auxiliary types used for all instantiations of _Hashtable nodes
  // and iterators.
+  using __unique_keys_t = true_type;
+  using __multi_keys_t = false_type;
+
+  using __constant_iterators_t = true_type;
+  using __mutable_iterators_t = false_type;
+
+  using __hash_cached_t = true_type;
+  using __hash_not_cached_t = false_type;


This is an ABI change, and the benefit doesn't seem large enough to
justify it. It will result in code size increases for anything that
links objects compiled before and after the change.

If we wanted to do this, I think it would be better to use enums, so:

enum _Unique_keys { __unique_keys, __multi_keys };

Otherwise you can use __hash_cached_t where __unique_keys_t is meant
to be used, so all you've done is introduce more names for the same
things.

If you want to replace the 'true' and 'false' literals with something
more descriptive, can't you just use constants?

constexpr bool __hash_cached = true;
constexpr bool __hash_not_cached = false;

Or just use comments:

struct _Local_iterator_base<_Key, _Value, _ExtractKey,
_H1, _H2, _Hash, /*cached=*/ false>




Re: [PATCH][Hashtable 0/6] Code review

2020-07-29 Thread François Dumont via Gcc-patches

On 17/07/20 12:11 pm, Jonathan Wakely wrote:

N.B. the 0/6 entry of a patch series is supposed to be a cover letter
describing the changes in the series, not one of the patches.

If you have patches 0/6, 1/6, 2/6 ... 6/6 then you actually have seven
patches, not six!

Anyway ...

On 19/12/19 20:17 +0100, François Dumont wrote:
diff --git a/libstdc++-v3/include/bits/hashtable_policy.h 
b/libstdc++-v3/include/bits/hashtable_policy.h

index f5809c7443a..b9320506bb2 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -172,6 +172,14 @@ namespace __detail

  // Auxiliary types used for all instantiations of _Hashtable nodes
  // and iterators.
+  using __unique_keys_t = true_type;
+  using __multi_keys_t = false_type;
+
+  using __constant_iterators_t = true_type;
+  using __mutable_iterators_t = false_type;
+
+  using __hash_cached_t = true_type;
+  using __hash_not_cached_t = false_type;


This is an ABI change, and the benefit doesn't seem large enough to
justify it. It will result in code size increases for anything that
links objects compiled before and after the change.

If we wanted to do this, I think it would be better to use enums, so:

enum _Unique_keys { __unique_keys, __multi_keys };

Otherwise you can use __hash_cached_t where __unique_keys_t is meant
to be used, so all you've done is introduce more names for the same
things.

If you want to replace the 'true' and 'false' literals with something
more descriptive, can't you just use constants?

constexpr bool __hash_cached = true;
constexpr bool __hash_not_cached = false;

Or just use comments:

    struct _Local_iterator_base<_Key, _Value, _ExtractKey,
    _H1, _H2, _Hash, /*cached=*/ false>



Ok, I'll review this patch with this simpler approach.

I even started to add comments in the patch you already approved.