Skip to content

Commit d6f5e1e

Browse files
committed
Refactoring
1. Remove recursion of operator++(), this leads to constant memory usage rather than filling the stack at some point 2. Extract subroutines from operator++() 3. Steal some refactoring that solved some bugs on topic-read-leniently, so it stands to reason that we should apply it here already
1 parent 4951d58 commit d6f5e1e

6 files changed

Lines changed: 313 additions & 124 deletions

File tree

include/openPMD/Iteration.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,14 @@ class Iteration : public Attributable
329329
*/
330330
BeginStepStatus beginStep(bool reread);
331331

332+
/*
333+
* Iteration-independent variant for beginStep().
334+
* Useful in group-based iteration encoding where the Iteration will only
335+
* be known after opening the step.
336+
*/
337+
static BeginStepStatus
338+
beginStep(std::optional<Iteration> thisObject, Series &series, bool reread);
339+
332340
/**
333341
* @brief End an IO step on the IO file (or file-like object)
334342
* containing this iteration. In case of group-based iteration

include/openPMD/ReadIterations.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,24 @@ class SeriesIterator
8989
m_currentIteration = *m_iterationsInCurrentStep.begin();
9090
return true;
9191
}
92+
93+
inline std::optional<uint64_t> peekCurrentIteration()
94+
{
95+
if (m_iterationsInCurrentStep.empty())
96+
{
97+
return std::nullopt;
98+
}
99+
else
100+
{
101+
return {*m_iterationsInCurrentStep.begin()};
102+
}
103+
}
104+
105+
std::optional<SeriesIterator *> nextIterationInStep();
106+
107+
std::optional<SeriesIterator *> nextStep();
108+
109+
std::optional<SeriesIterator *> loopBody();
92110
};
93111

94112
/**

include/openPMD/Series.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,13 +640,21 @@ OPENPMD_private
640640
iterations_iterator it,
641641
Iteration &iteration);
642642

643+
AdvanceStatus advance(AdvanceMode mode);
644+
643645
/**
644646
* @brief Called at the end of an IO step to store the iterations defined
645647
* in the IO step to the snapshot attribute.
646648
*
647649
* @param doFlush If true, flush the IO handler.
648650
*/
649651
void flushStep(bool doFlush);
652+
653+
/*
654+
* Returns the current content of the /data/snapshot attribute.
655+
* (We could also add this to the public API some time)
656+
*/
657+
std::optional<std::vector<uint64_t> > currentSnapshot() const;
650658
}; // Series
651659
} // namespace openPMD
652660

src/Iteration.cpp

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -569,24 +569,53 @@ void Iteration::read_impl(std::string const &groupPath)
569569
auto Iteration::beginStep(bool reread) -> BeginStepStatus
570570
{
571571
BeginStepStatus res;
572-
using IE = IterationEncoding;
573572
auto series = retrieveSeries();
573+
return beginStep({*this}, series, reread);
574+
}
575+
576+
auto Iteration::beginStep(
577+
std::optional<Iteration> thisObject, Series &series, bool reread)
578+
-> BeginStepStatus
579+
{
580+
BeginStepStatus res;
581+
using IE = IterationEncoding;
574582
// Initialize file with this to quiet warnings
575583
// The following switch is comprehensive
576584
internal::AttributableData *file = nullptr;
577585
switch (series.iterationEncoding())
578586
{
579587
case IE::fileBased:
580-
file = &Attributable::get();
588+
if (thisObject.has_value())
589+
{
590+
file = &static_cast<Attributable &>(*thisObject).get();
591+
}
592+
else
593+
{
594+
throw error::Internal(
595+
"Advancing a step in file-based iteration encoding is "
596+
"iteration-specific.");
597+
}
581598
break;
582599
case IE::groupBased:
583600
case IE::variableBased:
584601
file = &series.get();
585602
break;
586603
}
587604

588-
AdvanceStatus status = series.advance(
589-
AdvanceMode::BEGINSTEP, *file, series.indexOf(*this), *this);
605+
AdvanceStatus status;
606+
if (thisObject.has_value())
607+
{
608+
status = series.advance(
609+
AdvanceMode::BEGINSTEP,
610+
*file,
611+
series.indexOf(*thisObject),
612+
*thisObject);
613+
}
614+
else
615+
{
616+
status = series.advance(AdvanceMode::BEGINSTEP);
617+
}
618+
590619
switch (status)
591620
{
592621
case AdvanceStatus::OVER:
@@ -598,22 +627,31 @@ auto Iteration::beginStep(bool reread) -> BeginStepStatus
598627
}
599628

600629
// re-read -> new datasets might be available
601-
if (reread &&
630+
auto IOHandl = series.IOHandler();
631+
if (reread && status != AdvanceStatus::RANDOMACCESS &&
602632
(series.iterationEncoding() == IE::groupBased ||
603633
series.iterationEncoding() == IE::variableBased) &&
604-
(this->IOHandler()->m_frontendAccess == Access::READ_ONLY ||
605-
this->IOHandler()->m_frontendAccess == Access::READ_WRITE))
634+
(IOHandl->m_frontendAccess == Access::READ_ONLY ||
635+
IOHandl->m_frontendAccess == Access::READ_WRITE))
606636
{
607-
switch (IOHandler()->m_frontendAccess)
637+
switch (IOHandl->m_frontendAccess)
608638
{
609639
case Access::READ_ONLY:
610640
case Access::READ_WRITE: {
611641
bool previous = series.iterations.written();
612642
series.iterations.written() = false;
613-
auto oldStatus = IOHandler()->m_seriesStatus;
614-
IOHandler()->m_seriesStatus = internal::SeriesStatus::Parsing;
615-
res.iterationsInOpenedStep = series.readGorVBased(false);
616-
IOHandler()->m_seriesStatus = oldStatus;
643+
auto oldStatus = IOHandl->m_seriesStatus;
644+
IOHandl->m_seriesStatus = internal::SeriesStatus::Parsing;
645+
try
646+
{
647+
res.iterationsInOpenedStep = series.readGorVBased(false);
648+
}
649+
catch (...)
650+
{
651+
IOHandl->m_seriesStatus = oldStatus;
652+
throw;
653+
}
654+
IOHandl->m_seriesStatus = oldStatus;
617655
series.iterations.written() = previous;
618656
break;
619657
}

0 commit comments

Comments
 (0)