Skip to content

Commit 86d478e

Browse files
committed
No longer use map entry SCALAR in application logic
Not yet supported: Backward compatibility for still allowing legacy access to scalar entries
1 parent a65eda3 commit 86d478e

15 files changed

+110
-98
lines changed

include/openPMD/ParticleSpecies.hpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,9 @@ namespace traits
6868
ret.particlePatches.linkHierarchy(ret.writable());
6969

7070
auto &np = ret.particlePatches["numParticles"];
71-
auto &npc = np[RecordComponent::SCALAR];
72-
npc.resetDataset(Dataset(determineDatatype<uint64_t>(), {1}));
73-
npc.parent() = np.parent();
71+
np.resetDataset(Dataset(determineDatatype<uint64_t>(), {1}));
7472
auto &npo = ret.particlePatches["numParticlesOffset"];
75-
auto &npoc = npo[RecordComponent::SCALAR];
76-
npoc.resetDataset(Dataset(determineDatatype<uint64_t>(), {1}));
77-
npoc.parent() = npo.parent();
73+
npo.resetDataset(Dataset(determineDatatype<uint64_t>(), {1}));
7874
}
7975
};
8076
} // namespace traits

include/openPMD/backend/BaseRecord.hpp

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,6 @@ namespace internal
4444
, public T_RecordComponentData
4545
{
4646
public:
47-
/**
48-
* True if this Record contains a scalar record component.
49-
* If so, then that record component is the only component contained,
50-
* and the last hierarchical layer is skipped (i.e. only one OPEN_PATH
51-
* task for Record and RecordComponent).
52-
*/
53-
bool m_containsScalar = false;
54-
5547
BaseRecordData();
5648

5749
BaseRecordData(BaseRecordData const &) = delete;
@@ -124,6 +116,8 @@ class BaseRecord
124116

125117
mapped_type &operator[](key_type const &key) override;
126118
mapped_type &operator[](key_type &&key) override;
119+
mapped_type &at(key_type const &key);
120+
mapped_type const &at(key_type const &key) const;
127121
size_type erase(key_type const &key) override;
128122
iterator erase(iterator res) override;
129123
//! @todo add also, as soon as added in Container:
@@ -162,7 +156,6 @@ class BaseRecord
162156
void flush(std::string const &, internal::FlushParams const &) final;
163157
virtual void
164158
flush_impl(std::string const &, internal::FlushParams const &) = 0;
165-
virtual void read() = 0;
166159

167160
/**
168161
* @brief Check recursively whether this BaseRecord is dirty.
@@ -214,12 +207,15 @@ BaseRecord<T_elem>::operator[](key_type const &key)
214207
"A scalar component can not be contained at "
215208
"the same time as one or more regular components.");
216209

217-
mapped_type &ret = Container<T_elem>::operator[](key);
218210
if (keyScalar)
219211
{
220-
get().m_containsScalar = true;
221-
ret.parent() = this->parent();
212+
/*
213+
* This activates the RecordComponent API of this object.
214+
*/
215+
T_RecordComponent::get();
222216
}
217+
mapped_type &ret = keyScalar ? static_cast<mapped_type &>(*this)
218+
: T_Container::operator[](key);
223219
return ret;
224220
}
225221
}
@@ -240,16 +236,45 @@ BaseRecord<T_elem>::operator[](key_type &&key)
240236
"A scalar component can not be contained at "
241237
"the same time as one or more regular components.");
242238

243-
mapped_type &ret = Container<T_elem>::operator[](std::move(key));
244239
if (keyScalar)
245240
{
246-
get().m_containsScalar = true;
247-
ret.parent() = this->parent();
241+
/*
242+
* This activates the RecordComponent API of this object.
243+
*/
244+
T_RecordComponent::get();
248245
}
246+
mapped_type &ret = keyScalar ? static_cast<mapped_type &>(*this)
247+
: T_Container::operator[](std::move(key));
249248
return ret;
250249
}
251250
}
252251

