diff --git a/src/libraries/JANA/Components/JStorage.h b/src/libraries/JANA/Components/JStorage.h index 08b366995..1b812ddc0 100644 --- a/src/libraries/JANA/Components/JStorage.h +++ b/src/libraries/JANA/Components/JStorage.h @@ -12,7 +12,6 @@ #include #include #include -#include class JFactory; @@ -26,10 +25,10 @@ class JStorage { // Fields Status m_status = Status::Empty; std::string m_collection_name; - std::optional m_collection_tag = std::nullopt; + JOptional m_collection_tag; std::string m_type_name; JFactory* m_factory = nullptr; - std::optional m_inner_type_index = std::nullopt; // e.g. Hit, Cluster + JOptional m_inner_type_index; mutable JCallGraphRecorder::JDataOrigin m_insert_origin = JCallGraphRecorder::ORIGIN_NOT_AVAILABLE; protected: @@ -45,9 +44,9 @@ class JStorage { // Getters Status GetStatus() const { return m_status; } std::string GetCollectionName() const { return m_collection_name; } - std::optional GetCollectionTag() const { return m_collection_tag; } + JOptional GetCollectionTag() const { return m_collection_tag; } std::string GetTypeName() const { return m_type_name; } - std::optional GetTypeIndex() const { return m_inner_type_index; } + JOptional GetTypeIndex() const { return m_inner_type_index; } JCallGraphRecorder::JDataOrigin GetInsertOrigin() const { return m_insert_origin; } ///< If objects were placed here by JEvent::Insert() this records whether that call was made from a source or factory. JFactory* GetFactory() const { return m_factory; } diff --git a/src/libraries/JANA/JFactory.h b/src/libraries/JANA/JFactory.h index 3369c925d..7db60f2a2 100644 --- a/src/libraries/JANA/JFactory.h +++ b/src/libraries/JANA/JFactory.h @@ -17,7 +17,6 @@ #include #include #include -#include class JEvent; @@ -165,7 +164,7 @@ class JFactory : public jana::components::JComponent, virtual void Process(const std::shared_ptr&) {} virtual void Finish() {} - virtual std::optional GetObjectType() const { return std::nullopt; } + virtual std::type_index GetObjectType() const { throw JException("GetObjectType not supported for non-JFactoryT's"); } virtual std::size_t GetNumObjects() const { throw JException("Not implemented!"); diff --git a/src/libraries/JANA/JFactorySet.cc b/src/libraries/JANA/JFactorySet.cc index 7ff1dfbd2..ccf99d6f7 100644 --- a/src/libraries/JANA/JFactorySet.cc +++ b/src/libraries/JANA/JFactorySet.cc @@ -105,11 +105,11 @@ bool JFactorySet::Add(JFactory* aFactory) mAllFactories.push_back(aFactory); - auto object_type = aFactory->GetObjectType(); - if (object_type != std::nullopt) { + + if (aFactory->GetOutputs().empty()) { // We have an old-style JFactory! - auto typed_key = std::make_pair( *object_type, aFactory->GetTag() ); + auto typed_key = std::make_pair( aFactory->GetObjectType(), aFactory->GetTag() ); auto untyped_key = std::make_pair( aFactory->GetObjectName(), aFactory->GetTag() ); auto typed_result = mFactories.find(typed_key); @@ -291,10 +291,13 @@ void JFactorySet::Print() const /// Release() loops over all contained factories, clearing their data void JFactorySet::Release() { - - for (const auto& sFactoryPair : mFactories) { - auto sFactory = sFactoryPair.second; - sFactory->ClearData(); + for (auto* fac : mAllFactories) { + fac->ClearData(); + } + for (auto& it : mCollectionsFromName) { + if (it.second->GetFactory() == nullptr) { + it.second->ClearData(); + } } } diff --git a/src/libraries/JANA/JFactoryT.h b/src/libraries/JANA/JFactoryT.h index 456a63200..46fbccb33 100644 --- a/src/libraries/JANA/JFactoryT.h +++ b/src/libraries/JANA/JFactoryT.h @@ -66,7 +66,7 @@ class JFactoryT : public JFactory { void Process(const std::shared_ptr&) override {} - std::optional GetObjectType(void) const override { + std::type_index GetObjectType(void) const override { return std::type_index(typeid(T)); } diff --git a/src/libraries/JANA/Utils/JAny.h b/src/libraries/JANA/Utils/JAny.h index ad244afaf..68e343af1 100644 --- a/src/libraries/JANA/Utils/JAny.h +++ b/src/libraries/JANA/Utils/JAny.h @@ -3,6 +3,9 @@ // Subject to the terms in the LICENSE file found in the top-level directory. #pragma once +#include +#include +#include /// Ideally we'd just use std::any, but we are restricted to C++14 for the time being struct JAny { @@ -17,3 +20,68 @@ struct JAnyT : JAny { ~JAnyT() override = default; // deletes the t }; + +template +class JOptional { +private: + using StorageT = typename std::aligned_storage::type; + bool has_value; + StorageT storage; + +public: + JOptional() : has_value(false) {} + + JOptional(const T& val) : has_value(true) { + new (&storage) T(val); + } + + JOptional(T&& val) : has_value(true) { + new (&storage) T(std::move(val)); + } + + ~JOptional() { + reset(); + } + + // Checks if there is a value + bool hasValue() const { return has_value; } + + // Accesses the value, throws if not present + T& get() { + if (!has_value) { + throw std::runtime_error("No value present"); + } + return *reinterpret_cast(&storage); // Access without launder (C++14) + } + + const T& get() const { + if (!has_value) { + throw std::runtime_error("No value present"); + } + return *reinterpret_cast(&storage); // Access without launder (C++14) + } + + // Resets the optional (removes the value) + void reset() { + if (has_value) { + reinterpret_cast(&storage)->~T(); // Explicitly call destructor + has_value = false; + } + } + + // Set the value + void set(const T& val) { + reset(); + new (&storage) T(val); // Placement new + has_value = true; + } + + // Set using move semantics + void set(T&& val) { + reset(); + new (&storage) T(std::move(val)); // Placement new + has_value = true; + } +}; + +