SerialQueue: add const version of the iterators.
Unfortunately you can't template on const-ness in C++ so we have to
duplicate all the iterator code for SerialQueue (that, or introduce very
heavy templating).
diff --git a/src/backend/common/SerialQueue.h b/src/backend/common/SerialQueue.h
index 23f6634..09dcbfc 100644
--- a/src/backend/common/SerialQueue.h
+++ b/src/backend/common/SerialQueue.h
@@ -27,7 +27,8 @@
private:
using SerialPair = std::pair<Serial, std::vector<T>>;
using Storage = std::vector<SerialPair>;
- using StorageIterator = typename Storage::const_iterator;
+ using StorageIterator = typename Storage::iterator;
+ using ConstStorageIterator = typename Storage::const_iterator;
public:
class Iterator {
@@ -37,13 +38,27 @@
bool operator==(const Iterator& other) const;
bool operator!=(const Iterator& other) const;
- const T& operator*() const;
+ T& operator*() const;
private:
StorageIterator storageIterator;
// Special case the serialIterator when it should be equal to storageIterator.begin()
// otherwise we could ask storageIterator.begin() when storageIterator is storage.end()
// which is invalid. storageIterator.begin() is tagged with a nullptr.
+ T* serialIterator;
+ };
+
+ class ConstIterator {
+ public:
+ ConstIterator(ConstStorageIterator start);
+ ConstIterator& operator++();
+
+ bool operator==(const ConstIterator& other) const;
+ bool operator!=(const ConstIterator& other) const;
+ const T& operator*() const;
+
+ private:
+ ConstStorageIterator storageIterator;
const T* serialIterator;
};
@@ -59,6 +74,18 @@
StorageIterator endIt;
};
+ class ConstBeginEnd {
+ public:
+ ConstBeginEnd(ConstStorageIterator start, ConstStorageIterator end);
+
+ ConstIterator begin() const;
+ ConstIterator end() const;
+
+ private:
+ ConstStorageIterator startIt;
+ ConstStorageIterator endIt;
+ };
+
// The serial must be given in (not strictly) increasing order.
void Enqueue(const T& value, Serial serial);
void Enqueue(T&& value, Serial serial);
@@ -70,8 +97,10 @@
// The UpTo variants of Iterate and Clear affect all values associated to a serial
// that is smaller OR EQUAL to the given serial. Iterating is done like so:
// for (const T& value : queue.IterateAll()) { stuff(T); }
- BeginEnd IterateAll() const;
- BeginEnd IterateUpTo(Serial serial) const;
+ ConstBeginEnd IterateAll() const;
+ ConstBeginEnd IterateUpTo(Serial serial) const;
+ BeginEnd IterateAll();
+ BeginEnd IterateUpTo(Serial serial);
void Clear();
void ClearUpTo(Serial serial);
@@ -80,7 +109,8 @@
private:
// Returns the first StorageIterator that a serial bigger than serial.
- StorageIterator FindUpTo(Serial serial) const;
+ ConstStorageIterator FindUpTo(Serial serial) const;
+ StorageIterator FindUpTo(Serial serial);
Storage storage;
};
@@ -93,7 +123,7 @@
if (Empty() || storage.back().first < serial) {
storage.emplace_back(SerialPair(serial, {}));
}
- storage.back().second.push_back(value);
+ storage.back().second.emplace_back(value);
}
template<typename T>
@@ -103,7 +133,7 @@
if (Empty() || storage.back().first < serial) {
storage.emplace_back(SerialPair(serial, {}));
}
- storage.back().second.push_back(value);
+ storage.back().second.emplace_back(value);
}
template<typename T>
@@ -126,12 +156,22 @@
}
template<typename T>
- typename SerialQueue<T>::BeginEnd SerialQueue<T>::IterateAll() const {
+ typename SerialQueue<T>::ConstBeginEnd SerialQueue<T>::IterateAll() const {
return {storage.begin(), storage.end()};
}
template<typename T>
- typename SerialQueue<T>::BeginEnd SerialQueue<T>::IterateUpTo(Serial serial) const {
+ typename SerialQueue<T>::ConstBeginEnd SerialQueue<T>::IterateUpTo(Serial serial) const {
+ return {storage.begin(), FindUpTo(serial)};
+ }
+
+ template<typename T>
+ typename SerialQueue<T>::BeginEnd SerialQueue<T>::IterateAll() {
+ return {storage.begin(), storage.end()};
+ }
+
+ template<typename T>
+ typename SerialQueue<T>::BeginEnd SerialQueue<T>::IterateUpTo(Serial serial) {
return {storage.begin(), FindUpTo(serial)};
}
@@ -152,7 +192,16 @@
}
template<typename T>
- typename SerialQueue<T>::StorageIterator SerialQueue<T>::FindUpTo(Serial serial) const {
+ typename SerialQueue<T>::ConstStorageIterator SerialQueue<T>::FindUpTo(Serial serial) const {
+ auto it = storage.begin();
+ while (it != storage.end() && it->first <= serial) {
+ it ++;
+ }
+ return it;
+ }
+
+ template<typename T>
+ typename SerialQueue<T>::StorageIterator SerialQueue<T>::FindUpTo(Serial serial) {
auto it = storage.begin();
while (it != storage.end() && it->first <= serial) {
it ++;
@@ -186,7 +235,7 @@
template<typename T>
typename SerialQueue<T>::Iterator& SerialQueue<T>::Iterator::operator++() {
- const T* vectorData = storageIterator->second.data();
+ T* vectorData = storageIterator->second.data();
if (serialIterator == nullptr) {
serialIterator = vectorData + 1;
@@ -213,13 +262,72 @@
}
template<typename T>
- const T& SerialQueue<T>::Iterator::operator*() const {
+ T& SerialQueue<T>::Iterator::operator*() const {
if (serialIterator == nullptr) {
return *storageIterator->second.begin();
}
return *serialIterator;
}
+ // SerialQueue::ConstBeginEnd
+
+ template<typename T>
+ SerialQueue<T>::ConstBeginEnd::ConstBeginEnd(typename SerialQueue<T>::ConstStorageIterator start, typename SerialQueue<T>::ConstStorageIterator end)
+ : startIt(start), endIt(end) {
+ }
+
+ template<typename T>
+ typename SerialQueue<T>::ConstIterator SerialQueue<T>::ConstBeginEnd::begin() const {
+ return {startIt};
+ }
+
+ template<typename T>
+ typename SerialQueue<T>::ConstIterator SerialQueue<T>::ConstBeginEnd::end() const {
+ return {endIt};
+ }
+
+ // SerialQueue::ConstIterator
+
+ template<typename T>
+ SerialQueue<T>::ConstIterator::ConstIterator(typename SerialQueue<T>::ConstStorageIterator start)
+ : storageIterator(start), serialIterator(nullptr) {
+ }
+
+ template<typename T>
+ typename SerialQueue<T>::ConstIterator& SerialQueue<T>::ConstIterator::operator++() {
+ const T* vectorData = storageIterator->second.data();
+
+ if (serialIterator == nullptr) {
+ serialIterator = vectorData + 1;
+ } else {
+ serialIterator ++;
+ }
+
+ if (serialIterator >= vectorData + storageIterator->second.size()) {
+ serialIterator = nullptr;
+ storageIterator ++;
+ }
+
+ return *this;
+ }
+
+ template<typename T>
+ bool SerialQueue<T>::ConstIterator::operator==(const typename SerialQueue<T>::ConstIterator& other) const {
+ return other.storageIterator == storageIterator && other.serialIterator == serialIterator;
+ }
+
+ template<typename T>
+ bool SerialQueue<T>::ConstIterator::operator!=(const typename SerialQueue<T>::ConstIterator& other) const {
+ return !(*this == other);
+ }
+
+ template<typename T>
+ const T& SerialQueue<T>::ConstIterator::operator*() const {
+ if (serialIterator == nullptr) {
+ return *storageIterator->second.begin();
+ }
+ return *serialIterator;
+ }
}
#endif // BACKEND_COMMON_SERIALQUEUE_H_