252+
template <typename T_elem>
253+
auto BaseRecord<T_elem>::at(key_type const &key) -> mapped_type &
254+
{
255+
return const_cast<mapped_type &>(
256+
static_cast<BaseRecord<T_elem> const *>(this)->at(key));
257+
}
258+
259+
template <typename T_elem>
260+
auto BaseRecord<T_elem>::at(key_type const &key) const -> mapped_type const &
261+
{
262+
bool const keyScalar = (key == RecordComponent::SCALAR);
263+
if (keyScalar)
264+
{
265+
if (!get().m_datasetDefined)
266+
{
267+
throw std::out_of_range(
268+
"[at()] Requested scalar entry from non-scalar record.");
269+
}
270+
return static_cast<mapped_type const &>(*this);
271+
}
272+
else
273+
{
274+
return T_Container::at(key);
275+
}
276+
}
277+
253278
template <typename T_elem>
254279
inline typename BaseRecord<T_elem>::size_type
255280
BaseRecord<T_elem>::erase(key_type const &key)
@@ -260,22 +285,21 @@ BaseRecord<T_elem>::erase(key_type const &key)
260285
res = Container<T_elem>::erase(key);
261286
else
262287
{
263-
mapped_type &rc = this->find(RecordComponent::SCALAR)->second;
264-
if (rc.written())
288+
if (this->written())
265289
{
266290
Parameter<Operation::DELETE_DATASET> dDelete;
267291
dDelete.name = ".";
268-
this->IOHandler()->enqueue(IOTask(&rc, dDelete));
292+
this->IOHandler()->enqueue(IOTask(this, dDelete));
269293
this->IOHandler()->flush(internal::defaultFlushParams);
270294
}
271-
res = Container<T_elem>::erase(key);
295+
res = this->datasetDefined() ? 1 : 0;
272296
}
273297

274298
if (keyScalar)
275299
{
276300
this->written() = false;
277301
this->writable().abstractFilePosition.reset();
278-
this->get().m_containsScalar = false;
302+
this->get().m_datasetDefined = false;
279303
}
280304
return res;
281305
}
@@ -290,23 +314,11 @@ BaseRecord<T_elem>::erase(iterator res)
290314
ret = Container<T_elem>::erase(res);
291315
else
292316
{
293-
mapped_type &rc = this->find(RecordComponent::SCALAR)->second;
294-
if (rc.written())
295-
{
296-
Parameter<Operation::DELETE_DATASET> dDelete;
297-
dDelete.name = ".";
298-
this->IOHandler()->enqueue(IOTask(&rc, dDelete));
299-
this->IOHandler()->flush(internal::defaultFlushParams);
300-
}
301-
ret = Container<T_elem>::erase(res);
317+
throw std::runtime_error(
318+
"Unreachable! Iterators do not yet cover scalars (they will in a "
319+
"later commit).");
302320
}
303321

304-
if (keyScalar)
305-
{
306-
this->written() = false;
307-
this->writable().abstractFilePosition.reset();
308-
this->get().m_containsScalar = false;
309-
}
310322
return ret;
311323
}
312324

@@ -320,7 +332,7 @@ inline std::array<double, 7> BaseRecord<T_elem>::unitDimension() const
320332
template <typename T_elem>
321333
inline bool BaseRecord<T_elem>::scalar() const
322334
{
323-
return get().m_containsScalar;
335+
return this->datasetDefined();
324336
}
325337

