mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 10:49:14 +00:00
Factor SerialQueue into SerialQueue and SerialMap
This change moves most of SerialQueue into SerialStorage and factors it to make SerialMap and SerialQueue. SerialMap does not enforce that items are Enqueue'd in monotonically increasing order. This is useful for implement timeline fences because OnCompletion callbacks may be added in an arbitrary order. Bug: dawn:26 Change-Id: I03376117311112b0b94ed887a31974f36c4a5464 Reviewed-on: https://dawn-review.googlesource.com/c/2720 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
d8c1a48fc4
commit
e06d57d338
@@ -15,321 +15,72 @@
|
||||
#ifndef COMMON_SERIALQUEUE_H_
|
||||
#define COMMON_SERIALQUEUE_H_
|
||||
|
||||
#include "common/Assert.h"
|
||||
#include "common/Serial.h"
|
||||
#include "common/SerialStorage.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
template <typename T>
|
||||
class SerialQueue {
|
||||
private:
|
||||
class SerialQueue;
|
||||
|
||||
template <typename T>
|
||||
struct SerialStorageTraits<SerialQueue<T>> {
|
||||
using Value = T;
|
||||
using SerialPair = std::pair<Serial, std::vector<T>>;
|
||||
using Storage = std::vector<SerialPair>;
|
||||
using StorageIterator = typename Storage::iterator;
|
||||
using ConstStorageIterator = typename Storage::const_iterator;
|
||||
};
|
||||
|
||||
// SerialQueue stores an associative list mapping a Serial to T.
|
||||
// It enforces that the Serials enqueued are strictly non-decreasing.
|
||||
// This makes it very efficient iterate or clear all items added up
|
||||
// to some Serial value because they are stored contiguously in memory.
|
||||
template <typename T>
|
||||
class SerialQueue : public SerialStorage<SerialQueue<T>> {
|
||||
public:
|
||||
class Iterator {
|
||||
public:
|
||||
Iterator(StorageIterator start);
|
||||
Iterator& operator++();
|
||||
|
||||
bool operator==(const Iterator& other) const;
|
||||
bool operator!=(const Iterator& other) const;
|
||||
T& 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.
|
||||
T* mSerialIterator;
|
||||
};
|
||||
|
||||
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 mStorageIterator;
|
||||
const T* 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;
|
||||
};
|
||||
using SerialPair = typename SerialStorageTraits<SerialQueue<T>>::SerialPair;
|
||||
|
||||
// The serial must be given in (not strictly) increasing order.
|
||||
void Enqueue(const T& value, Serial serial);
|
||||
void Enqueue(T&& value, Serial serial);
|
||||
void Enqueue(const std::vector<T>& values, Serial serial);
|
||||
void Enqueue(std::vector<T>&& values, Serial 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;
|
||||
|
||||
private:
|
||||
// Returns the first StorageIterator that a serial bigger than serial.
|
||||
ConstStorageIterator FindUpTo(Serial serial) const;
|
||||
StorageIterator FindUpTo(Serial serial);
|
||||
Storage mStorage;
|
||||
};
|
||||
|
||||
// SerialQueue
|
||||
|
||||
template <typename T>
|
||||
void SerialQueue<T>::Enqueue(const T& value, Serial serial) {
|
||||
DAWN_ASSERT(Empty() || mStorage.back().first <= serial);
|
||||
DAWN_ASSERT(this->Empty() || this->mStorage.back().first <= serial);
|
||||
|
||||
if (Empty() || mStorage.back().first < serial) {
|
||||
mStorage.emplace_back(SerialPair(serial, {}));
|
||||
if (this->Empty() || this->mStorage.back().first < serial) {
|
||||
this->mStorage.emplace_back(SerialPair(serial, {}));
|
||||
}
|
||||
mStorage.back().second.emplace_back(value);
|
||||
this->mStorage.back().second.emplace_back(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SerialQueue<T>::Enqueue(T&& value, Serial serial) {
|
||||
DAWN_ASSERT(Empty() || mStorage.back().first <= serial);
|
||||
DAWN_ASSERT(this->Empty() || this->mStorage.back().first <= serial);
|
||||
|
||||
if (Empty() || mStorage.back().first < serial) {
|
||||
mStorage.emplace_back(SerialPair(serial, {}));
|
||||
if (this->Empty() || this->mStorage.back().first < serial) {
|
||||
this->mStorage.emplace_back(SerialPair(serial, {}));
|
||||
}
|
||||
mStorage.back().second.emplace_back(value);
|
||||
this->mStorage.back().second.emplace_back(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SerialQueue<T>::Enqueue(const std::vector<T>& values, Serial serial) {
|
||||
DAWN_ASSERT(values.size() > 0);
|
||||
DAWN_ASSERT(Empty() || mStorage.back().first <= serial);
|
||||
mStorage.emplace_back(SerialPair(serial, {values}));
|
||||
DAWN_ASSERT(this->Empty() || this->mStorage.back().first <= serial);
|
||||
this->mStorage.emplace_back(SerialPair(serial, {values}));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SerialQueue<T>::Enqueue(std::vector<T>&& values, Serial serial) {
|
||||
DAWN_ASSERT(values.size() > 0);
|
||||
DAWN_ASSERT(Empty() || mStorage.back().first <= serial);
|
||||
mStorage.emplace_back(SerialPair(serial, {values}));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool SerialQueue<T>::Empty() const {
|
||||
return mStorage.empty();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename SerialQueue<T>::ConstBeginEnd SerialQueue<T>::IterateAll() const {
|
||||
return {mStorage.begin(), mStorage.end()};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename SerialQueue<T>::ConstBeginEnd SerialQueue<T>::IterateUpTo(Serial serial) const {
|
||||
return {mStorage.begin(), FindUpTo(serial)};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename SerialQueue<T>::BeginEnd SerialQueue<T>::IterateAll() {
|
||||
return {mStorage.begin(), mStorage.end()};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename SerialQueue<T>::BeginEnd SerialQueue<T>::IterateUpTo(Serial serial) {
|
||||
return {mStorage.begin(), FindUpTo(serial)};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SerialQueue<T>::Clear() {
|
||||
mStorage.clear();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SerialQueue<T>::ClearUpTo(Serial serial) {
|
||||
mStorage.erase(mStorage.begin(), FindUpTo(serial));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Serial SerialQueue<T>::FirstSerial() const {
|
||||
DAWN_ASSERT(!Empty());
|
||||
return mStorage.front().first;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename SerialQueue<T>::ConstStorageIterator SerialQueue<T>::FindUpTo(Serial serial) const {
|
||||
auto it = mStorage.begin();
|
||||
while (it != mStorage.end() && it->first <= serial) {
|
||||
it++;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename SerialQueue<T>::StorageIterator SerialQueue<T>::FindUpTo(Serial serial) {
|
||||
auto it = mStorage.begin();
|
||||
while (it != mStorage.end() && it->first <= serial) {
|
||||
it++;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
// SerialQueue::BeginEnd
|
||||
|
||||
template <typename T>
|
||||
SerialQueue<T>::BeginEnd::BeginEnd(typename SerialQueue<T>::StorageIterator start,
|
||||
typename SerialQueue<T>::StorageIterator end)
|
||||
: mStartIt(start), mEndIt(end) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename SerialQueue<T>::Iterator SerialQueue<T>::BeginEnd::begin() const {
|
||||
return {mStartIt};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename SerialQueue<T>::Iterator SerialQueue<T>::BeginEnd::end() const {
|
||||
return {mEndIt};
|
||||
}
|
||||
|
||||
// SerialQueue::Iterator
|
||||
|
||||
template <typename T>
|
||||
SerialQueue<T>::Iterator::Iterator(typename SerialQueue<T>::StorageIterator start)
|
||||
: mStorageIterator(start), mSerialIterator(nullptr) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename SerialQueue<T>::Iterator& SerialQueue<T>::Iterator::operator++() {
|
||||
T* 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 T>
|
||||
bool SerialQueue<T>::Iterator::operator==(const typename SerialQueue<T>::Iterator& other) const {
|
||||
return other.mStorageIterator == mStorageIterator && other.mSerialIterator == mSerialIterator;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool SerialQueue<T>::Iterator::operator!=(const typename SerialQueue<T>::Iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T& SerialQueue<T>::Iterator::operator*() const {
|
||||
if (mSerialIterator == nullptr) {
|
||||
return *mStorageIterator->second.begin();
|
||||
}
|
||||
return *mSerialIterator;
|
||||
}
|
||||
|
||||
// SerialQueue::ConstBeginEnd
|
||||
|
||||
template <typename T>
|
||||
SerialQueue<T>::ConstBeginEnd::ConstBeginEnd(typename SerialQueue<T>::ConstStorageIterator start,
|
||||
typename SerialQueue<T>::ConstStorageIterator end)
|
||||
: mStartIt(start), mEndIt(end) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename SerialQueue<T>::ConstIterator SerialQueue<T>::ConstBeginEnd::begin() const {
|
||||
return {mStartIt};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename SerialQueue<T>::ConstIterator SerialQueue<T>::ConstBeginEnd::end() const {
|
||||
return {mEndIt};
|
||||
}
|
||||
|
||||
// SerialQueue::ConstIterator
|
||||
|
||||
template <typename T>
|
||||
SerialQueue<T>::ConstIterator::ConstIterator(typename SerialQueue<T>::ConstStorageIterator start)
|
||||
: mStorageIterator(start), mSerialIterator(nullptr) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename SerialQueue<T>::ConstIterator& SerialQueue<T>::ConstIterator::operator++() {
|
||||
const T* 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 T>
|
||||
bool SerialQueue<T>::ConstIterator::operator==(
|
||||
const typename SerialQueue<T>::ConstIterator& other) const {
|
||||
return other.mStorageIterator == mStorageIterator && other.mSerialIterator == mSerialIterator;
|
||||
}
|
||||
|
||||
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 (mSerialIterator == nullptr) {
|
||||
return *mStorageIterator->second.begin();
|
||||
}
|
||||
return *mSerialIterator;
|
||||
DAWN_ASSERT(this->Empty() || this->mStorage.back().first <= serial);
|
||||
this->mStorage.emplace_back(SerialPair(serial, {values}));
|
||||
}
|
||||
|
||||
#endif // COMMON_SERIALQUEUE_H_
|
||||
|
||||
Reference in New Issue
Block a user