Skip to content

Commit 113d205

Browse files
committed
Improved ChunkedStorage.hpp
1 parent 30a98b3 commit 113d205

File tree

1 file changed

+126
-15
lines changed

1 file changed

+126
-15
lines changed

runtime/ChunkedStorage.hpp

+126-15
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,14 @@ class ChunkedStorage {
211211
/// Get the number of elements stored in this ChunkedStorage
212212
size_type size() const { return numElements; }
213213

214+
/// Is this storage empty?
215+
bool empty() const { return size() == 0; }
216+
217+
/// Remove all elements
218+
void clear() {
219+
freeChunks();
220+
}
221+
214222
/// Emplace a value at the end
215223
template <typename... Args>
216224
T& emplace_back(Args&&... args) {
@@ -315,7 +323,88 @@ class ParallelChunkedStorage {
315323
};
316324

317325
private:
318-
using ChunkHeader = ChunkedStorage<T>::ChunkHeader;
326+
using ChunkHeader = typename ChunkedStorage<T>::ChunkHeader;
327+
328+
/// The chunked storage for one thread
329+
struct LocalChunkedStorageEntry {
330+
/// The chunked storage
331+
ChunkedStorage<T> storage;
332+
/// The thread id given by a caller of `createLocalStorage`
333+
uint32_t threadId;
334+
/// The index of this entry. All indexes are unique but may not be
335+
/// consistent with the order of the `next` pointers.
336+
size_t index = -1;
337+
/// The next entry
338+
LocalChunkedStorageEntry* next = nullptr;
339+
};
340+
341+
342+
/// An iterator over all elements in a `ParallelChunkedStorage`
343+
template <bool isConst>
344+
class Iterator {
345+
public:
346+
using difference_type = std::ptrdiff_t;
347+
using value_type = std::conditional_t<isConst, const T, T>;
348+
using pointer = value_type*;
349+
using reference = value_type&;
350+
using iterator_category = std::forward_iterator_tag;
351+
352+
private:
353+
friend class ParallelChunkedStorage;
354+
355+
using storage_iterator = std::conditional_t<isConst, typename ChunkedStorage<T>::const_iterator, typename ChunkedStorage<T>::iterator>;
356+
using storage_type = std::conditional_t<isConst, const ChunkedStorage<T>, ChunkedStorage<T>>;
357+
358+
/// The current entry
359+
LocalChunkedStorageEntry* currentEntry = nullptr;
360+
/// The iterator of the current entry
361+
storage_iterator it;
362+
363+
/// Make sure that the iterator points to a valid element or the end
364+
void skipEmpty() {
365+
while (currentEntry && it == currentEntry->storage.end()) {
366+
currentEntry = currentEntry->next;
367+
if (currentEntry)
368+
it = static_cast<storage_type&>(currentEntry->storage).begin();
369+
else
370+
it = {};
371+
}
372+
}
373+
374+
/// Constructor
375+
Iterator(LocalChunkedStorageEntry* entry, storage_iterator it) : currentEntry(entry), it(it) {
376+
skipEmpty();
377+
}
378+
379+
public:
380+
/// Default constructor
381+
Iterator() = default;
382+
383+
/// Dereference
384+
reference operator*() const {
385+
return *it;
386+
}
387+
/// Dereference
388+
pointer operator->() const {
389+
return it.operator->();
390+
}
391+
392+
/// Pre-increment
393+
Iterator& operator++() {
394+
++it;
395+
skipEmpty();
396+
return *this;
397+
}
398+
/// Post-increment
399+
Iterator operator++(int) {
400+
Iterator it(*this);
401+
operator++();
402+
return it;
403+
}
404+
405+
/// Equality comparison
406+
bool operator==(const Iterator& other) const = default;
407+
};
319408

320409
/// A parallel iterator over all chunks in a `ParallelChunkedStorage`
321410
template <bool isConst>
@@ -550,23 +639,12 @@ class ParallelChunkedStorage {
550639
};
551640

552641
public:
642+
using iterator = Iterator<false>;
643+
using const_iterator = Iterator<true>;
553644
using parallel_iterator = ParallelIterator<false>;
554645
using const_parallel_iterator = ParallelIterator<true>;
555646

556647
private:
557-
/// The chunked storage for one thread
558-
struct LocalChunkedStorageEntry {
559-
/// The chunked storage
560-
ChunkedStorage<T> storage;
561-
/// The thread id given by a caller of `createLocalStorage`
562-
uint32_t threadId;
563-
/// The index of this entry. All indexes are unique but may not be
564-
/// consistent with the order of the `next` pointers.
565-
size_t index = -1;
566-
/// The next entry
567-
LocalChunkedStorageEntry* next = nullptr;
568-
};
569-
570648
/// The first entry in the list of chunked storages
571649
LocalChunkedStorageEntry* frontEntry = nullptr;
572650
/// The total number of entries
@@ -609,6 +687,15 @@ class ParallelChunkedStorage {
609687
numEntries = 0;
610688
}
611689

690+
/// The total number of elements. Note that this is not thread-safe and
691+
/// linear in the number of threads.
692+
size_t size() const {
693+
size_t numElements = 0;
694+
for (auto* entry = frontEntry; entry; entry = entry->next)
695+
numElements += entry->storage.size();
696+
return numElements;
697+
}
698+
612699
/// Create a new local chunked storage
613700
LocalChunkedStorageRef createLocalStorage(uint32_t threadId) {
614701
auto* entry = new LocalChunkedStorageEntry;
@@ -627,13 +714,37 @@ class ParallelChunkedStorage {
627714
return ref;
628715
}
629716

717+
/// Get an iterator to the first element
718+
iterator begin() {
719+
typename ChunkedStorage<T>::iterator it;
720+
if (frontEntry)
721+
it = std::begin(frontEntry->storage);
722+
return iterator(frontEntry, it);
723+
}
724+
/// Get an iterator to the first element
725+
const_iterator begin() const {
726+
typename ChunkedStorage<T>::const_iterator it;
727+
if (frontEntry)
728+
it = std::cbegin(frontEntry->storage);
729+
return const_iterator(frontEntry, it);
730+
}
731+
732+
/// Get the end iterator
733+
iterator end() {
734+
return {};
735+
}
736+
/// Get the end iterator
737+
const_iterator end() const {
738+
return {};
739+
}
740+
630741
/// Get a parallel iterator
631742
parallel_iterator parallelIter() {
632743
return parallel_iterator(*this);
633744
}
634745
/// Get a parallel iterator
635746
const_parallel_iterator parallelIter() const {
636-
return parallel_iterator(*this);
747+
return const_parallel_iterator(*this);
637748
}
638749
};
639750
//---------------------------------------------------------------------------

0 commit comments

Comments
 (0)