diff --git a/Control/AthenaKernel/AthenaKernel/ExtendedEventContext.h b/Control/AthenaKernel/AthenaKernel/ExtendedEventContext.h index c5fc1d5102e3ca807f556f57f7ce56ed299b633f..2ea60e03d4e26430290f4dc91a12138eff364928 100644 --- a/Control/AthenaKernel/AthenaKernel/ExtendedEventContext.h +++ b/Control/AthenaKernel/AthenaKernel/ExtendedEventContext.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ #ifndef ATHENAKERNEL_EXTENDEDEVENTCONTEXT_H @@ -50,10 +50,10 @@ namespace Atlas { /** * @brief Thread-local thinning cache. - * Set when we are doing output with thinning' the cache + * Set when we are doing output with thinning; the cache * provides information about what was thinned. * This is to allow converters to get thinning information. - * Unfortuneately, we don't have a better way of doing this + * Unfortunately, we don't have a better way of doing this * without changing Gaudi interfaces. */ void setThinningCache (const SG::ThinningCache* cache) { m_thinningCache = cache; } diff --git a/Control/AthenaKernel/AthenaKernel/ThinningCache.h b/Control/AthenaKernel/AthenaKernel/ThinningCache.h index 195657a828a104991807537b7add7f77d24ef38f..e577bc110c0e7962478b63f697ac2fadfdcb5b68 100644 --- a/Control/AthenaKernel/AthenaKernel/ThinningCache.h +++ b/Control/AthenaKernel/AthenaKernel/ThinningCache.h @@ -15,7 +15,9 @@ #include "AthenaKernel/ThinningDecisionBase.h" +#include "AthenaKernel/ThinningInfo.h" #include "AthenaKernel/sgkey_t.h" +#include "CxxUtils/ConcurrentBitset.h" #include <unordered_map> #include <string> #include <vector> @@ -29,6 +31,7 @@ namespace SG { class ThinningDecisionBase; +class auxid_set_t; /** @@ -111,19 +114,38 @@ public: void lockOwned(); + /** + * @brief Set vetoed variable information one object. + * @param key SG string key of the object being added. + * @param vetoed Set of vetoed variables for this object. + */ + void setVetoed (const std::string& key, + const CxxUtils::ConcurrentBitset& vetoed); + + + /** + * @brief Return thinning information for @c key. + * @param key SG key for which to return selected variables. + * + * Return thinning information @c key, or nullptr. + */ + const ThinningInfo* thinningInfo (const std::string& key) const; + + /** * @brief Clear the cache. */ void clear(); + private: /// Mapping by string SG key. - typedef std::unordered_map<std::string, const ThinningDecisionBase*> map_t; + typedef std::unordered_map<std::string, ThinningInfo> map_t; map_t m_map; /// Mapping by hashed SG key. - typedef std::unordered_map<sgkey_t, const ThinningDecisionBase*> sgmap_t; + typedef std::unordered_map<sgkey_t, ThinningInfo> sgmap_t; sgmap_t m_sgmap; /// List of decision objects we've copied in order to handle merges. @@ -135,13 +157,13 @@ private: /** * @brief Merge a new thinning request into an existing one via AND. - * @param oldThinningIt Iterator in @c m_map of the existing thinning decision. + * @param info @c ThinningInfo with existing decision. * @param sgkeys SG hashed keys of the object being added. * @param thinning New thinning decision. * * The new thinning decision will be combined with the old one via AND. */ - void merge (map_t::iterator oldThinningIt, + void merge (ThinningInfo& info, const std::vector<sgkey_t>& sgkeys, const ThinningDecisionBase& thinning); }; diff --git a/Control/AthenaKernel/AthenaKernel/ThinningInfo.h b/Control/AthenaKernel/AthenaKernel/ThinningInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..5814f94afd63ed59ab1a96039f25f0cfd54607f7 --- /dev/null +++ b/Control/AthenaKernel/AthenaKernel/ThinningInfo.h @@ -0,0 +1,60 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. +/* + * Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration. + */ +/** + * @file AthenaKernel/ThinningInfo.h + * @author scott snyder <snyder@bnl.gov> + * @date Jul, 2020 + * @brief Hold thinning/slimming information for a given object. + */ + + +#ifndef ATHENAKERNEL_THINNINGINFO_H +#define ATHENAKERNEL_THINNINGINFO_H + + +#include "CxxUtils/ConcurrentBitset.h" + + +namespace SG { + + +class ThinningDecisionBase; + + +/** + * @brief Hold thinning/slimming information for a given object. + * + * Thinning/slimming information for objects in the event store + * can come from several sources. At present, this includes the TrigDecision + * objects recorded in the event store by thinning algorithms + * and the list of suppressed aux variables constructed by AthenaOutputStream. + * + * ThinningCacheTool will assemble them in one place for ease of access + * during output. ThinningCache maps object keys to ThinningInfo objects, + * when then hold the information for single objects. + */ +class ThinningInfo +{ +public: + /// Thinning for the object. + const ThinningDecisionBase* m_decision; + + /// Set of auxids not to be written for this object. + /// (In principle, we should use SG::auxid_set_t here, but there + /// are dependency issues with that.) + CxxUtils::ConcurrentBitset m_vetoed; + + /// Test if a variable has been vetoed. + bool vetoed (size_t id) const + { + return m_vetoed.test (id); + } +}; + + +} // namespace SG + + +#endif // not ATHENAKERNEL_THINNINGINFO_H diff --git a/Control/AthenaKernel/AthenaKernel/getThinningCache.h b/Control/AthenaKernel/AthenaKernel/getThinningCache.h index 4e1740dad8244e44c99078eabed92e766f0266c9..a86ea1d1b726f22a8cbf740e5a559b75199611a2 100644 --- a/Control/AthenaKernel/AthenaKernel/getThinningCache.h +++ b/Control/AthenaKernel/AthenaKernel/getThinningCache.h @@ -1,6 +1,6 @@ // This file's extension implies that it's C, but it's really -*- C++ -*-. /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /** * @file AthenaKernel/getThinningCache.h @@ -21,6 +21,7 @@ class EventContext; namespace SG { class ThinningCache; + class ThinningInfo; class ThinningDecisionBase; @@ -40,6 +41,26 @@ const SG::ThinningCache* getThinningCache (const EventContext& ctx); const SG::ThinningCache* getThinningCache(); +/** + * @brief Retrieve the current thinning information for @c key. + * @brief ctx Event context. + * @param key SG key to test. + * + * Returns nullptr if there is no thinning for @c key. + */ +const SG::ThinningInfo* getThinningInfo (const EventContext& ctx, + const std::string& key); + + +/** + * @brief Retrieve the current thinning information for @c key. + * @param key SG key to test. + * + * Returns nullptr if there is no thinning for @c key. + */ +const SG::ThinningInfo* getThinningInfo (const std::string& key); + + /** * @brief Retrieve the current thinning decision for @c key. * @brief ctx Event context. diff --git a/Control/AthenaKernel/CMakeLists.txt b/Control/AthenaKernel/CMakeLists.txt index 1de3e8819c474ae6b8471bd00f471c27a352fb1e..0c39c9702932da1b0f1f13c9216790ae20486add 100644 --- a/Control/AthenaKernel/CMakeLists.txt +++ b/Control/AthenaKernel/CMakeLists.txt @@ -154,10 +154,14 @@ atlas_add_test( ThinningCache_test SOURCES test/ThinningCache_test.cxx LINK_LIBRARIES AthenaKernel TestTools ) +atlas_add_test( ThinningInfo_test + SOURCES test/ThinningInfo_test.cxx + LINK_LIBRARIES AthenaKernel TestTools ) + atlas_add_test( getThinningCache_test SOURCES test/getThinningCache_test.cxx LINK_LIBRARIES AthenaKernel TestTools ) - atlas_add_test( AlgorithmTimer_test +atlas_add_test( AlgorithmTimer_test SOURCES test/AlgorithmTimer_test.cxx LINK_LIBRARIES AthenaKernel ) diff --git a/Control/AthenaKernel/share/ThinningInfo_test.ref b/Control/AthenaKernel/share/ThinningInfo_test.ref new file mode 100644 index 0000000000000000000000000000000000000000..f81d60e457b2e3a8ce71124f1e81315a240b1f6e --- /dev/null +++ b/Control/AthenaKernel/share/ThinningInfo_test.ref @@ -0,0 +1,2 @@ +AthenaKernel/ThinningInfo_test +test1 diff --git a/Control/AthenaKernel/src/ThinningCache.cxx b/Control/AthenaKernel/src/ThinningCache.cxx index 00ed972c2163398ce0e8e3b4a907be83750c91ae..d417dd5a62e534263681b296bc75381d6eb87050 100644 --- a/Control/AthenaKernel/src/ThinningCache.cxx +++ b/Control/AthenaKernel/src/ThinningCache.cxx @@ -37,7 +37,7 @@ ThinningCache::thinning (const std::string& key) const { auto it = m_map.find (key); if (it != m_map.end()) { - return it->second; + return it->second.m_decision; } return nullptr; } @@ -55,7 +55,7 @@ ThinningCache::thinning (const sgkey_t sgkey) const { auto it = m_sgmap.find (sgkey); if (it != m_sgmap.end()) { - return it->second; + return it->second.m_decision; } return nullptr; } @@ -81,19 +81,26 @@ void ThinningCache::addThinning (const std::string& key, { if (!thinning) return; - auto pos = m_map.try_emplace (key, thinning); - if (!pos.second) { - if (!unique) { - merge (pos.first, sgkeys, *thinning); - return; + { + ThinningInfo& info = m_map[key]; + if (info.m_decision) { + if (!unique) { + merge (info, sgkeys, *thinning); + return; + } + throw std::runtime_error ("Duplicated thinning definition"); + } + else { + info.m_decision = thinning; } - throw std::runtime_error ("Duplicated thinning definition"); } for (sgkey_t sgkey : sgkeys) { - if (!m_sgmap.try_emplace (sgkey, thinning).second) { + ThinningInfo& info = m_sgmap[sgkey]; + if (info.m_decision) { throw std::runtime_error ("Duplicated thinning definition"); } + info.m_decision = thinning; } } @@ -132,6 +139,36 @@ void ThinningCache::lockOwned() } +/** + * @brief Set selected variable information one object. + * @param key SG string key of the object being added. + * @param sgkeys SG hashed keys of the object being added. + * @param vetoed Set of vetoed variables for this object. + */ +void ThinningCache::setVetoed (const std::string& key, + const CxxUtils::ConcurrentBitset& vetoed) +{ + m_map[key].m_vetoed = vetoed; +} + + +/** + * @brief Return thinning information for @c key. + * @param key SG key for which to return selected variables. + * + * Return thinning information @c key, or nullptr. + */ +const ThinningInfo* +ThinningCache::thinningInfo (const std::string& key) const +{ + auto it = m_map.find (key); + if (it != m_map.end()) { + return &it->second; + } + return nullptr; +} + + /** * @brief Clear the cache. */ @@ -146,13 +183,13 @@ void ThinningCache::clear() /** * @brief Merge a new thinning request into an existing one via AND. - * @param oldThinningIt Iterator in @c m_map of the existing thinning decision. + * @param info @c ThinningInfo with existing decision. * @param sgkeys SG hashed keys of the object being added. * @param thinning New thinning decision. * * The new thinning decision will be combined with the old one via AND. */ -void ThinningCache::merge (map_t::iterator oldThinningIt, +void ThinningCache::merge (ThinningInfo& info, const std::vector<sgkey_t>& sgkeys, const ThinningDecisionBase& thinning) { @@ -165,7 +202,7 @@ void ThinningCache::merge (map_t::iterator oldThinningIt, // We expect this to be relatively rare and the number of such objects // to be small, so just use a linear search. auto ownedIt = std::find_if (m_owned.begin(), m_owned.end(), - [old = oldThinningIt->second] + [old = info.m_decision] (const std::unique_ptr<SG::ThinningDecisionBase>& p) { return p.get() == old; }); @@ -175,13 +212,13 @@ void ThinningCache::merge (map_t::iterator oldThinningIt, } else { // We need to make a copy of the existing decision and enter it into the maps. - m_owned.push_back (std::make_unique<SG::ThinningDecisionBase> (oldThinningIt->second->size())); + m_owned.push_back (std::make_unique<SG::ThinningDecisionBase> (info.m_decision->size())); oldThinning = m_owned.back().get(); - oldThinning->thin (*oldThinningIt->second); - oldThinningIt->second = oldThinning; + oldThinning->thin (*info.m_decision); + info.m_decision = oldThinning; for (sgkey_t sgkey : sgkeys) { - m_sgmap[sgkey] = oldThinning; + m_sgmap[sgkey].m_decision = oldThinning; } } diff --git a/Control/AthenaKernel/src/getThinningCache.cxx b/Control/AthenaKernel/src/getThinningCache.cxx index 9563626cd65d432cd6a3a02557cde1f28d22b93f..99b3132c26f440e56690c4330918dba9e0a73b71 100644 --- a/Control/AthenaKernel/src/getThinningCache.cxx +++ b/Control/AthenaKernel/src/getThinningCache.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /** * @file AthenaKernel/src/getThinningCache.h @@ -44,6 +44,35 @@ const SG::ThinningCache* getThinningCache() } +/** + * @brief Retrieve the current thinning information for @c key. + * @brief ctx Event context. + * @param key SG key to test. + * + * Returns nullptr if there is no thinning for @c key. + */ +const SG::ThinningInfo* getThinningInfo (const EventContext& ctx, + const std::string& key) +{ + if (const SG::ThinningCache* cache = getThinningCache (ctx)) { + return cache->thinningInfo (key); + } + return nullptr; +} + + +/** + * @brief Retrieve the current thinning information for @c key. + * @param key SG key to test. + * + * Returns nullptr if there is no thinning for @c key. + */ +const SG::ThinningInfo* getThinningInfo (const std::string& key) +{ + return getThinningInfo (Gaudi::Hive::currentContext(), key); +} + + /** * @brief Retrieve the current thinning decision for @c key. * @brief ctx Event context. diff --git a/Control/AthenaKernel/test/ThinningCache_test.cxx b/Control/AthenaKernel/test/ThinningCache_test.cxx index 42531f72b2b4b68ce1f847ded74a4905b90a1354..39d49ae73c02d79f70bbf6e4ef865c3488a47bbf 100644 --- a/Control/AthenaKernel/test/ThinningCache_test.cxx +++ b/Control/AthenaKernel/test/ThinningCache_test.cxx @@ -108,6 +108,14 @@ void test1() cache.setTrigNavigationThinningSvc (&tt); assert (cache.trigNavigationThinningSvc() == &tt); + assert (cache.thinningInfo ("foo")->m_vetoed.empty()); + CxxUtils::ConcurrentBitset bs (64); + bs.set (13); + cache.setVetoed ("foo", bs); + assert (cache.thinningInfo ("foo")->m_vetoed == bs); + assert (cache.thinningInfo ("foo")->vetoed(13)); + assert (!cache.thinningInfo ("foo")->vetoed(14)); + cache.clear(); assert (cache.empty()); assert (cache.trigNavigationThinningSvc() == nullptr); diff --git a/Control/AthenaKernel/test/ThinningInfo_test.cxx b/Control/AthenaKernel/test/ThinningInfo_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4dfc0fbe51bb1e46b8e8f2ab389fbe294cae5ec4 --- /dev/null +++ b/Control/AthenaKernel/test/ThinningInfo_test.cxx @@ -0,0 +1,30 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ +/** + * @file AthenaKernel/test/ThinningInfo_test.cxx + * @author scott snyder <snyder@bnl.gov> + * @date Jul, 2020 + * @brief Regression tests for ThinningInfo. + */ + +#undef NDEBUG + +#include "AthenaKernel/ThinningInfo.h" +#include <cassert> +#include <iostream> +#include <stdexcept> + + +void test1() +{ + std::cout << "test1\n"; +} + + +int main() +{ + std::cout << "AthenaKernel/ThinningInfo_test\n"; + test1(); + return 0; +} diff --git a/Control/AthenaKernel/test/getThinningCache_test.cxx b/Control/AthenaKernel/test/getThinningCache_test.cxx index 0f9b630fbe3de9ddf2c754df80d9f348a61c832a..3caee6fd94f41923eaedebc0797a8f7be3681b0f 100644 --- a/Control/AthenaKernel/test/getThinningCache_test.cxx +++ b/Control/AthenaKernel/test/getThinningCache_test.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /** * @file AthenaKernel/test/getThinningCache_test.cxx @@ -29,6 +29,8 @@ void test1() assert (SG::getThinningCache() == nullptr); assert (SG::getThinningCache(ctx) == nullptr); + assert (SG::getThinningInfo("foo") == nullptr); + assert (SG::getThinningInfo(ctx, "foo") == nullptr); assert (SG::getThinningDecision("foo") == nullptr); assert (SG::getThinningDecision(ctx, "foo") == nullptr); assert (SG::getThinningDecision(101) == nullptr); @@ -42,6 +44,8 @@ void test1() ctx.getExtension<Atlas::ExtendedEventContext>().setThinningCache (&cache); assert (SG::getThinningCache() == nullptr); assert (SG::getThinningCache(ctx) == &cache); + assert (SG::getThinningInfo("foo") == nullptr); + assert (SG::getThinningInfo(ctx, "foo") == nullptr); assert (SG::getThinningDecision("foo") == nullptr); assert (SG::getThinningDecision(ctx, "foo") == nullptr); assert (SG::getThinningDecision(101) == nullptr); @@ -52,6 +56,8 @@ void test1() assert (SG::getThinningCache() == nullptr); assert (SG::getThinningCache(ctx) == &cache); + assert (SG::getThinningInfo("foo") == nullptr); + assert (SG::getThinningInfo(ctx, "foo")->m_decision == &dec); assert (SG::getThinningDecision("foo") == nullptr); assert (SG::getThinningDecision(ctx, "foo") == &dec); assert (SG::getThinningDecision(101) == nullptr); @@ -61,6 +67,8 @@ void test1() assert (SG::getThinningCache() == &cache); assert (SG::getThinningCache(ctx) == &cache); + assert (SG::getThinningInfo("foo")->m_decision == &dec); + assert (SG::getThinningInfo(ctx, "foo")->m_decision == &dec); assert (SG::getThinningDecision("foo") == &dec); assert (SG::getThinningDecision(ctx, "foo") == &dec); assert (SG::getThinningDecision(101) == &dec);