Skip to content

Commit

Permalink
Introduce SharedAttributableData
Browse files Browse the repository at this point in the history
  • Loading branch information
franzpoeschel committed Nov 15, 2024
1 parent d1015ee commit a41857c
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 32 deletions.
79 changes: 57 additions & 22 deletions include/openPMD/backend/Attributable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,19 @@ namespace internal
class IterationData;
class SeriesData;

class AttributableData
class SharedAttributableData
{
friend class openPMD::Attributable;

public:
AttributableData();
AttributableData(AttributableData const &) = delete;
AttributableData(AttributableData &&) = delete;
virtual ~AttributableData() = default;
SharedAttributableData(AttributableData *);
SharedAttributableData(SharedAttributableData const &) = delete;
SharedAttributableData(SharedAttributableData &&) = delete;
virtual ~SharedAttributableData() = default;

AttributableData &operator=(AttributableData const &) = delete;
AttributableData &operator=(AttributableData &&) = delete;
SharedAttributableData &
operator=(SharedAttributableData const &) = delete;
SharedAttributableData &operator=(SharedAttributableData &&) = delete;

using A_MAP = std::map<std::string, Attribute>;
/**
Expand All @@ -77,6 +78,46 @@ namespace internal
*/
Writable m_writable;

private:
/**
* The attributes defined by this Attributable.
*/
A_MAP m_attributes;
};

/*
* This is essentially a two-level pointer.
*
* 1. level: Our public API hands out handles to users that are (shared)
* pointers to an internal object (PIMPL).
* 2. level: Multiple internal objects might refer to the same item in an
* openPMD file, e.g. to the same backend object.
* So, the internal object for an Attributable is a shared pointer to the
* unique object identifying this item.
*
* Such sharing occurs in the CustomHierarchy class where multiple
* containers refer to the same group in the openPMD hierarchy
* (container of groups, of meshes, of particle species, of datasets).
* This might also become relevant for links as in HDF5 if we choose to
* implement them.
*/

class AttributableData : public std::shared_ptr<SharedAttributableData>
{
friend class openPMD::Attributable;

using SharedData_t = std::shared_ptr<SharedAttributableData>;

public:
AttributableData();
AttributableData(SharedAttributableData *);
AttributableData(AttributableData const &) = delete;
AttributableData(AttributableData &&) = delete;
virtual ~AttributableData() = default;

AttributableData &operator=(AttributableData const &) = delete;
AttributableData &operator=(AttributableData &&) = delete;

template <typename T>
T asInternalCopyOf()
{
Expand Down Expand Up @@ -112,12 +153,6 @@ namespace internal
std::shared_ptr<typename T::Data_t>(self, [](auto const *) {}));
return res;
}

private:
/**
* The attributes defined by this Attributable.
*/
A_MAP m_attributes;
};

