Skip to content

Commit b6645b4

Browse files
committed
Prepare Attributable for virtual inheritance
Only one instance of std::shared<Data_t>, dynamically casted Use only zero-param constructors to avoid diamond initialization pitfalls
1 parent d212b10 commit b6645b4

16 files changed

+100
-182
lines changed

include/openPMD/Iteration.hpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -244,17 +244,14 @@ class Iteration : public Attributable
244244
private:
245245
Iteration();
246246

247-
std::shared_ptr<internal::IterationData> m_iterationData{
248-
new internal::IterationData};
249-
250247
inline internal::IterationData const &get() const
251248
{
252-
return *m_iterationData;
249+
return dynamic_cast<internal::IterationData const &>(*m_attri);
253250
}
254251

255252
inline internal::IterationData &get()
256253
{
257-
return *m_iterationData;
254+
return dynamic_cast<internal::IterationData &>(*m_attri);
258255
}
259256

260257
void flushFileBased(

include/openPMD/RecordComponent.hpp

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ class RecordComponent : public BaseRecordComponent
105105
friend class ParticleSpecies;
106106
template <typename T_elem>
107107
friend class BaseRecord;
108-
template <typename T_elem>
109-
friend class BaseRecordInterface;
110108
friend class Record;
111109
friend class Mesh;
112110
template <typename>
@@ -431,31 +429,23 @@ class RecordComponent : public BaseRecordComponent
431429
*/
432430
bool dirtyRecursive() const;
433431

434-
std::shared_ptr<internal::RecordComponentData> m_recordComponentData{
435-
new internal::RecordComponentData()};
436-
437-
RecordComponent();
438-
439432
// clang-format off
440433
OPENPMD_protected
441434
// clang-format on
442435

443-
RecordComponent(std::shared_ptr<internal::RecordComponentData>);
436+
using Data_t = internal::RecordComponentData;
444437

445-
inline internal::RecordComponentData const &get() const
446-
{
447-
return *m_recordComponentData;
448-
}
438+
RecordComponent();
449439

450-
inline internal::RecordComponentData &get()
440+
inline Data_t const &get() const
451441
{
452-
return *m_recordComponentData;
442+
return dynamic_cast<Data_t const &>(*m_attri);
453443
}
454444

455-
inline void setData(std::shared_ptr<internal::RecordComponentData> data)
445+
inline Data_t &get()
456446
{
457-
m_recordComponentData = std::move(data);
458-
BaseRecordComponent::setData(m_recordComponentData);
447+
auto &res = dynamic_cast<Data_t &>(*m_attri);
448+
return res;
459449
}
460450

461451
void readBase();

include/openPMD/Series.hpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,13 @@ namespace internal
6363
*
6464
* (Not movable or copyable)
6565
*
66+
* Class is final since our std::shared_ptr<Data_t> pattern has the little
67+
* disadvantage that child constructors overwrite the parent constructors.
68+
* Since the SeriesData constructor does some initialization, making this
69+
* class final avoids stumbling over this pitfall.
70+
*
6671
*/
67-
class SeriesData : public AttributableData
72+
class SeriesData final : public AttributableData
6873
{
6974
public:
7075
explicit SeriesData() = default;
@@ -192,10 +197,6 @@ class Series : public Attributable
192197
friend class internal::SeriesData;
193198
friend class WriteIterations;
194199

195-
protected:
196-
// Should not be called publicly, only by implementing classes
197-
Series(std::shared_ptr<internal::SeriesData>);
198-
199200
public:
200201
explicit Series();
201202

@@ -533,13 +534,11 @@ OPENPMD_private
533534
using iterations_t = decltype(internal::SeriesData::iterations);
534535
using iterations_iterator = iterations_t::iterator;
535536

536-
std::shared_ptr<internal::SeriesData> m_series = nullptr;
537-
538537
inline internal::SeriesData &get()
539538
{
540-
if (m_series)
539+
if (m_attri)
541540
{
542-
return *m_series;
541+
return dynamic_cast<internal::SeriesData &>(*m_attri);
543542
}
544543
else
545544
{
@@ -550,9 +549,9 @@ OPENPMD_private
550549

551550
inline internal::SeriesData const &get() const
552551
{
553-
if (m_series)
552+
if (m_attri)
554553
{
555-
return *m_series;
554+
return dynamic_cast<internal::SeriesData const &>(*m_attri);
556555
}
557556
else
558557
{
@@ -561,6 +560,12 @@ OPENPMD_private
561560
}
562561
}
563562

563+
inline void setData(std::shared_ptr<internal::SeriesData> series)
564+
{
565+
iterations = series->iterations;
566+
Attributable::setData(std::move(series));
567+
}
568+
564569
std::unique_ptr<ParsedInput> parseInput(std::string);
565570
/**
566571
* @brief Parse non-backend-specific configuration in JSON config.

include/openPMD/backend/Attributable.hpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,6 @@ class Attributable
114114
std::shared_ptr<internal::AttributableData> m_attri{
115115
new internal::AttributableData()};
116116

117-
// Should not be called publicly, only by implementing classes
118-
Attributable(std::shared_ptr<internal::AttributableData>);
119-
120117
public:
121118
Attributable();
122119

@@ -356,9 +353,11 @@ OPENPMD_protected
356353
return m_attri->m_writable;
357354
}
358355

359-
inline void setData(std::shared_ptr<internal::AttributableData> attri)
356+
template <typename T = internal::AttributableData>
357+
inline void setData(std::shared_ptr<T> attri)
360358
{
361-
m_attri = std::move(attri);
359+
m_attri = std::static_pointer_cast<internal::AttributableData>(
360+
std::move(attri));
362361
}
363362

364363
inline internal::AttributableData &get()

include/openPMD/backend/BaseRecord.hpp

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -63,30 +63,21 @@ class BaseRecord : public Container<T_elem>
6363
friend class Record;
6464
friend class Mesh;
6565

66-
std::shared_ptr<internal::BaseRecordData<T_elem> > m_baseRecordData{
67-
new internal::BaseRecordData<T_elem>()};
66+
using Data_t = internal::BaseRecordData<T_elem>;
67+
std::shared_ptr<Data_t> m_baseRecordData{new Data_t()};
6868

69-
inline internal::BaseRecordData<T_elem> &get()
69+
inline Data_t const &get() const
7070
{
71-
return *m_baseRecordData;
71+
return dynamic_cast<Data_t const &>(*this->m_attri);
7272
}
7373

74-
inline internal::BaseRecordData<T_elem> const &get() const
74+
inline Data_t &get()
7575
{
76-
return *m_baseRecordData;
76+
return dynamic_cast<Data_t &>(*this->m_attri);
7777
}
7878

7979
BaseRecord();
8080

81-
protected:
82-
BaseRecord(std::shared_ptr<internal::BaseRecordData<T_elem> >);
83-
84-
inline void setData(internal::BaseRecordData<T_elem> *data)
85-
{
86-
m_baseRecordData = std::move(data);
87-
Container<T_elem>::setData(m_baseRecordData);
88-
}
89-
9081
public:
9182
using key_type = typename Container<T_elem>::key_type;
9283
using mapped_type = typename Container<T_elem>::mapped_type;
@@ -137,7 +128,6 @@ class BaseRecord : public Container<T_elem>
137128
bool scalar() const;
138129

139130
protected:
140-
BaseRecord(internal::BaseRecordData<T_elem> *);
141131
void readBase();
142132

143133
private:
@@ -164,25 +154,20 @@ namespace internal
164154
template <typename T_elem>
165155
BaseRecordData<T_elem>::BaseRecordData()
166156
{
167-
Attributable impl{{this, [](auto const *) {}}};
157+
Attributable impl;
158+
impl.setData({this, [](auto const *) {}});
168159
impl.setAttribute(
169160
"unitDimension",
170161
std::array<double, 7>{{0., 0., 0., 0., 0., 0., 0.}});
171162
}
172163
} // namespace internal
173164

174165
template <typename T_elem>
175-
BaseRecord<T_elem>::BaseRecord() : Container<T_elem>{nullptr}
166+
BaseRecord<T_elem>::BaseRecord()
176167
{
177-
Container<T_elem>::setData(m_baseRecordData);
168+
Attributable::setData(std::make_shared<Data_t>());
178169
}
179170

180-
template <typename T_elem>
181-
BaseRecord<T_elem>::BaseRecord(
182-
std::shared_ptr<internal::BaseRecordData<T_elem> > data)
183-
: Container<T_elem>{data}, m_baseRecordData{std::move(data)}
184-
{}
185-
186171
template <typename T_elem>
187172
inline typename BaseRecord<T_elem>::mapped_type &
188173
BaseRecord<T_elem>::operator[](key_type const &key)

include/openPMD/backend/BaseRecordComponent.hpp

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ namespace openPMD
3535
{
3636
namespace internal
3737
{
38-
class BaseRecordComponentData : public AttributableData
38+
class BaseRecordComponentData : virtual public AttributableData
3939
{
4040
public:
4141
/**
@@ -61,7 +61,7 @@ namespace internal
6161
};
6262
} // namespace internal
6363

64-
class BaseRecordComponent : public Attributable
64+
class BaseRecordComponent : virtual public Attributable
6565
{
6666
template <typename T, typename T_key, typename T_container>
6767
friend class Container;
@@ -102,28 +102,18 @@ class BaseRecordComponent : public Attributable
102102
ChunkTable availableChunks();
103103

104104
protected:
105-
std::shared_ptr<internal::BaseRecordComponentData>
106-
m_baseRecordComponentData{new internal::BaseRecordComponentData()};
105+
using Data_t = internal::BaseRecordComponentData;
107106

108-
inline internal::BaseRecordComponentData const &get() const
107+
inline Data_t const &get() const
109108
{
110-
return *m_baseRecordComponentData;
109+
return dynamic_cast<Data_t const &>(*m_attri);
111110
}
112111

113-
inline internal::BaseRecordComponentData &get()
112+
inline Data_t &get()
114113
{
115-
return *m_baseRecordComponentData;
114+
return dynamic_cast<Data_t &>(*m_attri);
116115
}
117116

118-
inline void setData(std::shared_ptr<internal::BaseRecordComponentData> data)
119-
{
120-
m_baseRecordComponentData = std::move(data);
121-
Attributable::setData(m_baseRecordComponentData);
122-
}
123-
124-
BaseRecordComponent(std::shared_ptr<internal::BaseRecordComponentData>);
125-
126-
private:
127117
BaseRecordComponent();
128118
}; // BaseRecordComponent
129119

include/openPMD/backend/Container.hpp

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ namespace internal
6565
typename T,
6666
typename T_key = std::string,
6767
typename T_container = std::map<T_key, T> >
68-
class ContainerData : public AttributableData
68+
class ContainerData : virtual public AttributableData
6969
{
7070
public:
7171
using InternalContainer = T_container;
@@ -128,7 +128,7 @@ template <
128128
typename T,
129129
typename T_key = std::string,
130130
typename T_container = std::map<T_key, T> >
131-
class Container : public Attributable
131+
class Container : virtual public Attributable
132132
{
133133
static_assert(
134134
std::is_base_of<Attributable, T>::value,
@@ -147,22 +147,14 @@ class Container : public Attributable
147147
using ContainerData = internal::ContainerData<T, T_key, T_container>;
148148
using InternalContainer = T_container;
149149

150-
std::shared_ptr<ContainerData> m_containerData{new ContainerData()};
151-
152-
inline void setData(std::shared_ptr<ContainerData> containerData)
153-
{
154-
m_containerData = std::move(containerData);
155-
Attributable::setData(m_containerData);
156-
}
157-
158150
inline InternalContainer const &container() const
159151
{
160-
return m_containerData->m_container;
152+
return dynamic_cast<ContainerData const &>(*m_attri).m_container;
161153
}
162154

163155
inline InternalContainer &container()
164156
{
165-
return m_containerData->m_container;
157+
return dynamic_cast<ContainerData &>(*m_attri).m_container;
166158
}
167159

168160
public:
@@ -428,10 +420,6 @@ class Container : public Attributable
428420
OPENPMD_protected
429421
// clang-format on
430422

431-
Container(std::shared_ptr<ContainerData> containerData)
432-
: Attributable{containerData}, m_containerData{std::move(containerData)}
433-
{}
434-
435423
void clear_unchecked()
436424
{
437425
if (written())
@@ -454,13 +442,9 @@ OPENPMD_protected
454442
flushAttributes(flushParams);
455443
}
456444

457-
// clang-format off
458-
OPENPMD_private
459-
// clang-format on
460-
461-
Container() : Attributable{nullptr}
445+
Container()
462446
{
463-
Attributable::setData(m_containerData);
447+
Attributable::setData(std::make_shared<ContainerData>());
464448
}
465449
};
466450

@@ -532,7 +516,8 @@ namespace internal
532516
~EraseStaleEntries()
533517
{
534518
auto &map = m_originalContainer.container();
535-
using iterator_t = typename BareContainer_t::const_iterator;
519+
using iterator_t =
520+
typename BareContainer_t::InternalContainer::const_iterator;
536521
std::vector<iterator_t> deleteMe;
537522
deleteMe.reserve(map.size() - m_accessedKeys.size());
538523
for (iterator_t it = map.begin(); it != map.end(); ++it)

0 commit comments

Comments
 (0)