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:27 UTC
[trafficserver] 02/08: IntrusiveDList: Update erase methods.
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 c157bdcb38d719b3413f19ed1f6f8fc3246ccf34
Author: Alan M. Carroll <am...@apache.org>
AuthorDate: Sun Jul 22 21:24:02 2018 -0500
IntrusiveDList: Update erase methods.
---
.../internal-libraries/intrusive-list.en.rst | 35 ++++++++++++-
lib/ts/IntrusiveDList.h | 57 ++++++++++++++++++++--
2 files changed, 86 insertions(+), 6 deletions(-)
diff --git a/doc/developer-guide/internal-libraries/intrusive-list.en.rst b/doc/developer-guide/internal-libraries/intrusive-list.en.rst
index 7a9c3b6..32e78c7 100644
--- a/doc/developer-guide/internal-libraries/intrusive-list.en.rst
+++ b/doc/developer-guide/internal-libraries/intrusive-list.en.rst
@@ -23,7 +23,9 @@ IntrusiveDList
:class:`IntrusiveDList` is a class that provides a double linked list using pointers embeded in the
object. :class:`IntrusiveDList` also acts as a queue. No memory management is done - objects can be
added to and removed from the list but the allocation and deallocation of the objects must be
-handled outside the class. This class supports an STL compliant bidirectional iteration.
+handled outside the class. This class supports an STL compliant bidirectional iteration. The
+iterators automatically convert to pointer as in normal use of this class the contained elements
+will be referenced by pointers.
Definition
**********
@@ -52,6 +54,16 @@ Definition
Return a reference to the previous element pointer embedded in the element :arg:`elt`.
+ .. type:: iterator
+
+ An STL compliant bidirectional iterator on elements in the list. :type:`iterator` has a user
+ defined conversion to :code:`value_type *` for convenience in use.
+
+ .. type:: const_iterator
+
+ An STL compliant bidirectional constant iterator on elements in the list. :type:`const_iterator` has a user
+ defined conversion to :code:`const value_type *` for convenience in use.
+
.. function:: value_type * head()
Return a pointer to the head element in the list. This may be :code:`nullptr` if the list is empty.
@@ -84,6 +96,27 @@ Definition
Remove the tail element and return a pointer to it. May be :code:`nullptr` if the list is empty.
+ .. function:: iterator erase(const iterator & loc)
+
+ Remove the element at :arg:`loc`. Return the element after :arg:`loc`.
+
+ .. function:: iterator erase(const iterator & start, const iterator & limit)
+
+ Remove the elements in the half open range from and including :arg:`start`
+ to but not including :arg:`limit`.
+
+ .. function:: iterator iterator_for(value_type * value)
+
+ Return an :type:`iterator` that refers to :arg:`value`. :arg:`value` is checked for being in a
+ list but there is no guarantee it is in this list. If :arg:`value` is not in a list then the
+ end iterator is returned.
+
+ .. function:: const_iterator iterator_for(const value_type * value)
+
+ Return a :type:`const_iterator` that refers to :arg:`value`. :arg:`value` is checked for being
+ in a list but there is no guarantee it is in this list. If :arg:`value` is not in a list then
+ the end iterator is returned.
+
Usage
*****
diff --git a/lib/ts/IntrusiveDList.h b/lib/ts/IntrusiveDList.h
index 98f92d4..44fa8c5 100644
--- a/lib/ts/IntrusiveDList.h
+++ b/lib/ts/IntrusiveDList.h
@@ -265,9 +265,18 @@ public:
/// @return This list.
self_type &insert_before(iterator const &target, value_type *v);
- /// Take @a elt out of this list.
- /// @return This list.
- self_type &erase(value_type *v);
+ /// Take @a v out of this list.
+ /// @return The element after @a v.
+ value_type *erase(value_type *v);
+
+ /// Take the element at @a loc out of this list.
+ /// @return Iterator for the next element.
+ iterator erase(const iterator &loc);
+
+ /// Take elements out of the list.
+ /// Remove elements start with @a start up to but not including @a limit.
+ /// @return @a limit
+ iterator erase(const iterator &start, const iterator &limit);
/// Remove all elements.
/// @note @b No memory management is done!
@@ -577,12 +586,15 @@ IntrusiveDList<L>::insert_before(iterator const &target, value_type *v) -> self_
template <typename L>
auto
-IntrusiveDList<L>::erase(value_type *v) -> self_type &
+IntrusiveDList<L>::erase(value_type *v) -> value_type *
{
+ value_type *zret{nullptr};
+
if (L::prev_ptr(v)) {
L::next_ptr(L::prev_ptr(v)) = L::next_ptr(v);
}
if (L::next_ptr(v)) {
+ zret = L::next_ptr(v);
L::prev_ptr(L::next_ptr(v)) = L::prev_ptr(v);
}
if (v == _head) {
@@ -594,10 +606,45 @@ IntrusiveDList<L>::erase(value_type *v) -> self_type &
L::prev_ptr(v) = L::next_ptr(v) = nullptr;
--_count;
- return *this;
+ return zret;
}
template <typename L>
+auto
+IntrusiveDList<L>::erase(const iterator &loc) -> iterator
+{
+ return this->iterator_for(this->erase(loc._v));
+};
+
+template <typename L>
+auto
+IntrusiveDList<L>::erase(const iterator &first, const iterator &limit) -> iterator
+{
+ value_type *spot = first;
+ value_type *prev{L::prev_ptr(spot)};
+ if (prev) {
+ L::next_ptr(prev) = limit;
+ }
+ if (spot == _head) {
+ _head = limit;
+ }
+ // tail is only updated if @a limit is @a end (e.g., @c nullptr).
+ if (nullptr == limit) {
+ _tail = prev;
+ } else {
+ L::prev_ptr(limit) = prev;
+ }
+ // Clear links in removed elements.
+ while (spot != limit) {
+ value_type *target{spot};
+ spot = L::next_ptr(spot);
+ L::prev_ptr(target) = L::next_ptr(target) = nullptr;
+ };
+
+ return {limit._v, this};
+};
+
+template <typename L>
size_t
IntrusiveDList<L>::count() const
{