Ignore:
Timestamp:
2018-07-05T21:41:21Z (6 years ago)
Author:
Dzejrou <dzejrou@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2d46556
Parents:
e037873d
git-author:
Dzejrou <dzejrou@…> (2018-04-26 15:12:10)
git-committer:
Dzejrou <dzejrou@…> (2018-07-05 21:41:21)
Message:

cpp: moved more logic to the policies, since a lot of the code added to unordered_map was the same as in unordered_set

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/cpp/include/internal/hash_table.hpp

    re037873d r492377a  
    215215            return make_pair(it, ++it);
    216216        }
     217
     218        /**
     219         * Note: We have to duplicate code for emplace, insert(const&)
     220         *       and insert(&&) here, because the node (which makes distinction
     221         *       between the arguments) is only created if the value isn't
     222         *       in the table already.
     223         */
     224
     225        template<class Table, class... Args>
     226        static pair<
     227            typename Table::iterator, bool
     228        > emplace(Table& table, Args&&... args)
     229        {
     230            using value_type = typename Table::value_type;
     231            using node_type  = typename Table::node_type;
     232            using iterator   = typename Table::iterator;
     233
     234            table.increment_size();
     235
     236            auto val = value_type{forward<Args>(args)...};
     237            const auto& key = table.get_key(val);
     238            auto [bucket, target, idx] = table.find_insertion_spot(key);
     239
     240            if (!bucket)
     241                return make_pair(table.end(), false);
     242
     243            if (target && table.keys_equal(key, target->value))
     244            {
     245                table.decrement_size();
     246
     247                return make_pair(
     248                    iterator{
     249                        table.table(), idx, table.bucket_count(),
     250                        target
     251                    },
     252                    false
     253                );
     254            }
     255            else
     256            {
     257                auto node = new node_type{move(val)};
     258                bucket->prepend(node);
     259
     260                return make_pair(iterator{
     261                    table.table(), idx,
     262                    table.bucket_count(),
     263                    node
     264                }, true);
     265            }
     266        }
     267
     268        template<class Table, class Value>
     269        static pair<
     270            typename Table::iterator, bool
     271        > insert(Table& table, const Value& val)
     272        {
     273            using node_type  = typename Table::node_type;
     274            using iterator   = typename Table::iterator;
     275
     276            table.increment_size();
     277
     278            const auto& key = table.get_key(val);
     279            auto [bucket, target, idx] = table.find_insertion_spot(key);
     280
     281            if (!bucket)
     282                return make_pair(table.end(), false);
     283
     284            if (target && table.keys_equal(key, target->value))
     285            {
     286                table.decrement_size();
     287
     288                return make_pair(
     289                    iterator{
     290                        table.table(), idx, table.bucket_count(),
     291                        target
     292                    },
     293                    false
     294                );
     295            }
     296            else
     297            {
     298                auto node = new node_type{val};
     299                bucket->prepend(node);
     300
     301                return make_pair(iterator{
     302                    table.table(), idx,
     303                    table.bucket_count(),
     304                    node
     305                }, true);
     306            }
     307        }
     308
     309        template<class Table, class Value>
     310        static pair<
     311            typename Table::iterator, bool
     312        > insert(Table& table, Value&& val)
     313        {
     314            using value_type = typename Table::value_type;
     315            using node_type  = typename Table::node_type;
     316            using iterator   = typename Table::iterator;
     317
     318            table.increment_size();
     319
     320            const auto& key = table.get_key(val);
     321            auto [bucket, target, idx] = table.find_insertion_spot(key);
     322
     323            if (!bucket)
     324                return make_pair(table.end(), false);
     325
     326            if (target && table.keys_equal(key, target->value))
     327            {
     328                table.decrement_size();
     329
     330                return make_pair(
     331                    iterator{
     332                        table.table(), idx, table.bucket_count(),
     333                        target
     334                    },
     335                    false
     336                );
     337            }
     338            else
     339            {
     340                auto node = new node_type{forward<value_type>(val)};
     341                bucket->prepend(node);
     342
     343                return make_pair(iterator{
     344                    table.table(), idx,
     345                    table.bucket_count(),
     346                    node
     347                }, true);
     348            }
     349        }
    217350    };
    218351
     
    340473            return make_pair(first, last);
    341474        }
     475
     476        template<class Table, class... Args>
     477        static pair<
     478            typename Table::iterator, bool
     479        > emplace(Table& table, Args&&... args)
     480        {
     481            using node_type  = typename Table::node_type;
     482
     483            auto node = new node_type{forward<Args>(args)...};
     484
     485            return insert(table, node);
     486        }
     487
     488        template<class Table, class Value>
     489        static pair<
     490            typename Table::iterator, bool
     491        > insert(Table& table, const Value& val)
     492        {
     493            using node_type  = typename Table::node_type;
     494
     495            auto node = new node_type{val};
     496
     497            return insert(table, node);
     498        }
     499
     500        template<class Table, class Value>
     501        static pair<
     502            typename Table::iterator, bool
     503        > insert(Table& table, Value&& val)
     504        {
     505            using value_type = typename Table::value_type;
     506            using node_type  = typename Table::node_type;
     507
     508            auto node = new node_type{forward<value_type>(val)};
     509
     510            return insert(table, node);
     511        }
     512
     513        template<class Table>
     514        static pair<
     515            typename Table::iterator, bool
     516        > insert(Table& table, typename Table::node_type* node)
     517        {
     518            using iterator   = typename Table::iterator;
     519
     520            table.increment_size();
     521
     522            const auto& key = table.get_key(node->value);
     523            auto [bucket, target, idx] = table.find_insertion_spot(key);
     524
     525            if (!bucket)
     526                return make_pair(table.end(), false);
     527
     528            if (target && table.keys_equal(key, target->value))
     529                target->append(node);
     530            else
     531                bucket->prepend(node);
     532
     533            return make_pair(iterator{
     534                table.table(), idx,
     535                table.bucket_count(),
     536                node
     537            }, true);
     538        }
    342539    };
    343540
     
    8851082            }
    8861083
    887             template<class Allocator, class... Args>
    888             void emplace(const hint_type& where, Allocator& alloc, Args&&... args)
    889             {
    890                 if (!hint_ok_(where))
    891                     return;
    892 
    893                 auto node = new list_node<value_type>{forward<Args&&>(args)...};
    894                 if (get<1>(where) == nullptr) // Append here will create a new head.
    895                     get<0>(where)->append(node);
    896                 else // Prepending before an exact position is common in the standard.
    897                     get<1>(where)->prepend(node);
    898 
    899                 ++size_;
    900 
    901                 rehash_if_needed();
    902             }
    903 
    904             void insert(const hint_type& where, const value_type& val)
    905             {
    906                 if (!hint_ok_(where))
    907                     return;
    908 
    909                 auto node = new list_node<value_type>{val};
    910                 if (get<1>(where) == nullptr)
    911                     get<0>(where)->append(node);
    912                 else
    913                     get<1>(where)->prepend(node);
    914 
    915                 ++size_;
    916 
    917                 rehash_if_needed();
    918             }
    919 
    920             void insert(const hint_type& where, value_type&& val)
    921             {
    922                 if (!hint_ok_(where))
    923                     return;
    924 
    925                 auto node = new list_node<value_type>{forward<value_type>(val)};
    926                 if (get<1>(where) == nullptr)
    927                     get<0>(where)->append(node);
    928                 else
    929                     get<1>(where)->prepend(node);
    930 
    931                 ++size_;
    932 
    933                 rehash_if_needed();
     1084            template<class... Args>
     1085            pair<iterator, bool> emplace(Args&&... args)
     1086            {
     1087                return Policy::emplace(*this, forward<Args>(args)...);
     1088            }
     1089
     1090            pair<iterator, bool> insert(const value_type& val)
     1091            {
     1092                return Policy::insert(*this, val);
     1093            }
     1094
     1095            pair<iterator, bool> insert(value_type&& val)
     1096            {
     1097                return Policy::insert(*this, forward<value_type>(val));
    9341098            }
    9351099
     
    12511415            }
    12521416
    1253             node_type* find_node_or_return_head(const key_type& key,
    1254                                                 const hash_table_bucket<value_type, size_type>& bucket)
    1255             {
    1256                 if (bucket.head)
    1257                 {
    1258                     auto head = bucket.head;
    1259                     auto current = bucket.head;
    1260 
    1261                     do
    1262                     {
    1263                         if (keys_equal(key, current->value))
    1264                             return current;
    1265                         else
    1266                             current = current->next;
    1267                     }
    1268                     while (current != head);
    1269 
    1270                     return head;
    1271                 }
    1272                 else
    1273                     return nullptr;
    1274             }
    1275 
    12761417        private:
    12771418            hash_table_bucket<value_type, size_type>* table_;
     
    12901431            }
    12911432
    1292             bool hint_ok_(const hint_type& hint)
    1293             {
    1294                 // TODO: pass this to the policy, because the multi policy
    1295                 //       will need to check if a similar key is close,
    1296                 //       that is something like:
    1297                 //          return get<1>(hint)->prev->key == key || !bucket.contains(key)
    1298                 // TODO: also, make it public and make hint usage one level above?
    1299                 //       (since we already have insert with decisive hint)
    1300                 return get<0>(hint) != nullptr && get<2>(hint) < bucket_count_;
    1301             }
    1302 
    1303             // Praise C++11 for this.
    13041433            friend Policy;
    13051434    };
Note: See TracChangeset for help on using the changeset viewer.