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).
This commit is contained in:
parent
e64dec7a3d
commit
76707f9ac9
|
@ -27,7 +27,8 @@ namespace backend {
|
|||
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 @@ namespace backend {
|
|||
|
||||
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 @@ namespace backend {
|
|||
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 @@ namespace backend {
|
|||
// 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 @@ namespace backend {
|
|||
|
||||
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 @@ namespace backend {
|
|||
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 @@ namespace backend {
|
|||
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 @@ namespace backend {
|
|||
}
|
||||
|
||||
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 @@ namespace backend {
|
|||
}
|
||||
|
||||
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 @@ namespace backend {
|
|||
|
||||
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 @@ namespace backend {
|
|||
}
|
||||
|
||||
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_
|
||||
|
|
Loading…
Reference in New Issue