131 typedef TKey value_type;
132 typedef TKey key_type;
133 typedef THash hasher;
134 typedef TKeyEqual key_equal;
135 typedef value_type& reference;
136 typedef const value_type& const_reference;
138 typedef value_type&& rvalue_reference;
140 typedef value_type* pointer;
141 typedef const value_type* const_pointer;
142 typedef size_t size_type;
144 typedef const TKey& key_parameter_t;
150 struct node_t :
public link_t
152 node_t(const_reference key_)
160 friend bool operator==(
const node_t& lhs,
const node_t& rhs)
162 return (lhs.key == rhs.key);
165 friend bool operator!=(
const node_t& lhs,
const node_t& rhs)
167 return !(lhs == rhs);
178 typedef typename bucket_t::iterator local_iterator;
179 typedef typename bucket_t::const_iterator const_local_iterator;
182 class iterator :
public etl::iterator<ETL_OR_STD::forward_iterator_tag, TKey>
186 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, TKey>::value_type value_type;
187 typedef typename iunordered_multiset::key_type key_type;
188 typedef typename iunordered_multiset::hasher hasher;
189 typedef typename iunordered_multiset::key_equal key_equal;
190 typedef typename iunordered_multiset::reference reference;
191 typedef typename iunordered_multiset::const_reference const_reference;
192 typedef typename iunordered_multiset::pointer pointer;
193 typedef typename iunordered_multiset::const_pointer const_pointer;
194 typedef typename iunordered_multiset::size_type size_type;
196 friend class iunordered_multiset;
197 friend class const_iterator;
203 iterator(
const iterator& other)
204 : pbuckets_end(other.pbuckets_end)
205 , pbucket(other.pbucket)
211 iterator& operator++()
216 if (inode == pbucket->end())
220 while ((pbucket != pbuckets_end) && (pbucket->empty()))
226 if (pbucket != pbuckets_end)
228 inode = pbucket->begin();
236 iterator operator++(
int)
238 iterator temp(*
this);
244 iterator& operator=(
const iterator& other)
246 pbuckets_end = other.pbuckets_end;
247 pbucket = other.pbucket;
253 reference operator*()
const
259 pointer operator&()
const
261 return &(inode->key);
265 pointer operator->()
const
267 return &(inode->key);
271 friend bool operator==(
const iterator& lhs,
const iterator& rhs)
273 return lhs.compare(rhs);
277 friend bool operator!=(
const iterator& lhs,
const iterator& rhs)
279 return !(lhs == rhs);
285 iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
286 : pbuckets_end(pbuckets_end_)
293 bool compare(
const iterator& rhs)
const
295 return rhs.inode == inode;
299 bucket_t& get_bucket()
305 bucket_t*& get_bucket_list_iterator()
311 local_iterator get_local_iterator()
316 bucket_t* pbuckets_end;
318 local_iterator inode;
322 class const_iterator :
public etl::iterator<ETL_OR_STD::forward_iterator_tag, const TKey>
326 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, const TKey>::value_type value_type;
327 typedef typename iunordered_multiset::key_type key_type;
328 typedef typename iunordered_multiset::hasher hasher;
329 typedef typename iunordered_multiset::key_equal key_equal;
330 typedef typename iunordered_multiset::reference reference;
331 typedef typename iunordered_multiset::const_reference const_reference;
332 typedef typename iunordered_multiset::pointer pointer;
333 typedef typename iunordered_multiset::const_pointer const_pointer;
334 typedef typename iunordered_multiset::size_type size_type;
336 friend class iunordered_multiset;
337 friend class iterator;
344 : pbuckets_end(other.pbuckets_end)
345 , pbucket(other.pbucket)
351 const_iterator(
const const_iterator& other)
352 : pbuckets_end(other.pbuckets_end)
353 , pbucket(other.pbucket)
359 const_iterator& operator++()
364 if (inode == pbucket->end())
369 while ((pbucket != pbuckets_end) && (pbucket->empty()))
375 if (pbucket != pbuckets_end)
377 inode = pbucket->begin();
385 const_iterator operator++(
int)
387 const_iterator temp(*
this);
393 const_iterator& operator=(
const const_iterator& other)
395 pbuckets_end = other.pbuckets_end;
396 pbucket = other.pbucket;
402 const_reference operator*()
const
408 const_pointer operator&()
const
410 return &(inode->key);
414 const_pointer operator->()
const
416 return &(inode->key);
420 friend bool operator==(
const const_iterator& lhs,
const const_iterator& rhs)
422 return lhs.compare(rhs);
426 friend bool operator!=(
const const_iterator& lhs,
const const_iterator& rhs)
428 return !(lhs == rhs);
434 const_iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
435 : pbuckets_end(pbuckets_end_)
442 bool compare(
const const_iterator& rhs)
const
444 return rhs.inode == inode;
448 bucket_t& get_bucket()
454 bucket_t*& get_bucket_list_iterator()
460 local_iterator get_local_iterator()
465 bucket_t* pbuckets_end;
467 local_iterator inode;
470 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
478 return iterator((pbuckets + number_of_buckets), first, first->begin());
487 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
496 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
505 return pbuckets[i].begin();
514 const_local_iterator
begin(
size_t i)
const
516 return pbuckets[i].cbegin();
525 const_local_iterator
cbegin(
size_t i)
const
527 return pbuckets[i].cbegin();
536 return iterator((pbuckets + number_of_buckets), last, last->end());
543 const_iterator
end()
const
545 return const_iterator((pbuckets + number_of_buckets), last, last->end());
554 return const_iterator((pbuckets + number_of_buckets), last, last->end());
561 local_iterator
end(
size_t i)
563 return pbuckets[i].end();
570 const_local_iterator
end(
size_t i)
const
572 return pbuckets[i].cend();
579 const_local_iterator
cend(
size_t i)
const
581 return pbuckets[i].cend();
590 return key_hash_function(key) % number_of_buckets;
598 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
601 return key_hash_function(key) % number_of_buckets;
611 size_t index = bucket(key);
613 return etl::distance(pbuckets[index].
begin(), pbuckets[index].
end());
621 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
624 size_t index = bucket(key);
626 return etl::distance(pbuckets[index].
begin(), pbuckets[index].
end());
636 return number_of_buckets;
645 return number_of_buckets;
657 template <
typename TIterator>
658 void assign(TIterator first_, TIterator last_)
660#if ETL_IS_DEBUG_BUILD
661 difference_type d = etl::distance(first_, last_);
668 while (first_ != last_)
681 ETL_OR_STD::pair<iterator, bool>
insert(const_reference key)
683 ETL_OR_STD::pair<iterator, bool> result(
end(),
false);
691 bucket_t* pbucket = pbuckets + index;
692 bucket_t& bucket = *pbucket;
698 node_t* node = allocate_data_node();
700 ::new (&node->key) value_type(key);
701 ETL_INCREMENT_DEBUG_COUNT;
705 adjust_first_last_markers_after_insert(&bucket);
707 result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->
begin());
708 result.second =
true;
714 local_iterator inode = bucket.
begin();
716 while (inode != bucket.
end())
719 if (key_equal_function(inode->key, key))
729 node_t* node = allocate_data_node();
731 ::new (&node->key) value_type(key);
732 ETL_INCREMENT_DEBUG_COUNT;
736 adjust_first_last_markers_after_insert(&bucket);
739 result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
740 result.second =
true;
753 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
754 ETL_OR_STD::pair<iterator, bool>
insert(
const K& key)
756 ETL_OR_STD::pair<iterator, bool> result(
end(),
false);
764 bucket_t* pbucket = pbuckets + index;
765 bucket_t& bucket = *pbucket;
771 node_t* node = allocate_data_node();
774 ETL_INCREMENT_DEBUG_COUNT;
777 bucket.insert_after(bucket.before_begin(), *node);
778 adjust_first_last_markers_after_insert(&bucket);
780 result.first =
iterator((pbuckets + number_of_buckets), pbucket, pbucket->
begin());
781 result.second = true;
786 local_iterator inode_previous = bucket.before_begin();
787 local_iterator inode = bucket.begin();
789 while (inode != bucket.end())
792 if (key_equal_function(inode->key, key))
802 node_t* node = allocate_data_node();
804 ::new (&node->key) value_type(key);
805 ETL_INCREMENT_DEBUG_COUNT;
808 bucket.insert_after(inode_previous, *node);
809 adjust_first_last_markers_after_insert(&bucket);
812 result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
813 result.second = true;
827 ETL_OR_STD::pair<iterator, bool>
insert(rvalue_reference key)
829 ETL_OR_STD::pair<iterator, bool> result(
end(),
false);
837 bucket_t* pbucket = pbuckets + index;
838 bucket_t& bucket = *pbucket;
844 node_t* node = allocate_data_node();
846 ::new (&node->key) value_type(
etl::move(key));
847 ETL_INCREMENT_DEBUG_COUNT;
850 bucket.insert_after(bucket.before_begin(), *node);
851 adjust_first_last_markers_after_insert(&bucket);
853 result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->
begin());
854 result.second = true;
859 local_iterator inode_previous = bucket.before_begin();
860 local_iterator inode = bucket.begin();
862 while (inode != bucket.end())
865 if (key_equal_function(inode->key, key))
875 node_t* node = allocate_data_node();
877 ::new (&node->key) value_type(etl::move(key));
878 ETL_INCREMENT_DEBUG_COUNT;
881 bucket.insert_after(inode_previous, *node);
882 adjust_first_last_markers_after_insert(&bucket);
885 result.first =
iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
886 result.second = true;
900 iterator
insert(const_iterator , const_reference key)
913 template <
class TIterator>
914 void insert(TIterator first_, TIterator last_)
916 while (first_ != last_)
923#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
927 template <
typename... Args>
935 node_t* node = allocate_data_node();
938 ETL_INCREMENT_DEBUG_COUNT;
940 key_parameter_t key = node->key;
946 bucket_t* pbucket = pbuckets + index;
947 bucket_t& bucket = *pbucket;
953 bucket.insert_after(bucket.before_begin(), *node);
954 adjust_first_last_markers_after_insert(&bucket);
956 result =
iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
961 local_iterator inode_previous = bucket.before_begin();
962 local_iterator inode = bucket.begin();
964 while (inode != bucket.end())
967 if (key_equal_function(inode->key, key))
977 bucket.insert_after(inode_previous, *node);
978 adjust_first_last_markers_after_insert(&bucket);
981 result =
iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
998 bucket_t& bucket = pbuckets[bucket_id];
1001 local_iterator icurrent = bucket.
begin();
1003 while (icurrent != bucket.
end())
1005 if (key_equal_function(icurrent->key, key))
1007 delete_data_node(iprevious, icurrent, bucket);
1009 icurrent = iprevious;
1028 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1029 size_t erase(
const K& key)
1034 bucket_t& bucket = pbuckets[bucket_id];
1037 local_iterator icurrent = bucket.begin();
1039 while (icurrent != bucket.end())
1041 if (key_equal_function(icurrent->key, key))
1043 delete_data_node(iprevious, icurrent, bucket);
1045 icurrent = iprevious;
1066 iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
1069 bucket_t& bucket = ielement.get_bucket();
1071 local_iterator icurrent = ielement.get_local_iterator();
1074 while (iprevious->etl_next != &*icurrent)
1079 delete_data_node(iprevious, icurrent, bucket);
1091 iterator
erase(const_iterator first_, const_iterator last_)
1094 if ((first_ ==
begin()) && (last_ ==
end()))
1101 bucket_t* pbucket = first_.get_bucket_list_iterator();
1102 bucket_t* pend_bucket = last_.get_bucket_list_iterator();
1104 local_iterator icurrent = first_.get_local_iterator();
1105 local_iterator iend = last_.get_local_iterator();
1109 while (iprevious->etl_next != &*icurrent)
1115 iterator ibefore_erased = iterator((pbuckets + number_of_buckets), pbucket, iprevious);
1118 while ((icurrent != iend) || (pbucket != pend_bucket))
1120 icurrent = delete_data_node(iprevious, icurrent, *pbucket);
1123 if ((icurrent != iend) || (pbucket != pend_bucket))
1126 if ((icurrent == pbucket->
end()))
1131 }
while (pbucket->
empty());
1134 icurrent = pbucket->
begin();
1139 return ++ibefore_erased;
1158 const_iterator f =
find(key);
1159 const_iterator l = f;
1166 while ((l !=
end()) && key_equal_function(key, *l))
1182 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1183 size_t count(
const K& key)
const
1194 while ((l !=
end()) && key_equal_function(key, *l))
1214 bucket_t* pbucket = pbuckets + index;
1215 bucket_t& bucket = *pbucket;
1218 if (!bucket.
empty())
1221 local_iterator inode = bucket.
begin();
1222 local_iterator iend = bucket.
end();
1224 while (inode != iend)
1227 if (key_equal_function(key, inode->key))
1229 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1245 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1250 bucket_t* pbucket = pbuckets + index;
1251 bucket_t& bucket = *pbucket;
1254 if (!bucket.empty())
1257 local_iterator inode = bucket.begin();
1258 local_iterator iend = bucket.end();
1260 while (inode != iend)
1263 if (key_equal_function(key, inode->key))
1265 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1281 const_iterator
find(key_parameter_t key)
const
1285 bucket_t* pbucket = pbuckets + index;
1286 bucket_t& bucket = *pbucket;
1289 if (!bucket.
empty())
1292 local_iterator inode = bucket.
begin();
1293 local_iterator iend = bucket.
end();
1295 while (inode != iend)
1298 if (key_equal_function(key, inode->key))
1300 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1316 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1321 bucket_t* pbucket = pbuckets + index;
1322 bucket_t& bucket = *pbucket;
1325 if (!bucket.empty())
1328 local_iterator inode = bucket.begin();
1329 local_iterator iend = bucket.end();
1331 while (inode != iend)
1334 if (key_equal_function(key, inode->key))
1336 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1358 iterator f =
find(key);
1365 while ((l !=
end()) && key_equal_function(key, *l))
1371 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1384 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1385 ETL_OR_STD::pair<iterator, iterator>
equal_range(
const K& key)
1394 while ((l !=
end()) && key_equal_function(key, *l))
1400 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1413 ETL_OR_STD::pair<const_iterator, const_iterator>
equal_range(key_parameter_t key)
const
1415 const_iterator f =
find(key);
1416 const_iterator l = f;
1422 while ((l !=
end()) && key_equal_function(key, *l))
1428 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1441 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1442 ETL_OR_STD::pair<const_iterator, const_iterator>
equal_range(
const K& key)
const
1451 while ((l !=
end()) && key_equal_function(key, *l))
1457 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1466 return pnodepool->size();
1474 return pnodepool->max_size();
1482 return pnodepool->max_size();
1490 return pnodepool->empty();
1498 return pnodepool->full();
1507 return pnodepool->available();
1525 return key_hash_function;
1534 return key_equal_function;
1546 key_equal_function = rhs.
key_eq();
1563 key_hash_function = rhs.hash_function();
1564 key_equal_function = rhs.key_eq();
1565 move(rhs.begin(), rhs.end());
1584 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1596 iunordered_multiset(pool_t& node_pool_, bucket_t* pbuckets_,
size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_)
1597 : pnodepool(&node_pool_)
1598 , pbuckets(pbuckets_)
1599 , number_of_buckets(number_of_buckets_)
1602 , key_hash_function(key_hash_function_)
1603 , key_equal_function(key_equal_function_)
1615 for (
size_t i = 0UL; i < number_of_buckets; ++i)
1617 bucket_t& bucket = pbuckets[i];
1619 if (!bucket.
empty())
1622 local_iterator it = bucket.
begin();
1624 while (it != bucket.
end())
1627 it->key.~value_type();
1629 ETL_DECREMENT_DEBUG_COUNT;
1638 pnodepool->release_all();
1666 node_t* allocate_data_node()
1669 return (pnodepool->*func)();
1675 void adjust_first_last_markers_after_insert(bucket_t* pbucket)
1684 if (pbucket < first)
1688 else if (pbucket > last)
1698 void adjust_first_last_markers_after_erase(bucket_t* pbucket)
1707 if (pbucket == first)
1711 while (first->empty())
1716 else if (pbucket == last)
1721 bucket_t* pend = last;
1725 while (pbucket != pend)
1727 if (!pbucket->empty())
1741 local_iterator delete_data_node(local_iterator iprevious, local_iterator icurrent, bucket_t& bucket)
1743 local_iterator inext = bucket.erase_after(iprevious);
1744 icurrent->key.~value_type();
1745 pnodepool->release(&*icurrent);
1746 adjust_first_last_markers_after_erase(&bucket);
1747 ETL_DECREMENT_DEBUG_COUNT;
1762 const size_t number_of_buckets;
1769 hasher key_hash_function;
1772 key_equal key_equal_function;
1775 ETL_DECLARE_DEBUG_COUNT;
1780#if defined(ETL_POLYMORPHIC_UNORDERED_MULTISET) || defined(ETL_POLYMORPHIC_CONTAINERS)