2018-11-28 17:30:12 +00:00
|
|
|
// Copyright 2018 The Dawn Authors
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
#ifndef COMMON_SERIALSTORAGE_H_
|
|
|
|
#define COMMON_SERIALSTORAGE_H_
|
|
|
|
|
|
|
|
#include "common/Assert.h"
|
|
|
|
#include "common/Serial.h"
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct SerialStorageTraits {};
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
class SerialStorage {
|
|
|
|
private:
|
|
|
|
using Value = typename SerialStorageTraits<Derived>::Value;
|
|
|
|
using Storage = typename SerialStorageTraits<Derived>::Storage;
|
|
|
|
using StorageIterator = typename SerialStorageTraits<Derived>::StorageIterator;
|
|
|
|
using ConstStorageIterator = typename SerialStorageTraits<Derived>::ConstStorageIterator;
|
|
|
|
|
|
|
|
public:
|
|
|
|
class Iterator {
|
|
|
|
public:
|
|
|
|
Iterator(StorageIterator start);
|
|
|
|
Iterator& operator++();
|
|
|
|
|
|
|
|
bool operator==(const Iterator& other) const;
|
|
|
|
bool operator!=(const Iterator& other) const;
|
|
|
|
Value& operator*() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
StorageIterator mStorageIterator;
|
|
|
|
// Special case the mSerialIterator when it should be equal to mStorageIterator.begin()
|
|
|
|
// otherwise we could ask mStorageIterator.begin() when mStorageIterator is mStorage.end()
|
|
|
|
// which is invalid. mStorageIterator.begin() is tagged with a nullptr.
|
|
|
|
Value* mSerialIterator;
|
|
|
|
};
|
|
|
|
|
|
|
|
class ConstIterator {
|
|
|
|
public:
|
|
|
|
ConstIterator(ConstStorageIterator start);
|
|
|
|
ConstIterator& operator++();
|
|
|
|
|
|
|
|
bool operator==(const ConstIterator& other) const;
|
|
|
|
bool operator!=(const ConstIterator& other) const;
|
|
|
|
const Value& operator*() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
ConstStorageIterator mStorageIterator;
|
|
|
|
const Value* mSerialIterator;
|
|
|
|
};
|
|
|
|
|
|
|
|
class BeginEnd {
|
|
|
|
public:
|
|
|
|
BeginEnd(StorageIterator start, StorageIterator end);
|
|
|
|
|
|
|
|
Iterator begin() const;
|
|
|
|
Iterator end() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
StorageIterator mStartIt;
|
|
|
|
StorageIterator mEndIt;
|
|
|
|
};
|
|
|
|
|
|
|
|
class ConstBeginEnd {
|
|
|
|
public:
|
|
|
|
ConstBeginEnd(ConstStorageIterator start, ConstStorageIterator end);
|
|
|
|
|
|
|
|
ConstIterator begin() const;
|
|
|
|
ConstIterator end() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
ConstStorageIterator mStartIt;
|
|
|
|
ConstStorageIterator mEndIt;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Derived classes may specialize constraits for elements stored
|
|
|
|
// Ex.) SerialQueue enforces that the serial must be given in (not strictly)
|
|
|
|
// increasing order
|
|
|
|
template <typename... Params>
|
|
|
|
void Enqueue(Params&&... args, Serial serial) {
|
|
|
|
Derived::Enqueue(std::forward<Params>(args)..., serial);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Empty() const;
|
|
|
|
|
|
|
|
// 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); }
|
|
|
|
ConstBeginEnd IterateAll() const;
|
|
|
|
ConstBeginEnd IterateUpTo(Serial serial) const;
|
|
|
|
BeginEnd IterateAll();
|
|
|
|
BeginEnd IterateUpTo(Serial serial);
|
|
|
|
|
|
|
|
void Clear();
|
|
|
|
void ClearUpTo(Serial serial);
|
|
|
|
|
|
|
|
Serial FirstSerial() const;
|
2019-01-29 00:10:07 +00:00
|
|
|
Serial LastSerial() const;
|
2018-11-28 17:30:12 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
// Returns the first StorageIterator that a serial bigger than serial.
|
|
|
|
ConstStorageIterator FindUpTo(Serial serial) const;
|
|
|
|
StorageIterator FindUpTo(Serial serial);
|
|
|
|
Storage mStorage;
|
|
|
|
};
|
|
|
|
|
|
|
|
// SerialStorage
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
bool SerialStorage<Derived>::Empty() const {
|
|
|
|
return mStorage.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
typename SerialStorage<Derived>::ConstBeginEnd SerialStorage<Derived>::IterateAll() const {
|
|
|
|
return {mStorage.begin(), mStorage.end()};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
typename SerialStorage<Derived>::ConstBeginEnd SerialStorage<Derived>::IterateUpTo(
|
|
|
|
Serial serial) const {
|
|
|
|
return {mStorage.begin(), FindUpTo(serial)};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
typename SerialStorage<Derived>::BeginEnd SerialStorage<Derived>::IterateAll() {
|
|
|
|
return {mStorage.begin(), mStorage.end()};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
typename SerialStorage<Derived>::BeginEnd SerialStorage<Derived>::IterateUpTo(Serial serial) {
|
|
|
|
return {mStorage.begin(), FindUpTo(serial)};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
void SerialStorage<Derived>::Clear() {
|
|
|
|
mStorage.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
void SerialStorage<Derived>::ClearUpTo(Serial serial) {
|
|
|
|
mStorage.erase(mStorage.begin(), FindUpTo(serial));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
Serial SerialStorage<Derived>::FirstSerial() const {
|
|
|
|
DAWN_ASSERT(!Empty());
|
|
|
|
return mStorage.begin()->first;
|
|
|
|
}
|
|
|
|
|
2019-01-29 00:10:07 +00:00
|
|
|
template <typename Derived>
|
|
|
|
Serial SerialStorage<Derived>::LastSerial() const {
|
|
|
|
DAWN_ASSERT(!Empty());
|
|
|
|
return mStorage.back().first;
|
|
|
|
}
|
|
|
|
|
2018-11-28 17:30:12 +00:00
|
|
|
template <typename Derived>
|
|
|
|
typename SerialStorage<Derived>::ConstStorageIterator SerialStorage<Derived>::FindUpTo(
|
|
|
|
Serial serial) const {
|
|
|
|
auto it = mStorage.begin();
|
|
|
|
while (it != mStorage.end() && it->first <= serial) {
|
|
|
|
it++;
|
|
|
|
}
|
|
|
|
return it;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
typename SerialStorage<Derived>::StorageIterator SerialStorage<Derived>::FindUpTo(Serial serial) {
|
|
|
|
auto it = mStorage.begin();
|
|
|
|
while (it != mStorage.end() && it->first <= serial) {
|
|
|
|
it++;
|
|
|
|
}
|
|
|
|
return it;
|
|
|
|
}
|
|
|
|
|
|
|
|
// SerialStorage::BeginEnd
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
SerialStorage<Derived>::BeginEnd::BeginEnd(typename SerialStorage<Derived>::StorageIterator start,
|
|
|
|
typename SerialStorage<Derived>::StorageIterator end)
|
|
|
|
: mStartIt(start), mEndIt(end) {
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
typename SerialStorage<Derived>::Iterator SerialStorage<Derived>::BeginEnd::begin() const {
|
|
|
|
return {mStartIt};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
typename SerialStorage<Derived>::Iterator SerialStorage<Derived>::BeginEnd::end() const {
|
|
|
|
return {mEndIt};
|
|
|
|
}
|
|
|
|
|
|
|
|
// SerialStorage::Iterator
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
SerialStorage<Derived>::Iterator::Iterator(typename SerialStorage<Derived>::StorageIterator start)
|
|
|
|
: mStorageIterator(start), mSerialIterator(nullptr) {
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
typename SerialStorage<Derived>::Iterator& SerialStorage<Derived>::Iterator::operator++() {
|
|
|
|
Value* vectorData = mStorageIterator->second.data();
|
|
|
|
|
|
|
|
if (mSerialIterator == nullptr) {
|
|
|
|
mSerialIterator = vectorData + 1;
|
|
|
|
} else {
|
|
|
|
mSerialIterator++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mSerialIterator >= vectorData + mStorageIterator->second.size()) {
|
|
|
|
mSerialIterator = nullptr;
|
|
|
|
mStorageIterator++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
bool SerialStorage<Derived>::Iterator::operator==(
|
|
|
|
const typename SerialStorage<Derived>::Iterator& other) const {
|
|
|
|
return other.mStorageIterator == mStorageIterator && other.mSerialIterator == mSerialIterator;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
bool SerialStorage<Derived>::Iterator::operator!=(
|
|
|
|
const typename SerialStorage<Derived>::Iterator& other) const {
|
|
|
|
return !(*this == other);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
typename SerialStorage<Derived>::Value& SerialStorage<Derived>::Iterator::operator*() const {
|
|
|
|
if (mSerialIterator == nullptr) {
|
|
|
|
return *mStorageIterator->second.begin();
|
|
|
|
}
|
|
|
|
return *mSerialIterator;
|
|
|
|
}
|
|
|
|
|
|
|
|
// SerialStorage::ConstBeginEnd
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
SerialStorage<Derived>::ConstBeginEnd::ConstBeginEnd(
|
|
|
|
typename SerialStorage<Derived>::ConstStorageIterator start,
|
|
|
|
typename SerialStorage<Derived>::ConstStorageIterator end)
|
|
|
|
: mStartIt(start), mEndIt(end) {
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
typename SerialStorage<Derived>::ConstIterator SerialStorage<Derived>::ConstBeginEnd::begin()
|
|
|
|
const {
|
|
|
|
return {mStartIt};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
typename SerialStorage<Derived>::ConstIterator SerialStorage<Derived>::ConstBeginEnd::end() const {
|
|
|
|
return {mEndIt};
|
|
|
|
}
|
|
|
|
|
|
|
|
// SerialStorage::ConstIterator
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
SerialStorage<Derived>::ConstIterator::ConstIterator(
|
|
|
|
typename SerialStorage<Derived>::ConstStorageIterator start)
|
|
|
|
: mStorageIterator(start), mSerialIterator(nullptr) {
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
2020-07-10 18:19:38 +00:00
|
|
|
typename SerialStorage<Derived>::ConstIterator&
|
|
|
|
SerialStorage<Derived>::ConstIterator::operator++() {
|
2018-11-28 17:30:12 +00:00
|
|
|
const Value* vectorData = mStorageIterator->second.data();
|
|
|
|
|
|
|
|
if (mSerialIterator == nullptr) {
|
|
|
|
mSerialIterator = vectorData + 1;
|
|
|
|
} else {
|
|
|
|
mSerialIterator++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mSerialIterator >= vectorData + mStorageIterator->second.size()) {
|
|
|
|
mSerialIterator = nullptr;
|
|
|
|
mStorageIterator++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
bool SerialStorage<Derived>::ConstIterator::operator==(
|
|
|
|
const typename SerialStorage<Derived>::ConstIterator& other) const {
|
|
|
|
return other.mStorageIterator == mStorageIterator && other.mSerialIterator == mSerialIterator;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
bool SerialStorage<Derived>::ConstIterator::operator!=(
|
|
|
|
const typename SerialStorage<Derived>::ConstIterator& other) const {
|
|
|
|
return !(*this == other);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
|
|
const typename SerialStorage<Derived>::Value& SerialStorage<Derived>::ConstIterator::operator*()
|
|
|
|
const {
|
|
|
|
if (mSerialIterator == nullptr) {
|
|
|
|
return *mStorageIterator->second.begin();
|
|
|
|
}
|
|
|
|
return *mSerialIterator;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // COMMON_SERIALSTORAGE_H_
|