diff --git a/Utilities/Mergers/include/Mergers/ObjectStore.h b/Utilities/Mergers/include/Mergers/ObjectStore.h index 9ca357810481e..949581f96018a 100644 --- a/Utilities/Mergers/include/Mergers/ObjectStore.h +++ b/Utilities/Mergers/include/Mergers/ObjectStore.h @@ -20,21 +20,29 @@ #include #include #include -#include -#include +#include class TObject; -namespace o2::mergers +namespace o2 +{ + +namespace framework +{ +struct DataRef; +struct DataAllocator; +} // namespace framework + +namespace mergers { class MergeInterface; using TObjectPtr = std::shared_ptr; -using VectorOfTObject = std::vector; -using VectorOfTObjectPtr = std::vector; +using VectorOfRawTObjects = std::vector; +using VectorOfTObjectPtrs = std::vector; using MergeInterfacePtr = std::shared_ptr; -using ObjectStore = std::variant; +using ObjectStore = std::variant; namespace object_store_helpers { @@ -42,9 +50,9 @@ 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 @@ -52,6 +60,7 @@ bool snapshot(framework::DataAllocator& allocator, const header::DataHeader::Sub } // namespace object_store_helpers -} // namespace o2::mergers +} // namespace mergers +} // namespace o2 #endif // O2_OBJECTSTORE_H diff --git a/Utilities/Mergers/src/ObjectStore.cxx b/Utilities/Mergers/src/ObjectStore.cxx index ba1d01a21c01d..b2c7064cd8f0e 100644 --- a/Utilities/Mergers/src/ObjectStore.cxx +++ b/Utilities/Mergers/src/ObjectStore.cxx @@ -38,8 +38,7 @@ static std::string concat(Args&&... arguments) return std::move(ss.str()); } -template -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); @@ -61,14 +60,14 @@ MergeInterface* castToMergeInterface(bool inheritsFromTObject, void* object, TCl return objectAsMergeInterface; } -std::optional extractVector(o2::framework::FairTMessage& ftm, TClass* storedClass) +std::optional 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(object); + auto* extractedVector = static_cast(object); auto result = std::vector{}; result.reserve(extractedVector->size()); std::transform(extractedVector->begin(), extractedVector->end(), std::back_inserter(result), [](const auto& rawTObject) { return TObjectPtr(rawTObject, algorithm::deleteTCollections); }); @@ -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; @@ -142,15 +141,15 @@ struct snapshoter { }; template <> -struct snapshoter { +struct snapshoter { static bool snapshot(framework::DataAllocator& allocator, const header::DataHeader::SubSpecificationType subSpec, const ObjectStore& object) { - if (!std::holds_alternative(object)) { + if (!std::holds_alternative(object)) { return false; } // NOTE: it might be worth it to create custom stack allocators - const auto& mergedVector = std::get(object); + const auto& mergedVector = std::get(object); const auto vectorToSnapshot = object_store_helpers::toRawPointers(mergedVector); allocator.snapshot(framework::OutputRef{MergerBuilder::mergerIntegralOutputBinding(), subSpec}, vectorToSnapshot); @@ -163,7 +162,7 @@ bool snapshot(framework::DataAllocator& allocator, const header::DataHeader::Sub { return snapshoter::snapshot(allocator, subSpec, mergedObject) || snapshoter::snapshot(allocator, subSpec, mergedObject) || - snapshoter::snapshot(allocator, subSpec, mergedObject); + snapshoter::snapshot(allocator, subSpec, mergedObject); } } // namespace object_store_helpers diff --git a/Utilities/Mergers/test/test_ObjectStore.cxx b/Utilities/Mergers/test/test_ObjectStore.cxx index ff1bc22741533..320c90f2e81a5 100644 --- a/Utilities/Mergers/test/test_ObjectStore.cxx +++ b/Utilities/Mergers/test/test_ObjectStore.cxx @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. #include +#include #define BOOST_TEST_MODULE Test Utilities MergerObjectStore #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK @@ -20,7 +21,6 @@ #include "Headers/DataHeader.h" #include "Framework/DataRef.h" -#include #include #include @@ -33,7 +33,6 @@ using namespace o2::mergers; BOOST_AUTO_TEST_SUITE(TestObjectExtraction) template - DataRef makeDataRef(TypeToDataRef* obj) { DataRef ref; @@ -127,14 +126,14 @@ BOOST_AUTO_TEST_CASE(VectorOfHistos1D) { auto histo = std::make_shared("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(objStore)); - auto extractedVector = std::get(objStore); + BOOST_CHECK(std::holds_alternative(objStore)); + auto extractedVector = std::get(objStore); BOOST_CHECK(extractedVector.size() == 1); auto* extractedHisto = dynamic_cast(extractedVector[0].get()); BOOST_CHECK(gsl::span(histo->GetArray(), histo->GetSize()) == gsl::span(extractedHisto->GetArray(), extractedHisto->GetSize()));