template <typename, typename>
Expand Down Expand Up @@ -431,7 +466,7 @@ OPENPMD_protected
}
AbstractIOHandler const *IOHandler() const
{
auto &opt = m_attri->m_writable.IOHandler;
auto &opt = writable().IOHandler;
if (!opt || !opt->has_value())
{
return nullptr;
Expand All @@ -440,33 +475,33 @@ OPENPMD_protected
}
Writable *&parent()
{
return m_attri->m_writable.parent;
return writable().parent;
}
Writable const *parent() const
{
return m_attri->m_writable.parent;
return writable().parent;
}
Writable &writable()
{
return m_attri->m_writable;
return (*m_attri)->m_writable;
}
Writable const &writable() const
{
return m_attri->m_writable;
return (*m_attri)->m_writable;
}

inline void setData(std::shared_ptr<internal::AttributableData> attri)
{
m_attri = std::move(attri);
}

inline internal::AttributableData &get()
inline internal::SharedAttributableData &get()
{
return *m_attri;
return **m_attri;
}
inline internal::AttributableData const &get() const
inline internal::SharedAttributableData const &get() const
{
return *m_attri;
return **m_attri;
}

bool dirty() const
Expand Down
7 changes: 7 additions & 0 deletions include/openPMD/backend/Writable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class Series;

namespace internal
{
class SharedAttributableData;
class AttributableData;
class SeriesData;
} // namespace internal
Expand All @@ -73,6 +74,7 @@ namespace debug
*/
class Writable final
{
friend class internal::SharedAttributableData;
friend class internal::AttributableData;
friend class internal::SeriesData;
friend class Attributable;
Expand Down Expand Up @@ -142,6 +144,11 @@ OPENPMD_private
*/
std::shared_ptr<std::optional<std::unique_ptr<AbstractIOHandler>>>
IOHandler = nullptr;
/*
* Link to the containing Attributable.
* If multiple Attributables share the same Writable, then the creating one.
* (See SharedAttributableData)
*/
internal::AttributableData *attributable = nullptr;
Writable *parent = nullptr;

Expand Down
6 changes: 4 additions & 2 deletions src/Iteration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "openPMD/auxiliary/DerefDynamicCast.hpp"
#include "openPMD/auxiliary/Filesystem.hpp"
#include "openPMD/auxiliary/StringManip.hpp"
#include "openPMD/backend/Attributable.hpp"
#include "openPMD/backend/Writable.hpp"

#include <exception>
Expand Down Expand Up @@ -708,7 +709,8 @@ auto Iteration::beginStep(
case IE::fileBased:
if (thisObject.has_value())
{
file = &static_cast<Attributable &>(*thisObject).get();
file = static_cast<internal::AttributableData *>(
thisObject.value().m_attri.get());
}
else
{
Expand Down Expand Up @@ -790,7 +792,7 @@ void Iteration::endStep()
switch (series.iterationEncoding())
{
case IE::fileBased:
file = &Attributable::get();
file = m_attri.get();
break;
case IE::groupBased:
case IE::variableBased:
Expand Down
10 changes: 5 additions & 5 deletions src/Series.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1072,7 +1072,7 @@ void Series::initSeries(
std::unique_ptr<Series::ParsedInput> input)
{
auto &series = get();
auto &writable = series.m_writable;
auto &writable = series->m_writable;

/*
* In Access modes READ_LINEAR and APPEND, the Series constructor might have
Expand Down Expand Up @@ -2433,7 +2433,7 @@ AdvanceStatus Series::advance(
// If the backend does not support steps, we cannot continue here
param.isThisStepMandatory = true;
}
IOTask task(&file.m_writable, param);
IOTask task(&file->m_writable, param);
IOHandler()->enqueue(task);
}

Expand Down Expand Up @@ -2530,7 +2530,7 @@ AdvanceStatus Series::advance(AdvanceMode mode)
// If the backend does not support steps, we cannot continue here
param.isThisStepMandatory = true;
}
IOTask task(&series.m_writable, param);
IOTask task(&series->m_writable, param);
IOHandler()->enqueue(task);

// We cannot call Series::flush now, since the IO handler is still filled
Expand Down Expand Up @@ -2894,9 +2894,9 @@ namespace internal
// This releases the openPMD hierarchy
iterations.container().clear();
// Release the IO Handler
if (m_writable.IOHandler)
if (operator*().m_writable.IOHandler)
{
*m_writable.IOHandler = std::nullopt;
*operator*().m_writable.IOHandler = std::nullopt;
}
}
} // namespace internal
Expand Down
11 changes: 10 additions & 1 deletion src/backend/Attributable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,16 @@ namespace openPMD
{
namespace internal
{
AttributableData::AttributableData() : m_writable{this}
SharedAttributableData::SharedAttributableData(AttributableData *attr)
: m_writable{attr}
{}

AttributableData::AttributableData()
: SharedData_t(std::make_shared<SharedAttributableData>(this))
{}

AttributableData::AttributableData(SharedAttributableData *raw_ptr)
: SharedData_t({raw_ptr, [](auto const *) {}})
{}
} // namespace internal

Expand Down
5 changes: 3 additions & 2 deletions src/backend/Writable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "openPMD/backend/Writable.hpp"
#include "openPMD/Error.hpp"

#include "openPMD/backend/Attributable.hpp"
#include "openPMD/IO/AbstractIOHandler.hpp"
#include "openPMD/Series.hpp"
#include "openPMD/auxiliary/DerefDynamicCast.hpp"

#include <stdexcept>

namespace openPMD
Expand Down

0 comments on commit a41857c

Please sign in to comment.