Skip to content

Commit de24d93

Browse files
committed
DPL: separate iteration over the slots vs over parts in the slots
1 parent ab31e11 commit de24d93

7 files changed

Lines changed: 58 additions & 125 deletions

File tree

Detectors/TPC/workflow/readers/include/TPCReaderWorkflow/TPCSectorCompletionPolicy.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,9 @@ class TPCSectorCompletionPolicy
101101
size_t nMaxPartsPerRoute = 0;
102102
int inputType = -1;
103103
for (auto it = inputs.begin(), end = inputs.end(); it != end; ++it) {
104-
nMaxPartsPerRoute = it.size() > nMaxPartsPerRoute ? it.size() : nMaxPartsPerRoute;
104+
nMaxPartsPerRoute = it.parts().size() > nMaxPartsPerRoute ? it.parts().size() : nMaxPartsPerRoute;
105105
bool haveActivePart = false;
106-
for (auto const& ref : it) {
106+
for (auto const& ref : it.parts()) {
107107
if (!framework::DataRefUtils::isValid(ref)) {
108108
continue;
109109
}

Framework/Core/include/Framework/InputRecord.h

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -693,55 +693,20 @@ class InputRecord
693693
using reference = typename BaseType::reference;
694694
using pointer = typename BaseType::pointer;
695695
using ElementType = typename std::remove_const<value_type>::type;
696-
using iterator = InputSpan::Iterator<SelfType, T>;
697-
using const_iterator = InputSpan::Iterator<SelfType, const T>;
698696

699697
InputRecordIterator(InputRecord const* parent, bool isEnd = false)
700698
: BaseType(parent, isEnd)
701699
{
702700
}
703701

704-
/// Initial indices for part-level iteration: first part starts at {headerIdx=0, payloadIdx=1}.
705-
[[nodiscard]] DataRefIndices initialIndices() const { return {0, 1}; }
706-
/// Sentinel used by nextIndicesGetter to signal end-of-slot.
707-
[[nodiscard]] DataRefIndices endIndices() const { return {size_t(-1), size_t(-1)}; }
708-
709-
/// Get element at the given raw message indices in O(1).
710-
[[nodiscard]] ElementType getAtIndices(DataRefIndices indices) const
711-
{
712-
return this->parent()->getAtIndices(this->position(), indices);
713-
}
714-
715-
/// Advance @a current to the next part's indices in O(1).
716-
[[nodiscard]] DataRefIndices nextIndices(DataRefIndices current) const
717-
{
718-
return this->parent()->nextIndices(this->position(), current);
719-
}
720-
721-
/// Check if slot is valid, index of part is not used
702+
/// Check if slot is valid
722703
[[nodiscard]] bool isValid(size_t = 0) const
723704
{
724705
if (this->position() < this->parent()->size()) {
725706
return this->parent()->isValid(this->position());
726707
}
727708
return false;
728709
}
729-
730-
/// Get number of parts in input slot
731-
[[nodiscard]] size_t size() const
732-
{
733-
return this->parent()->getNofParts(this->position());
734-
}
735-
736-
[[nodiscard]] const_iterator begin() const
737-
{
738-
return const_iterator(this, size() == 0);
739-
}
740-
741-
[[nodiscard]] const_iterator end() const
742-
{
743-
return const_iterator(this, true);
744-
}
745710
};
746711

747712
using iterator = InputRecordIterator<DataRef>;

Framework/Core/include/Framework/InputRecordWalker.h

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,19 @@ class InputRecordWalker
7373
// the iterator over the input routes
7474
using input_iterator = decltype(std::declval<InputRecord>().begin());
7575

76+
// the range over parts in one slot — must be stored as a member so the
77+
// part_iterator (which holds a pointer into it) does not dangle
78+
using part_range = InputRecord::PartRange;
79+
using part_iterator = InputSpan::Iterator<part_range, const DataRef>;
80+
7681
Iterator() = delete;
7782

78-
Iterator(InputRecord& parent, input_iterator it, input_iterator end, std::vector<InputSpec> const& filterSpecs)
79-
: mParent(parent), mInputIterator(it), mEnd(end), mCurrent(mInputIterator.begin()), mFilterSpecs(filterSpecs)
83+
Iterator(input_iterator it, input_iterator end, std::vector<InputSpec> const& filterSpecs)
84+
: mInputIterator(it), mEnd(end), mCurrentRange(it.parts()), mCurrent(mCurrentRange.begin()), mFilterSpecs(filterSpecs)
8085
{
8186
next(true);
8287
}
8388

84-
~Iterator() = default;
85-
8689
// prefix increment
8790
self_type& operator++()
8891
{
@@ -104,9 +107,7 @@ class InputRecordWalker
104107
// comparison
105108
bool operator==(const self_type& other) const
106109
{
107-
bool result = mInputIterator == other.mInputIterator;
108-
result = result && mCurrent == other.mCurrent;
109-
return result;
110+
return mInputIterator == other.mInputIterator && mCurrent == other.mCurrent;
110111
}
111112

112113
bool operator!=(const self_type& rh) const
@@ -115,19 +116,13 @@ class InputRecordWalker
115116
}
116117

117118
private:
118-
// the iterator over the parts in one channel
119-
using part_iterator = typename input_iterator::const_iterator;
120-
121119
bool next(bool isInitialPart = false)
122120
{
121+
if (!isInitialPart) {
122+
++mCurrent;
123+
}
123124
while (mInputIterator != mEnd) {
124-
while (mCurrent != mInputIterator.end()) {
125-
// increment on the level of one input
126-
if (!isInitialPart && (mCurrent == mInputIterator.end() || ++mCurrent == mInputIterator.end())) {
127-
// no more parts, go to next input
128-
break;
129-
}
130-
isInitialPart = false;
125+
for (; mCurrent != mCurrentRange.end(); ++mCurrent) {
131126
// check filter rules
132127
if (mFilterSpecs.size() > 0) {
133128
bool isSelected = false;
@@ -143,15 +138,15 @@ class InputRecordWalker
143138
return true;
144139
}
145140
++mInputIterator;
146-
mCurrent = mInputIterator.begin();
147-
isInitialPart = true;
141+
mCurrentRange = mInputIterator.parts();
142+
mCurrent = mCurrentRange.begin();
148143
} // end loop over record
149144
return false;
150145
}
151146

152-
InputRecord& mParent;
153147
input_iterator mInputIterator;
154148
input_iterator mEnd;
149+
part_range mCurrentRange; // declared before mCurrent — initialized first
155150
part_iterator mCurrent;
156151
std::vector<InputSpec> const& mFilterSpecs;
157152
};
@@ -160,12 +155,12 @@ class InputRecordWalker
160155

161156
const_iterator begin() const
162157
{
163-
return const_iterator(mRecord, mRecord.begin(), mRecord.end(), mFilterSpecs);
158+
return const_iterator(mRecord.begin(), mRecord.end(), mFilterSpecs);
164159
}
165160

166161
const_iterator end() const
167162
{
168-
return const_iterator(mRecord, mRecord.end(), mRecord.end(), mFilterSpecs);
163+
return const_iterator(mRecord.end(), mRecord.end(), mFilterSpecs);
169164
}
170165

171166
private:

Framework/Core/include/Framework/InputSpan.h

Lines changed: 22 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -179,69 +179,40 @@ class InputSpan
179179
return mCurrentIndices.headerIdx;
180180
}
181181

182+
// return an iterable range over all parts in the current slot
183+
// only available for slot-level iterators whose parent has parts(size_t)
184+
[[nodiscard]] auto parts() const
185+
requires requires(ParentType const* p, size_t i) { p->parts(i); }
186+
{
187+
return mParent->parts(mCurrentIndices.headerIdx);
188+
}
189+
182190
private:
183191
ParentType const* mParent;
184192
DataRefIndices mCurrentIndices;
185193
ElementType mElement;
186194
};
187195

188-
/// @class InputSpanIterator
189-
/// An iterator over the input slots.
190-
/// It supports an iterator interface to access the parts in the slot.
191-
template <typename T>
192-
class InputSpanIterator : public Iterator<InputSpan, T>
193-
{
194-
public:
195-
using SelfType = InputSpanIterator;
196-
using BaseType = Iterator<InputSpan, T>;
197-
using value_type = typename BaseType::value_type;
198-
using reference = typename BaseType::reference;
199-
using pointer = typename BaseType::pointer;
200-
using ElementType = typename std::remove_const<value_type>::type;
201-
using iterator = Iterator<SelfType, T>;
202-
using const_iterator = Iterator<SelfType, const T>;
203-
204-
InputSpanIterator(InputSpan const* parent, bool isEnd = false)
205-
: BaseType(parent, isEnd)
206-
{
207-
}
196+
/// A range over the parts of a single slot, supporting range-based for.
197+
struct PartRange {
198+
InputSpan const* span;
199+
size_t slot;
208200

209-
/// Initial indices for part-level iteration: first part starts at {headerIdx=0, payloadIdx=1}.
210201
[[nodiscard]] DataRefIndices initialIndices() const { return {0, 1}; }
211-
/// Sentinel used by nextIndicesGetter to signal end-of-slot.
212202
[[nodiscard]] DataRefIndices endIndices() const { return {size_t(-1), size_t(-1)}; }
203+
[[nodiscard]] DataRef getAtIndices(DataRefIndices idx) const { return span->getAtIndices(slot, idx); }
204+
[[nodiscard]] DataRefIndices nextIndices(DataRefIndices idx) const { return span->nextIndices(slot, idx); }
205+
[[nodiscard]] size_t size() const { return span->getNofParts(slot); }
213206

214-
/// Get element at the given raw message indices in O(1).
215-
[[nodiscard]] ElementType getAtIndices(DataRefIndices indices) const
216-
{
217-
return this->parent()->getAtIndices(this->position(), indices);
218-
}
219-
220-
/// Advance @a current to the next part's indices in O(1).
221-
[[nodiscard]] DataRefIndices nextIndices(DataRefIndices current) const
222-
{
223-
return this->parent()->nextIndices(this->position(), current);
224-
}
225-
226-
/// Get number of parts in input slot
227-
[[nodiscard]] size_t size() const
228-
{
229-
return this->parent()->getNofParts(this->position());
230-
}
231-
232-
[[nodiscard]] const_iterator begin() const
233-
{
234-
return const_iterator(this, size() == 0);
235-
}
236-
237-
[[nodiscard]] const_iterator end() const
238-
{
239-
return const_iterator(this, true);
240-
}
207+
[[nodiscard]] Iterator<PartRange, const DataRef> begin() const { return {this, size() == 0}; }
208+
[[nodiscard]] Iterator<PartRange, const DataRef> end() const { return {this, true}; }
241209
};
242210

243-
using iterator = InputSpanIterator<DataRef>;
244-
using const_iterator = InputSpanIterator<const DataRef>;
211+
/// Return an iterable range over all parts in slot @a i.
212+
[[nodiscard]] PartRange parts(size_t i) const { return {this, i}; }
213+
214+
using const_iterator = Iterator<InputSpan, const DataRef>;
215+
using iterator = const_iterator;
245216

246217
// supporting read-only access and returning const_iterator
247218
[[nodiscard]] const_iterator begin() const

Framework/Core/src/CompletionPolicyHelpers.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ CompletionPolicy CompletionPolicyHelpers::consumeWhenAnyWithAllConditions(const
343343
}
344344
if (canConsume || conditionMissing) {
345345
for (auto it = inputs.begin(), end = inputs.end(); it != end; ++it) {
346-
for (auto const& ref : it) {
346+
for (auto const& ref : it.parts()) {
347347
if (!framework::DataRefUtils::isValid(ref)) {
348348
continue;
349349
}

Framework/Core/test/test_InputSpan.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ TEST_CASE("TestInputSpan")
6161
routeNo = 0;
6262
for (auto it = span.begin(), end = span.end(); it != end; ++it) {
6363
size_t partNo = 0;
64-
REQUIRE(it.size() * 2 == inputs[routeNo].size());
65-
for (auto const& ref : it) {
64+
REQUIRE(it.parts().size() * 2 == inputs[routeNo].size());
65+
for (auto const& ref : it.parts()) {
6666
REQUIRE(inputs[routeNo].at(partNo++) == ref.header);
6767
REQUIRE(inputs[routeNo].at(partNo++) == ref.payload);
6868
INFO(ref.header << " " << ref.payload);

Framework/Utils/include/DPLUtils/DPLRawParser.h

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,12 @@ class DPLRawParser
105105
Iterator() = delete;
106106

107107
Iterator(InputRecord& parent, input_iterator it, input_iterator end, std::vector<InputSpec> const& filterSpecs, fair::Severity sev = fair::Severity::alarm, size_t maxErrMsg = -1, size_t* cntErrMsg = nullptr)
108-
: mParent(parent), mInputIterator(it), mEnd(end), mPartIterator(mInputIterator.begin()), mParser(std::make_unique<parser_type>(reinterpret_cast<const char*>(&initializer), sizeof(initializer))), mCurrent(mParser->begin()), mFilterSpecs(filterSpecs), mMaxFailureMessages(maxErrMsg), mExtFailureCounter(cntErrMsg), mSeverity(sev)
108+
: mParent(parent), mInputIterator(it), mEnd(end), mCurrentRange(it.parts()), mPartIterator(mCurrentRange.begin()), mParser(std::make_unique<parser_type>(reinterpret_cast<const char*>(&initializer), sizeof(initializer))), mCurrent(mParser->begin()), mFilterSpecs(filterSpecs), mMaxFailureMessages(maxErrMsg), mExtFailureCounter(cntErrMsg), mSeverity(sev)
109109
{
110110
mParser.reset();
111111
next();
112112
}
113113

114-
~Iterator() = default;
115-
116114
// prefix increment
117115
self_type& operator++()
118116
{
@@ -205,7 +203,7 @@ class DPLRawParser
205203

206204
friend std::ostream& operator<<(std::ostream& os, self_type const& it)
207205
{
208-
if (it.mInputIterator != it.mEnd && it.mPartIterator != it.mInputIterator.end() && it.mParser != nullptr) {
206+
if (it.mInputIterator != it.mEnd && it.mPartIterator != it.mCurrentRange.end() && it.mParser != nullptr) {
209207
os << it.mCurrent;
210208
}
211209
return os;
@@ -223,7 +221,7 @@ class DPLRawParser
223221
friend std::ostream& operator<<(std::ostream& os, Fmt<FmtCtrl> const& fmt)
224222
{
225223
auto const& it = fmt.it;
226-
if (it.mInputIterator != it.mEnd && it.mPartIterator != it.mInputIterator.end() && it.mParser != nullptr) {
224+
if (it.mInputIterator != it.mEnd && it.mPartIterator != it.mCurrentRange.end() && it.mParser != nullptr) {
227225
if constexpr (FmtCtrl == raw_parser::FormatSpec::Info) {
228226
// TODO: need to propagate the format spec also on the RawParser object
229227
// for now this operation prints the RDH version info and the table header
@@ -236,8 +234,10 @@ class DPLRawParser
236234
}
237235

238236
private:
239-
// the iterator over the parts in one channel
240-
using part_iterator = typename input_iterator::const_iterator;
237+
// the range over parts in one slot — must be stored as a member so the
238+
// part_iterator (which holds a pointer into it) does not dangle
239+
using part_range = InputRecord::PartRange;
240+
using part_iterator = InputSpan::Iterator<part_range, const DataRef>;
241241
// the iterator over the over the parser pages
242242
using parser_iterator = typename parser_type::const_iterator;
243243

@@ -265,15 +265,15 @@ class DPLRawParser
265265

266266
while (mInputIterator != mEnd) {
267267
bool isInitial = mParser == nullptr;
268-
while (mPartIterator != mInputIterator.end()) {
268+
while (mPartIterator != mCurrentRange.end()) {
269269
// first increment on the parser level
270270
if (mParser && mCurrent != mParser->end() && ++mCurrent != mParser->end()) {
271271
// we have an active parser and there is still data at the incremented iterator
272272
return true;
273273
}
274274
// now increment on the level of one input
275275
mParser.reset();
276-
if (!isInitial && (mPartIterator == mInputIterator.end() || ++mPartIterator == mInputIterator.end())) {
276+
if (!isInitial && ++mPartIterator == mCurrentRange.end()) {
277277
// no more parts, go to next input
278278
break;
279279
}
@@ -312,14 +312,16 @@ class DPLRawParser
312312
}
313313
} // end loop over parts on one input
314314
++mInputIterator;
315-
mPartIterator = mInputIterator.begin();
315+
mCurrentRange = mInputIterator.parts();
316+
mPartIterator = mCurrentRange.begin();
316317
} // end loop over inputs
317318
return false;
318319
}
319320

320321
InputRecord& mParent;
321322
input_iterator mInputIterator;
322323
input_iterator mEnd;
324+
part_range mCurrentRange; // declared before mPartIterator — initialized first
323325
part_iterator mPartIterator;
324326
std::unique_ptr<parser_type> mParser;
325327
parser_iterator mCurrent;
@@ -355,4 +357,4 @@ class DPLRawParser
355357

356358
} // namespace o2::framework
357359

358-
#endif //FRAMEWORK_UTILS_DPLRAWPARSER_H
360+
#endif // FRAMEWORK_UTILS_DPLRAWPARSER_H

0 commit comments

Comments
 (0)