Skip to content

Commit

Permalink
fixup! vectors are supported in Mergers
Browse files Browse the repository at this point in the history
  • Loading branch information
Michal Tichák committed Jan 26, 2024
1 parent 38d5037 commit 1ee7595
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 26 deletions.
29 changes: 19 additions & 10 deletions Utilities/Mergers/include/Mergers/ObjectStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,47 @@
#include <variant>
#include <memory>
#include <vector>
#include <Framework/DataRef.h>
#include <Framework/DataAllocator.h>
#include <Headers/DataHeader.h>

class TObject;

namespace o2::mergers
namespace o2
{

namespace framework
{
struct DataRef;
struct DataAllocator;
} // namespace framework

namespace mergers
{

class MergeInterface;

using TObjectPtr = std::shared_ptr<TObject>;
using VectorOfTObject = std::vector<TObject*>;
using VectorOfTObjectPtr = std::vector<TObjectPtr>;
using VectorOfRawTObjects = std::vector<TObject*>;
using VectorOfTObjectPtrs = std::vector<TObjectPtr>;
using MergeInterfacePtr = std::shared_ptr<MergeInterface>;
using ObjectStore = std::variant<std::monostate, TObjectPtr, VectorOfTObjectPtr, MergeInterfacePtr>;
using ObjectStore = std::variant<std::monostate, TObjectPtr, VectorOfTObjectPtrs, MergeInterfacePtr>;

namespace object_store_helpers
{

/// \brief Takes a DataRef, deserializes it (if type is supported) and puts into an ObjectStore
ObjectStore extractObjectFrom(const framework::DataRef& ref);

/// \brief Helper function that converts vector of smart pointers to the vector of raw pointers that is serializable
/// Destroy original vector after destroying vector with raw pointers to avoid undefined behavior
VectorOfTObject toRawPointers(const VectorOfTObjectPtr&);
/// \brief Helper function that converts vector of smart pointers to the vector of raw pointers that is serializable.
/// Make sure that original vector lives longer than the observer vector to avoid undefined behavior.
VectorOfRawTObjects toRawPointers(const VectorOfTObjectPtrs&);

/// \brief Used in FullHistorMerger's and IntegratingMerger's publish function. Checks mergedObject for every state that is NOT monostate
/// and creates snapshot if underlying object to the framework
bool snapshot(framework::DataAllocator& allocator, const header::DataHeader::SubSpecificationType subSpec, const ObjectStore& mergedObject);

} // namespace object_store_helpers

} // namespace o2::mergers
} // namespace mergers
} // namespace o2

#endif // O2_OBJECTSTORE_H
21 changes: 10 additions & 11 deletions Utilities/Mergers/src/ObjectStore.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ static std::string concat(Args&&... arguments)
return std::move(ss.str());
}

