153 lines
4.4 KiB
C++
153 lines
4.4 KiB
C++
#ifndef SQL_INTRUSIVE_LIST_ITERATOR_H_
|
|
#define SQL_INTRUSIVE_LIST_ITERATOR_H_
|
|
/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software Foundation,
|
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
|
|
|
/**
|
|
@file intrusive_list_iterator.h
|
|
|
|
Iterator utilities for working with intrusive pointers.
|
|
*/
|
|
|
|
#include "my_dbug.h"
|
|
|
|
/**
|
|
An iterator that follows a 'next' pointer with an accessor function.
|
|
@tparam T The type of the object holding the intrusive list.
|
|
@tparam GetNextPointer The accessor function, returning a pointer to the
|
|
next object in the list.
|
|
|
|
@note Due to the nature of intrusive 'next' pointers it's not possible to
|
|
free an intrusive pointee while iterating over an intrusive list with
|
|
the pre-increment operator, as the enhanced for-loop does, e.g.
|
|
|
|
```
|
|
for(auto elem : elems)
|
|
delete *elem;
|
|
```
|
|
|
|
Will cause a core dump. However, the following is possible:
|
|
|
|
```
|
|
auto it = container.begin();
|
|
while(it != container.end()) delete *(it++);
|
|
```
|
|
*/
|
|
template <typename T, T *(*GetNextPointer)(const T *)>
|
|
class NextFunctionIterator {
|
|
public:
|
|
using value_type = T *;
|
|
/**
|
|
Constructs an iterator.
|
|
|
|
@param start The object that the iterator will start iterating
|
|
from.
|
|
*/
|
|
explicit NextFunctionIterator(T *start) : m_current(start) {}
|
|
|
|
/// Constructs a past-the-end iterator.
|
|
NextFunctionIterator() : m_current(nullptr) {}
|
|
|
|
NextFunctionIterator &operator++() {
|
|
DBUG_ASSERT(m_current != nullptr);
|
|
m_current = GetNextPointer(m_current);
|
|
return *this;
|
|
}
|
|
|
|
NextFunctionIterator operator++(int) {
|
|
auto pre_increment(*this);
|
|
++(*this);
|
|
return pre_increment;
|
|
}
|
|
|
|
T *operator*() const { return m_current; }
|
|
|
|
bool operator==(const NextFunctionIterator &other) const {
|
|
return m_current == other.m_current;
|
|
}
|
|
|
|
bool operator!=(const NextFunctionIterator &other) const {
|
|
return !((*this) == other);
|
|
}
|
|
|
|
private:
|
|
T *m_current;
|
|
};
|
|
|
|
/**
|
|
Helper template for the case when the 'next' member can be used directly,
|
|
typically when it's public and the class definition is known.
|
|
*/
|
|
template <typename T, T *T::*Member>
|
|
T *GetMember(const T *t) {
|
|
return t->*Member;
|
|
}
|
|
|
|
/**
|
|
An iterator that follows the 'next' pointer in an intrusive list.
|
|
Conforms to the ForwardIterator named requirement.
|
|
|
|
@tparam T The type of the object holding the intrusive list.
|
|
@tparam NextPointer The intrusive list's "next" pointer member.
|
|
*/
|
|
template <typename T, T *T::*NextPointer>
|
|
class IntrusiveListIterator
|
|
: public NextFunctionIterator<T, GetMember<T, NextPointer>> {
|
|
public:
|
|
IntrusiveListIterator() = default;
|
|
explicit IntrusiveListIterator(T *t)
|
|
: NextFunctionIterator<T, GetMember<T, NextPointer>>(t) {}
|
|
};
|
|
|
|
/**
|
|
Adds a collection interface on top of an iterator. The iterator must support a
|
|
default constructor constructing a past-the-end iterator.
|
|
|
|
@tparam IteratorType The iterator's class.
|
|
*/
|
|
template <typename IteratorType>
|
|
class IteratorContainer {
|
|
public:
|
|
using Type = typename IteratorType::value_type;
|
|
explicit IteratorContainer(Type first) : m_first(first) {}
|
|
|
|
IteratorType begin() { return IteratorType(m_first); }
|
|
IteratorType end() { return IteratorType(); }
|
|
|
|
private:
|
|
Type m_first;
|
|
};
|
|
|
|
template <typename T>
|
|
using GetNextPointerFunction = T *(*)(const T *);
|
|
|
|
/**
|
|
Convenience alias for instantiating a container directly from the accessor
|
|
function.
|
|
*/
|
|
template <typename T, GetNextPointerFunction<T> Fn>
|
|
using NextFunctionContainer = IteratorContainer<NextFunctionIterator<T, Fn>>;
|
|
|
|
/*
|
|
We inline the NextFunctionContainer definition below. We want to define this
|
|
alias as NextFunctionContainer<T, &GetMember<T, NextPointer>>, but VS2019
|
|
fails with C2996. It is likely a compiler bug.
|
|
*/
|
|
template <typename T, T *T::*NextPointer>
|
|
using IntrusiveListContainer =
|
|
IteratorContainer<NextFunctionIterator<T, &GetMember<T, NextPointer>>>;
|
|
|
|
#endif // SQL_INTRUSIVE_LIST_ITERATOR_H_
|