326338
template <typename T_elem>
@@ -362,7 +374,8 @@ template <typename T_elem>
362374
inline void BaseRecord<T_elem>::flush(
363375
std::string const &name, internal::FlushParams const &flushParams)
364376
{
365-
if (!this->written() && this->T_Container::empty())
377+
if (!this->written() && this->T_Container::empty() &&
378+
!this->datasetDefined())
366379
throw std::runtime_error(
367380
"A Record can not be written without any contained "
368381
"RecordComponents: " +

include/openPMD/backend/MeshRecordComponent.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class MeshRecordComponent : public RecordComponent
3939
MeshRecordComponent();
4040
MeshRecordComponent(NoInit);
4141
void read() override;
42+
void flush(std::string const &, internal::FlushParams const &);
4243

4344
public:
4445
~MeshRecordComponent() override = default;

include/openPMD/backend/PatchRecordComponent.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ OPENPMD_private
105105
// clang-format on
106106

107107
void flush(std::string const &, internal::FlushParams const &);
108-
void read();
108+
virtual void read();
109109

110110
/**
111111
* @brief Check recursively whether this RecordComponent is dirty.

src/Iteration.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -569,8 +569,7 @@ void Iteration::readMeshes(std::string const &meshesPath)
569569
auto shape = std::find(att_begin, att_end, "shape");
570570
if (value != att_end && shape != att_end)
571571
{
572-
MeshRecordComponent &mrc = m[MeshRecordComponent::SCALAR];
573-
mrc.parent() = m.parent();
572+
MeshRecordComponent &mrc = m;
574573
IOHandler()->enqueue(IOTask(&mrc, pOpen));
575574
IOHandler()->flush(internal::defaultFlushParams);
576575
mrc.get().m_isConstant = true;
@@ -601,8 +600,7 @@ void Iteration::readMeshes(std::string const &meshesPath)
601600
dOpen.name = mesh_name;
602601
IOHandler()->enqueue(IOTask(&m, dOpen));
603602
IOHandler()->flush(internal::defaultFlushParams);
604-
MeshRecordComponent &mrc = m[MeshRecordComponent::SCALAR];
605-
mrc.parent() = m.parent();
603+
MeshRecordComponent &mrc = m;
606604
IOHandler()->enqueue(IOTask(&mrc, dOpen));
607605
IOHandler()->flush(internal::defaultFlushParams);
608606
mrc.written() = false;

src/Mesh.cpp

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -219,21 +219,25 @@ void Mesh::flush_impl(
219219
{
220220
if (access::readOnly(IOHandler()->m_frontendAccess))
221221
{
222-
for (auto &comp : *this)
223-
comp.second.flush(comp.first, flushParams);
222+
auto &m = get();
223+
if (m.m_datasetDefined)
224+
{
225+
T_RecordComponent::flush(SCALAR, flushParams);
226+
}
227+
else
228+
{
229+
for (auto &comp : *this)
230+
comp.second.flush(comp.first, flushParams);
231+
}
224232
}
225233
else
226234
{
227235
if (!written())
228236
{
229237
if (scalar())
230238
{
231-
MeshRecordComponent &mrc = at(RecordComponent::SCALAR);
232-
mrc.parent() = parent();
239+
MeshRecordComponent &mrc = *this;
233240
mrc.flush(name, flushParams);
234-
Parameter<Operation::KEEP_SYNCHRONOUS> pSynchronize;
235-
pSynchronize.otherWritable = &mrc.writable();
236-
IOHandler()->enqueue(IOTask(this, pSynchronize));
237241
}
238242
else
239243
{
@@ -251,12 +255,7 @@ void Mesh::flush_impl(
251255
{
252256
if (scalar())
253257
{
254-
for (auto &comp : *this)
255-
{
256-
comp.second.flush(name, flushParams);
257-
writable().abstractFilePosition =
258-
comp.second.writable().abstractFilePosition;
259-
}
258+
T_RecordComponent::flush(name, flushParams);
260259
}
261260
else
262261
{
@@ -400,8 +399,7 @@ void Mesh::read()
400399

401400
if (scalar())
402401
{
403-
/* using operator[] will incorrectly update parent */
404-
map.at(MeshRecordComponent::SCALAR).read();
402+
T_RecordComponent::read();
405403
}
406404
else
407405
{

src/ParticlePatches.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ size_t ParticlePatches::numPatches() const
3232
if (this->empty())
3333
return 0;
3434

35-
return this->at("numParticles").at(RecordComponent::SCALAR).getExtent()[0];
35+
return this->at("numParticles").getExtent()[0];
3636
}
3737

3838
void ParticlePatches::read()
@@ -78,10 +78,8 @@ void ParticlePatches::read()
7878
}
7979

