From 3f91a8c4a692322c307e32df1a0aaf0d8f402493 Mon Sep 17 00:00:00 2001 From: Manuel Huber Date: Sun, 26 Jan 2025 13:04:08 +0100 Subject: [PATCH] add one more check --- include/RMGAnalysisReader.hh | 32 +++++++++++++++++++++----------- src/RMGAnalysisReader.cc | 13 ++++++++++--- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/include/RMGAnalysisReader.hh b/include/RMGAnalysisReader.hh index a50d380..8e0525e 100644 --- a/include/RMGAnalysisReader.hh +++ b/include/RMGAnalysisReader.hh @@ -43,7 +43,8 @@ class RMGAnalysisReader final { public: /** - * @brief thread-safe access handle to the underlying reader. */ + * @brief thread-safe access handle to the underlying reader. This handle can be used to set-up + * ntuple reading (in setup mode) or to read rows from the ntuple. */ class Access final { friend class RMGAnalysisReader; @@ -67,11 +68,15 @@ class RMGAnalysisReader final { /** * @brief wraps @ref G4VAnalysisReader::GetNtupleRow. */ - [[nodiscard]] auto GetNtupleRow() { return fReader->GetNtupleRow(fNtupleId); } + [[nodiscard]] auto GetNtupleRow() { + AssertSetup(false); + return fReader->GetNtupleRow(fNtupleId); + } /** * @brief wraps @ref G4VAnalysisReader::SetNtupleDColumn. */ auto SetNtupleDColumn(const std::string& name, G4double& value, const std::vector& allowed_units = {}) { + AssertSetup(true); AssertUnit(name, allowed_units); return fReader->SetNtupleDColumn(fNtupleId, name, value); } @@ -79,6 +84,7 @@ class RMGAnalysisReader final { * @brief wraps @ref G4VAnalysisReader::SetNtupleFColumn. */ auto SetNtupleFColumn(const std::string& name, G4float& value, const std::vector& allowed_units = {}) { + AssertSetup(true); AssertUnit(name, allowed_units); return fReader->SetNtupleFColumn(fNtupleId, name, value); } @@ -86,6 +92,7 @@ class RMGAnalysisReader final { * @brief wraps @ref G4VAnalysisReader::SetNtupleIColumn. */ auto SetNtupleIColumn(const std::string& name, G4int& value, const std::vector& allowed_units = {}) { + AssertSetup(true); AssertUnit(name, allowed_units); return fReader->SetNtupleIColumn(fNtupleId, name, value); } @@ -103,16 +110,18 @@ class RMGAnalysisReader final { // only allow creation or moving in parent. inline Access(G4AutoLock lock, G4VAnalysisReader* reader, int nt, - const std::map* u) - : fLock(std::move(lock)), fReader(reader), fNtupleId(nt), fUnits(u) {}; + const std::map* u, bool setup) + : fLock(std::move(lock)), fReader(reader), fNtupleId(nt), fUnits(u), fCanSetup(setup) {}; Access(Access&&) = default; void AssertUnit(const std::string& name, const std::vector& allowed_units) const; + void AssertSetup(bool setup) const; G4VAnalysisReader* fReader = nullptr; int fNtupleId = -1; const std::map* fUnits; G4AutoLock fLock; + bool fCanSetup = false; }; RMGAnalysisReader() = default; @@ -124,10 +133,11 @@ class RMGAnalysisReader final { RMGAnalysisReader& operator=(RMGAnalysisReader&&) = delete; /** - * @brief open an input file for reading of one specific ntuple. + * @brief open an input file for reading of one specific ntuple. The return access handle can be + * used to connect to-be-read column to variables. * * @details This function can only be used on the master thread. This operation acquires a - * global lock to avoid problems. + * global lock across all readers that will be held until the access handle is discarded. * * @param file_name the input file name. the file format is determined from the file extension. * @param ntuple_dir_name the first part of the input table name. For the table addressed by @@ -146,17 +156,17 @@ class RMGAnalysisReader final { std::string ntuple_name, std::string force_ext = ""); /** - * @brief if any file is open for reading, close the reader. + * @brief if any file is open for reading, close the reader. Also clean-up temporary files. * - * @details this invalidates all readers obtained via @ref RMGAnalysisReader::GetLockedReader. - * This function can only be used on the master thread. This operation acquires a global lock to - * avoid problems. */ + * @details This function can only be used on the master thread. This operation acquires a global + * across all readers. This function will not actually free resources allocated for the reader by Geant4. */ void CloseFile(); /** * @brief get an access handle to the current underlying G4VAnalysisReader. * - * @details this acquires a global lock to avoid problems. The lock is held until the access handle is discarded. */ + * @details The return access handle can be used to read row(s) from the ntuple. This function + * acquires a global across all readers that will be held until the access handle is discarded. */ [[nodiscard]] Access GetLockedReader() const; /** diff --git a/src/RMGAnalysisReader.cc b/src/RMGAnalysisReader.cc index 78f8f93..b73f989 100644 --- a/src/RMGAnalysisReader.cc +++ b/src/RMGAnalysisReader.cc @@ -66,7 +66,8 @@ RMGAnalysisReader::Access RMGAnalysisReader::OpenFile(const std::string& file_na // create an invalid lock to return on error. G4AutoLock invalid_lock(&fMutex, std::defer_lock); invalid_lock.release(); - auto invalid_access = RMGAnalysisReader::Access(std::move(invalid_lock), nullptr, -1, nullptr); + auto invalid_access = + RMGAnalysisReader::Access(std::move(invalid_lock), nullptr, -1, nullptr, false); if (fReader) return std::move(invalid_access); @@ -135,7 +136,7 @@ RMGAnalysisReader::Access RMGAnalysisReader::OpenFile(const std::string& file_na return std::move(invalid_access); } fUnits = units_map[ntuple_name]; - return {std::move(lock), fReader, fNtupleId, fHasUnits ? &fUnits : nullptr}; + return {std::move(lock), fReader, fNtupleId, fHasUnits ? &fUnits : nullptr, true}; } void RMGAnalysisReader::CloseFile() { @@ -166,7 +167,7 @@ RMGAnalysisReader::Access RMGAnalysisReader::GetLockedReader() const { G4AutoLock lock(&fMutex); - return {std::move(lock), fReader, fNtupleId, fHasUnits ? &fUnits : nullptr}; + return {std::move(lock), fReader, fNtupleId, fHasUnits ? &fUnits : nullptr, false}; } G4AutoLock RMGAnalysisReader::GetLock() const { @@ -196,3 +197,9 @@ void RMGAnalysisReader::Access::AssertUnit(const std::string& name, RMGLog::Out(RMGLog::fatal, "invalid unit '", GetUnit(name), "' for column ", name); } } + +void RMGAnalysisReader::Access::AssertSetup(bool setup) const { + if (setup != fCanSetup) { + RMGLog::Out(RMGLog::fatal, "invalid operation in mode fCanSetup=", fCanSetup); + } +}