Skip to content

Commit fd672b1

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 b37582b commit fd672b1

16 files changed

+100
-180
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>
@@ -432,31 +430,23 @@ class RecordComponent : public BaseRecordComponent
432430
*/
433431
bool dirtyRecursive() const;
434432

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

444-
RecordComponent(std::shared_ptr<internal::RecordComponentData>);
437+
using Data_t = internal::RecordComponentData;
445438

446-
inline internal::RecordComponentData const &get() const
447-
{
448-
return *m_recordComponentData;
449-
}
439+
RecordComponent();
450440

451-
inline internal::RecordComponentData &get()
441+
inline Data_t const &get() const
452442
{
453-
return *m_recordComponentData;
443+
return dynamic_cast<Data_t const &>(*m_attri);
454444
}
455445

456-
inline void setData(std::shared_ptr<internal::RecordComponentData> data)
446+
inline Data_t &get()
457447
{
458-
m_recordComponentData = std::move(data);
459-
BaseRecordComponent::setData(m_recordComponentData);
448+
auto &res = dynamic_cast<Data_t &>(*m_attri);
449+
return res;
460450
}
461451

462452
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
@@ -33,7 +33,7 @@ namespace openPMD
3333
{
3434
namespace internal
3535
{
36-
class BaseRecordComponentData : public AttributableData
36+
class BaseRecordComponentData : virtual public AttributableData
3737
{
3838
public:
3939
/**
@@ -59,7 +59,7 @@ namespace internal
5959
};
6060
} // namespace internal
6161

62-
class BaseRecordComponent : public Attributable
62+
class BaseRecordComponent : virtual public Attributable
6363
{
6464
template <typename T, typename T_key, typename T_container>
6565
friend class Container;
@@ -100,28 +100,18 @@ class BaseRecordComponent : public Attributable
100100
ChunkTable availableChunks();
101101

102102
protected:
103-
std::shared_ptr<internal::BaseRecordComponentData>
104-
m_baseRecordComponentData{new internal::BaseRecordComponentData()};
103+
using Data_t = internal::BaseRecordComponentData;
105104

106-
inline internal::BaseRecordComponentData const &get() const
105+
inline Data_t const &get() const
107106
{
108-
return *m_baseRecordComponentData;
107+
return dynamic_cast<Data_t const &>(*m_attri);
109108
}
110109

111-
inline internal::BaseRecordComponentData &get()
110+
inline Data_t &get()
112111
{
113-
return *m_baseRecordComponentData;
112+
return dynamic_cast<Data_t &>(*m_attri);
114113
}
115114

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

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)