8080
PatchRecord &pr = Container<PatchRecord>::operator[](component_name);
81-
PatchRecordComponent &prc = pr[RecordComponent::SCALAR];
82-
prc.parent() = pr.parent();
81+
PatchRecordComponent &prc = pr;
8382
dOpen.name = component_name;
84-
IOHandler()->enqueue(IOTask(&pr, dOpen));
8583
IOHandler()->enqueue(IOTask(&prc, dOpen));
8684
IOHandler()->flush(internal::defaultFlushParams);
8785

@@ -102,7 +100,7 @@ void ParticlePatches::read()
102100
pr.dirty() = false;
103101
try
104102
{
105-
prc.read();
103+
prc.PatchRecordComponent::read();
106104
}
107105
catch (error::ReadError const &err)
108106
{

src/ParticleSpecies.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,7 @@ void ParticleSpecies::read()
7979
auto shape = std::find(att_begin, att_end, "shape");
8080
if (value != att_end && shape != att_end)
8181
{
82-
internal::EraseStaleEntries<Record &> scalarMap(r);
83-
RecordComponent &rc = scalarMap[RecordComponent::SCALAR];
84-
rc.parent() = r.parent();
82+
RecordComponent &rc = r;
8583
IOHandler()->enqueue(IOTask(&rc, pOpen));
8684
IOHandler()->flush(internal::defaultFlushParams);
8785
rc.get().m_isConstant = true;
@@ -122,9 +120,7 @@ void ParticleSpecies::read()
122120
dOpen.name = record_name;
123121
IOHandler()->enqueue(IOTask(&r, dOpen));
124122
IOHandler()->flush(internal::defaultFlushParams);
125-
internal::EraseStaleEntries<Record &> scalarMap(r);
126-
RecordComponent &rc = scalarMap[RecordComponent::SCALAR];
127-
rc.parent() = r.parent();
123+
RecordComponent &rc = r;
128124
IOHandler()->enqueue(IOTask(&rc, dOpen));
129125
IOHandler()->flush(internal::defaultFlushParams);
130126
rc.written() = false;

src/Record.cpp

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,24 @@ void Record::flush_impl(
4848
{
4949
if (access::readOnly(IOHandler()->m_frontendAccess))
5050
{
51-
for (auto &comp : *this)
52-
comp.second.flush(comp.first, flushParams);
51+
if (scalar())
52+
{
53+
T_RecordComponent::flush(SCALAR, flushParams);
54+
}
55+
else
56+
{
57+
for (auto &comp : *this)
58+
comp.second.flush(comp.first, flushParams);
59+
}
5360
}
5461
else
5562
{
5663
if (!written())
5764
{
5865
if (scalar())
5966
{
60-
RecordComponent &rc = at(RecordComponent::SCALAR);
61-
rc.parent() = parent();
67+
RecordComponent &rc = *this;
6268
rc.flush(name, flushParams);
63-
Parameter<Operation::KEEP_SYNCHRONOUS> pSynchronize;
64-
pSynchronize.otherWritable = &rc.writable();
65-
IOHandler()->enqueue(IOTask(this, pSynchronize));
6669
}
6770
else
6871
{
@@ -81,12 +84,7 @@ void Record::flush_impl(
8184

8285
if (scalar())
8386
{
84-
for (auto &comp : *this)
85-
{
86-
comp.second.flush(name, flushParams);
87-
writable().abstractFilePosition =
88-
comp.second.writable().abstractFilePosition;
89-
}
87+
T_RecordComponent::flush(name, flushParams);
9088
}
9189
else
9290
{
@@ -104,17 +102,15 @@ void Record::read()
104102
if (scalar())
105103
{
106104
/* using operator[] will incorrectly update parent */
107-
auto &scalarComponent = this->at(RecordComponent::SCALAR);
108105
try
109106
{
110-
scalarComponent.read();
107+
T_RecordComponent::read();
111108
}
112109
catch (error::ReadError const &err)
113110
{
114111
std::cerr << "Cannot read scalar record component and will skip it "
115112
"due to read error:\n"
116113
<< err.what() << std::endl;
117-
this->container().erase(RecordComponent::SCALAR);
118114
}
119115
}
120116
else

0 commit comments

Comments
 (0)