Changeset 1d5424a in mainline
- Timestamp:
- 2018-07-05T21:41:21Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- ac68088
- Parents:
- 7320ca6
- git-author:
- Dzejrou <dzejrou@…> (2018-04-24 16:10:29)
- git-committer:
- Dzejrou <dzejrou@…> (2018-07-05 21:41:21)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/cpp/include/internal/hash_table.hpp
r7320ca6 r1d5424a 79 79 list_node<Value>* head; 80 80 81 hash_table_bucket() 82 : head{} 83 { /* DUMMY BODY */ } 84 81 85 Size size() const noexcept 82 86 { … … 104 108 void clear() 105 109 { 110 if (!head) 111 return; 112 106 113 auto current = head; 107 114 do … … 176 183 return 0; 177 184 } 185 186 template<class Table, class Key> 187 static pair< 188 typename Table::iterator, 189 typename Table::iterator 190 > equal_range(Table& table, const Key& key) 191 { 192 auto it = table.find(key); 193 return make_pair(it, it); 194 } 195 196 template<class Table, class Key> 197 static pair< 198 typename Table::const_iterator, 199 typename Table::const_iterator 200 > equal_range_const(Table& table, const Key& key) 201 { // Note: We cannot overload by return type, so we use a different name. 202 auto it = table.find(key); 203 return make_pair(it, it); 204 } 178 205 }; 179 206 … … 215 242 { 216 243 // TODO: erase all items with given key 244 } 245 246 template<class Table, class Key> 247 static pair< 248 typename Table::iterator, 249 typename Table::iterator 250 > equal_range(Table& table, const Key& key) 251 { 252 // TODO: implement 253 } 254 255 template<class Table, class Key> 256 static pair< 257 typename Table::const_iterator, 258 typename Table::const_iterator 259 > equal_range_const(Table& table, const Key& key) 260 { 261 // TODO: implement 217 262 } 218 263 }; … … 656 701 657 702 hash_table(size_type buckets, float max_load_factor = 1.f) 658 : table_{new hash_table_bucket<value_type, size_type>[buckets] },703 : table_{new hash_table_bucket<value_type, size_type>[buckets]()}, 659 704 bucket_count_{buckets}, size_{}, hasher_{}, key_eq_{}, 660 705 key_extractor_{}, max_load_factor_{max_load_factor} … … 714 759 715 760 template<class Allocator, class... Args> 716 iterator emplace(Allocator& alloc, Args&&... args) 717 { 718 // TODO: implement 719 } 720 721 void insert(const hint_type& where, const value_type& val) 761 void emplace(const hint_type& where, Allocator& alloc, Args&&... args) 722 762 { 723 763 if (!hint_ok_(where)) 724 764 return; 725 765 726 auto node = new list_node<value_type>{ val};766 auto node = new list_node<value_type>{forward<Args&&>(args)...}; 727 767 if (get<1>(where) == nullptr) // Append here will create a new head. 728 768 get<0>(where)->append(node); 729 769 else // Prepending before an exact position is common in the standard. 770 get<1>(where)->prepend(node); 771 772 ++size_; 773 // TODO: if we go over max load factor, rehash 774 } 775 776 void insert(const hint_type& where, const value_type& val) 777 { 778 if (!hint_ok_(where)) 779 return; 780 781 auto node = new list_node<value_type>{val}; 782 if (get<1>(where) == nullptr) 783 get<0>(where)->append(node); 784 else 730 785 get<1>(where)->prepend(node); 731 786 … … 787 842 } 788 843 789 template<class Allocator>790 844 void swap(hash_table& other) 791 noexcept(allocator_traits< Allocator>::is_always_equal::value &&845 noexcept(allocator_traits<allocator_type>::is_always_equal::value && 792 846 noexcept(swap(declval<Hasher&>(), declval<Hasher&>())) && 793 847 noexcept(swap(declval<KeyEq&>(), declval<KeyEq&>()))) … … 813 867 iterator find(const key_type& key) 814 868 { 815 // TODO: implement 869 auto idx = get_bucket_idx_(key); 870 auto head = table_[idx].head; 871 872 if (!head) 873 return end(); 874 875 auto current = head; 876 do 877 { 878 if (key_eq_(key, key_extractor_(current->value))) 879 return iterator{table_, idx, size_, current}; 880 current = current->next; 881 } 882 while (current != head); 883 884 return end(); 816 885 } 817 886 818 887 const_iterator find(const key_type& key) const 819 888 { 820 // TODO: implement 889 auto idx = get_bucket_idx_(key); 890 auto head = table_[idx].head; 891 892 if (!head) 893 return end(); 894 895 auto current = head; 896 do 897 { 898 if (key_eq_(key, key_extractor_(current->value))) 899 return iterator{table_, idx, size_, current}; 900 current = current->next; 901 } 902 while (current != head); 903 904 return end(); 821 905 } 822 906 … … 828 912 pair<iterator, iterator> equal_range(const key_type& key) 829 913 { 830 // TODO: implement914 return Policy::equal_range(*this, key); 831 915 } 832 916 833 917 pair<const_iterator, const_iterator> equal_range(const key_type& key) const 834 918 { 835 // TODO: implement919 return Policy::equal_range_const(*this, key); 836 920 } 837 921 … … 903 987 * can have no effect. 904 988 */ 905 } 906 907 void rehash(size_type n) 908 { 909 // TODO: implement 910 // TODO: exception thrown in rehash means the rehash 911 // has no effect, so we create a new table, insert in it 912 // and then swap 913 } 914 915 void reserve(size_type n) 916 { 917 // TODO: implement 989 // TODO: change max factor and rehash if needed 990 } 991 992 void rehash(size_type count) 993 { 994 if (count < size_ / max_load_factor_) 995 count = size_ / max_load_factor_; 996 997 // Note: This is the only place where an exception can be 998 // thrown (no mem) in this function, so wrap it 999 // in try-catch-rethrow. 1000 hash_table new_table{count, max_load_factor_}; 1001 1002 for (std::size_t i = 0; i < bucket_count_; ++i) 1003 { 1004 auto head = table_[i].head; 1005 if (!head) 1006 continue; 1007 1008 auto current = head; 1009 1010 do 1011 { 1012 auto next = current->next; 1013 1014 current->next = current; 1015 current->prev = current; 1016 1017 auto where = Policy::find_insertion_spot( 1018 new_table, key_extractor_(current->value) 1019 ); 1020 1021 /** 1022 * Note: We're rehashing, so we know each 1023 * key can be inserted. 1024 */ 1025 auto new_bucket = get<0>(where); 1026 auto new_successor = get<1>(where); 1027 1028 if (new_successor) 1029 new_successor->append(current); 1030 else 1031 new_bucket->append(current); 1032 1033 current = next; 1034 } while (current != head); 1035 1036 table_[i].head = nullptr; 1037 } 1038 1039 new_table.size_ = size_; 1040 swap(new_table); 1041 1042 delete[] new_table.table_; 1043 new_table.table_ = nullptr; 1044 } 1045 1046 void reserve(size_type count) 1047 { 1048 rehash(count / max_load_factor_ + 1); 918 1049 } 919 1050 … … 927 1058 { 928 1059 // Lists are deleted in ~hash_table_bucket. 929 delete[] table_; 1060 if (table_) 1061 delete[] table_; 930 1062 } 931 1063 … … 966 1098 // that is something like: 967 1099 // return get<1>(hint)->prev->key == key || !bucket.contains(key) 1100 // TODO: also, make it public and make hint usage one level above? 1101 // (since we already have insert with decisive hint) 968 1102 return get<0>(hint) != nullptr && get<2>(hint) < bucket_count_; 969 1103 }
Note:
See TracChangeset
for help on using the changeset viewer.