Skip to content

Commit ba895a5

Browse files
Snapshots API: Inherit from Attributable (#1765)
* Inherit Snapshots from Attributable * Add testing
1 parent 19d921f commit ba895a5

File tree

7 files changed

+46
-9
lines changed

7 files changed

+46
-9
lines changed

include/openPMD/backend/Attributable.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ namespace internal
117117
AttributableData &operator=(AttributableData const &) = delete;
118118
AttributableData &operator=(AttributableData &&) = delete;
119119

120+
// Make copies explicit, only to be used under the conditions described
121+
// above
122+
void cloneFrom(AttributableData const &other);
123+
120124
template <typename T>
121125
T asInternalCopyOf()
122126
{
@@ -209,6 +213,7 @@ class Attributable
209213
friend T &internal::makeOwning(T &self, Series);
210214
friend class StatefulSnapshotsContainer;
211215
friend class internal::AttributableData;
216+
friend class Snapshots;
212217

213218
protected:
214219
// tag for internal constructor

include/openPMD/snapshots/Snapshots.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#pragma once
2222

2323
#include "openPMD/Iteration.hpp"
24+
#include "openPMD/backend/Attributable.hpp"
2425
#include "openPMD/snapshots/ContainerTraits.hpp"
2526
#include <functional>
2627
#include <memory>
@@ -46,14 +47,16 @@ namespace openPMD
4647
* an Iteration handle goes invalid after closing it, a new Iteration handle is
4748
* acquired by Snapshots::operator[]().
4849
*/
49-
class Snapshots
50+
class Snapshots : public Attributable
5051
{
5152
private:
5253
friend class Series;
5354

5455
std::shared_ptr<AbstractSnapshotsContainer> m_snapshots;
5556

56-
Snapshots(std::shared_ptr<AbstractSnapshotsContainer> snapshots);
57+
Snapshots(
58+
std::shared_ptr<AbstractSnapshotsContainer> snapshots,
59+
Attributable &iterations);
5760

5861
inline auto get() const -> AbstractSnapshotsContainer const &;
5962
inline auto get() -> AbstractSnapshotsContainer &;

src/Series.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3314,7 +3314,8 @@ Series::snapshots(std::optional<SnapshotWorkflow> const snapshot_workflow)
33143314
case SnapshotWorkflow::RandomAccess: {
33153315
return Snapshots(
33163316
std::shared_ptr<RandomAccessIteratorContainer>{
3317-
new RandomAccessIteratorContainer(series.iterations)});
3317+
new RandomAccessIteratorContainer(series.iterations)},
3318+
series.iterations);
33183319
}
33193320
case SnapshotWorkflow::Synchronous: {
33203321
std::function<StatefulIterator *()> begin;
@@ -3329,7 +3330,8 @@ Series::snapshots(std::optional<SnapshotWorkflow> const snapshot_workflow)
33293330
}
33303331
return Snapshots(
33313332
std::shared_ptr<StatefulSnapshotsContainer>(
3332-
new StatefulSnapshotsContainer(std::move(begin))));
3333+
new StatefulSnapshotsContainer(std::move(begin))),
3334+
series.iterations);
33333335
}
33343336
}
33353337
throw std::runtime_error("unreachable!");

src/backend/Attributable.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ namespace internal
5050
AttributableData::AttributableData(SharedAttributableData *raw_ptr)
5151
: SharedData_t({raw_ptr, [](auto const *) {}})
5252
{}
53+
54+
void AttributableData::cloneFrom(AttributableData const &other)
55+
{
56+
using parent_t = std::shared_ptr<SharedAttributableData>;
57+
static_cast<parent_t &>(*this) = static_cast<parent_t const &>(other);
58+
}
59+
5360
} // namespace internal
5461

5562
Attributable::Attributable()

src/binding/python/Series.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "openPMD/Iteration.hpp"
2525
#include "openPMD/IterationEncoding.hpp"
2626
#include "openPMD/auxiliary/JSON.hpp"
27+
#include "openPMD/backend/Attributable.hpp"
2728
#include "openPMD/binding/python/Common.hpp"
2829
#include "openPMD/binding/python/Pickle.hpp"
2930
#include "openPMD/binding/python/auxiliary.hpp"
@@ -261,7 +262,7 @@ void init_Series(py::module &m)
261262
py::class_<IndexedIteration, Iteration>(m, "IndexedIteration")
262263
.def_readonly("iteration_index", &IndexedIteration::iterationIndex);
263264

264-
py::class_<WriteIterations>(m, "WriteIterations", R"END(
265+
py::class_<WriteIterations, Attributable>(m, "WriteIterations", R"END(
265266
Writing side of the streaming API.
266267
267268
Create instance via Series.writeIterations().

src/snapshots/Snapshots.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
#include "openPMD/snapshots/Snapshots.hpp"
2+
#include "openPMD/backend/Attributable.hpp"
23
namespace openPMD
34
{
4-
Snapshots::Snapshots(std::shared_ptr<AbstractSnapshotsContainer> snapshots)
5-
: m_snapshots(std::move(snapshots))
6-
{}
5+
Snapshots::Snapshots(
6+
std::shared_ptr<AbstractSnapshotsContainer> snapshots,
7+
Attributable &iterations)
8+
: Attributable(Attributable::NoInit()), m_snapshots(std::move(snapshots))
9+
{
10+
// Check the documentation of internal::AttributableData, we don't copy
11+
// the first-level pointer, only the second level
12+
// This avoids introducing depencencies between series.iterations and
13+
// series.snapshots()
14+
auto attributable_data = std::make_shared<internal::AttributableData>();
15+
attributable_data->cloneFrom(*iterations.m_attri);
16+
Attributable::setData(std::move(attributable_data));
17+
}
718
inline auto Snapshots::get() const -> AbstractSnapshotsContainer const &
819
{
920
return *m_snapshots;

test/CoreTest.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ TEST_CASE("myPath", "[core]")
190190
{
191191
#if openPMD_USE_INVASIVE_TESTS
192192
using vec_t = std::vector<std::string>;
193-
auto pathOf = [](Attributable &attr) {
193+
auto pathOf = [](Attributable const &attr) {
194194
auto res = attr.myPath();
195195
#if false
196196
std::cout << "Directory:\t" << res.directory << "\nSeries name:\t"
@@ -206,6 +206,8 @@ TEST_CASE("myPath", "[core]")
206206

207207
Series series("../samples/myPath.json", Access::CREATE);
208208
REQUIRE(pathOf(series) == vec_t{});
209+
REQUIRE(pathOf(series.iterations) == vec_t{"data"});
210+
REQUIRE(pathOf(series.snapshots()) == vec_t{"data"});
209211
auto iteration = series.iterations[1234];
210212
REQUIRE(pathOf(iteration) == vec_t{"data", "1234"});
211213

@@ -378,6 +380,12 @@ TEST_CASE("output_modification_test", "[core]")
378380
o.setName("MyOutput");
379381
REQUIRE(o.name() == "MyOutput");
380382

383+
o.snapshots().setAttribute("test", "value");
384+
REQUIRE(o.iterations.getAttribute("test").get<std::string>() == "value");
385+
386+
o.iterations.setAttribute<int>("test2", 2);
387+
REQUIRE(o.snapshots().getAttribute("test2").get<int>() == 2);
388+
381389
o.iterations[0];
382390
}
383391

0 commit comments

Comments
 (0)