template <typename TypeToRead>
void* readObject(TypeToRead&& type, o2::framework::FairTMessage& ftm)
void* readObject(const TClass* type, o2::framework::FairTMessage& ftm)
{
using namespace std::string_view_literals;
auto* object = ftm.ReadObjectAny(type);
Expand All @@ -61,14 +60,14 @@ MergeInterface* castToMergeInterface(bool inheritsFromTObject, void* object, TCl
return objectAsMergeInterface;
}

std::optional<ObjectStore> extractVector(o2::framework::FairTMessage& ftm, TClass* storedClass)
std::optional<ObjectStore> extractVector(o2::framework::FairTMessage& ftm, const TClass* storedClass)
{
if (!storedClass->InheritsFrom(TClass::GetClass(typeid(VectorOfTObject)))) {
if (!storedClass->InheritsFrom(TClass::GetClass(typeid(VectorOfRawTObjects)))) {
return std::nullopt;
}

auto* object = readObject(storedClass, ftm);
auto* extractedVector = static_cast<VectorOfTObject*>(object);
auto* extractedVector = static_cast<VectorOfRawTObjects*>(object);
auto result = std::vector<TObjectPtr>{};
result.reserve(extractedVector->size());
std::transform(extractedVector->begin(), extractedVector->end(), std::back_inserter(result), [](const auto& rawTObject) { return TObjectPtr(rawTObject, algorithm::deleteTCollections); });
Expand Down Expand Up @@ -118,10 +117,10 @@ ObjectStore extractObjectFrom(const framework::DataRef& ref)
}
}

VectorOfTObject toRawPointers(const VectorOfTObjectPtr& vector)
VectorOfRawTObjects toRawPointers(const VectorOfTObjectPtrs& vector)
{
// NOTE: MT - it might be worth it to create custom stack allocators for this case
VectorOfTObject result{};
VectorOfRawTObjects result{};
result.reserve(vector.size());
std::transform(vector.begin(), vector.end(), std::back_inserter(result), [](const auto& ptr) { return ptr.get(); });
return result;
Expand All @@ -142,15 +141,15 @@ struct snapshoter {
};

template <>
struct snapshoter<VectorOfTObjectPtr> {
struct snapshoter<VectorOfTObjectPtrs> {
static bool snapshot(framework::DataAllocator& allocator, const header::DataHeader::SubSpecificationType subSpec, const ObjectStore& object)
{
if (!std::holds_alternative<VectorOfTObjectPtr>(object)) {
if (!std::holds_alternative<VectorOfTObjectPtrs>(object)) {
return false;
}

// NOTE: it might be worth it to create custom stack allocators
const auto& mergedVector = std::get<VectorOfTObjectPtr>(object);
const auto& mergedVector = std::get<VectorOfTObjectPtrs>(object);
const auto vectorToSnapshot = object_store_helpers::toRawPointers(mergedVector);

allocator.snapshot(framework::OutputRef{MergerBuilder::mergerIntegralOutputBinding(), subSpec}, vectorToSnapshot);
Expand All @@ -163,7 +162,7 @@ bool snapshot(framework::DataAllocator& allocator, const header::DataHeader::Sub
{
return snapshoter<MergeInterfacePtr>::snapshot(allocator, subSpec, mergedObject) ||
snapshoter<TObjectPtr>::snapshot(allocator, subSpec, mergedObject) ||
snapshoter<VectorOfTObjectPtr>::snapshot(allocator, subSpec, mergedObject);
snapshoter<VectorOfTObjectPtrs>::snapshot(allocator, subSpec, mergedObject);
}

} // namespace object_store_helpers
Expand Down
9 changes: 4 additions & 5 deletions Utilities/Mergers/test/test_ObjectStore.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// or submit itself to any jurisdiction.

#include <TH1.h>
#include <gsl/span>
#define BOOST_TEST_MODULE Test Utilities MergerObjectStore
#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK
Expand All @@ -20,7 +21,6 @@
#include "Headers/DataHeader.h"
#include "Framework/DataRef.h"

#include <TH1I.h>
#include <TMessage.h>
#include <boost/test/unit_test.hpp>

Expand All @@ -33,7 +33,6 @@ using namespace o2::mergers;
BOOST_AUTO_TEST_SUITE(TestObjectExtraction)

template <typename TypeToDataRef>

DataRef makeDataRef(TypeToDataRef* obj)
{
DataRef ref;
Expand Down Expand Up @@ -127,14 +126,14 @@ BOOST_AUTO_TEST_CASE(VectorOfHistos1D)
{
auto histo = std::make_shared<TH1F>("histo 1d", "histo 1d", 100, 0, 100);
histo->Fill(5);
VectorOfTObjectPtr vectorWithData{histo};
VectorOfTObjectPtrs vectorWithData{histo};

auto vectorToDataRef = object_store_helpers::toRawPointers(vectorWithData);

DataRef ref = makeDataRef(&vectorToDataRef);
auto objStore = object_store_helpers::extractObjectFrom(ref);
BOOST_CHECK(std::holds_alternative<VectorOfTObjectPtr>(objStore));
auto extractedVector = std::get<VectorOfTObjectPtr>(objStore);
BOOST_CHECK(std::holds_alternative<VectorOfTObjectPtrs>(objStore));
auto extractedVector = std::get<VectorOfTObjectPtrs>(objStore);
BOOST_CHECK(extractedVector.size() == 1);
auto* extractedHisto = dynamic_cast<TH1F*>(extractedVector[0].get());
BOOST_CHECK(gsl::span(histo->GetArray(), histo->GetSize()) == gsl::span(extractedHisto->GetArray(), extractedHisto->GetSize()));
Expand Down

0 comments on commit 1ee7595

Please sign in to comment.