You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2018/08/22 14:55:30 UTC
[trafficserver] 05/08: IntrusiveHashMap: Update erase methods. Add
additional iterator_for methods for erase.
This is an automated email from the ASF dual-hosted git repository.
amc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 546a267efd94805f8c7655b4784c15fb31d3dc8e
Author: Alan M. Carroll <am...@apache.org>
AuthorDate: Sun Jul 22 21:25:15 2018 -0500
IntrusiveHashMap: Update erase methods.
Add additional iterator_for methods for erase.
---
lib/ts/IntrusiveHashMap.h | 103 ++++++++++++++++++++++++++++++++++------------
1 file changed, 76 insertions(+), 27 deletions(-)
diff --git a/lib/ts/IntrusiveHashMap.h b/lib/ts/IntrusiveHashMap.h
index c69a9a5..003326b 100644
--- a/lib/ts/IntrusiveHashMap.h
+++ b/lib/ts/IntrusiveHashMap.h
@@ -225,23 +225,30 @@ public:
/** Get an @c iterator for the value @a v.
- This is a bit obscure but needed in certain cases. It should only be used on a @a value that
- is already known to be in the table.
+ This is a bit obscure but needed in certain cases. Because the interface assumes iterators are always valid
+ this avoid containment checks, which is useful if @a v is already known to be in the container.
*/
iterator iterator_for(value_type *v);
+ const_iterator iterator_for(const value_type *v) const;
/** Remove the value at @a loc from the table.
@note This does @b not clean up the removed elements. Use carefully to avoid leaks.
- @return @c true if the value was removed, @c false otherwise.
+ @return An iterator the next value past @a loc. [STL compatibility]
*/
- bool erase(iterator const &loc);
+ iterator erase(iterator const &loc);
/// Remove all elements in the @c range @a r.
- bool erase(range const &r);
- /// Remove all elements in the range (first, last]
- bool erase(iterator const &first, iterator const &last);
+ iterator erase(range const &r);
+
+ /// Remove all elements in the range (start, limit]
+ iterator erase(iterator const &start, iterator const &limit);
+
+ /// Remove a @a value from the container.
+ /// @a value is checked for being a member of the container.
+ /// @return @c true if @a value was in the container and removed, @c false if it was not in the container.
+ bool erase(value_type *value);
/** Apply @a F(value_type&) to every element in the hash map.
*
@@ -479,6 +486,13 @@ IntrusiveHashMap<H>::equal_range(key_type key) const -> const_range
template <typename H>
auto
+IntrusiveHashMap<H>::iterator_for(const value_type *v) const -> const_iterator
+{
+ return _list.iterator_for(v);
+}
+
+template <typename H>
+auto
IntrusiveHashMap<H>::iterator_for(value_type *v) -> iterator
{
return _list.iterator_for(v);
@@ -541,31 +555,66 @@ IntrusiveHashMap<H>::insert(value_type *v)
}
template <typename H>
-bool
-IntrusiveHashMap<H>::erase(iterator const &loc)
+auto
+IntrusiveHashMap<H>::erase(iterator const &loc) -> iterator
{
- bool zret = false;
+ value_type *v = loc;
+ iterator zret = ++(this->iterator_for(v)); // get around no const_iterator -> iterator.
+ Bucket *b = this->bucket_for(H::key_of(v));
+ value_type *nv = H::next_ptr(v);
+ value_type *limit = b->limit();
+ if (b->_v == v) { // removed first element in bucket, update bucket
+ if (limit == nv) { // that was also the only element, deactivate bucket
+ _active_buckets.erase(b);
+ b->clear();
+ } else {
+ b->_v = nv;
+ --b->_count;
+ }
+ }
+ _list.erase(loc);
+ return zret;
+}
+template <typename H>
+bool
+IntrusiveHashMap<H>::erase(value_type *value)
+{
+ auto loc = this->find(value);
if (loc != this->end()) {
- value_type *v = &*loc;
- Bucket *b = this->bucket_for(H::key_of(v));
- if (b->contains(v)) {
- value_type *nv = H::next_ptr(v);
- value_type *limit = b->limit();
- if (b->_v == v) { // removed first element in bucket, update bucket
- if (limit == nv) { // that was also the only element, deactivate bucket
- _active_buckets.erase(b);
- b->clear();
- } else {
- b->_v = nv;
- --b->_count;
- }
- }
- zret = true;
- _list.erase(v);
+ this->erase(loc);
+ return true;
+ }
+ return false;
+}
+
+template <typename H>
+auto
+IntrusiveHashMap<H>::erase(iterator const &start, iterator const &limit) -> iterator
+{
+ auto spot{start};
+ Bucket *bucket{this->bucket_for(spot)};
+ while (spot != limit) {
+ auto target = bucket;
+ bucket = bucket->_link._next; // bump now to avoid forward iteration problems in case of bucket removal.
+ value_type *v_limit = bucket ? bucket->_v : nullptr;
+ while (spot != v_limit && spot != limit) {
+ --(target->_count);
+ ++spot;
+ }
+ if (target->_count == 0) {
+ _active_buckets.erase(target);
}
}
- return zret;
+ _list.erase(start, limit);
+ return _list.iterator_for(limit); // convert from const_iterator back to iterator
+};
+
+template <typename H>
+auto
+IntrusiveHashMap<H>::erase(range const &r) -> iterator
+{
+ return this->erase(r.first, r.second);
}
template <typename H>