Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-05-11 03:34:13

0001 #ifndef FWCore_Framework_EventSetupRecordImpl_h
0002 #define FWCore_Framework_EventSetupRecordImpl_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     Framework
0006 // Class  :     EventSetupRecordImpl
0007 //
0008 /**\class edm::eventsetup::EventSetupRecordImpl
0009 
0010  Description: Base class for all Records in an EventSetup.  Holds data with the same lifetime.
0011 
0012  Usage:
0013 This class contains the Proxies that make up a given Record.  It
0014 is designed to be reused time after time, rather than it being
0015 destroyed and a new one created every time a new Record is
0016 required.  Proxies can only be added by the EventSetupRecordProvider class which
0017 uses the 'add' function to do this.
0018 
0019 When the set of  Proxies for a Records changes, i.e. a
0020 ESProductResolverProvider is added of removed from the system, then the
0021 Proxies in a Record need to be changed as appropriate.
0022 In this design it was decided the easiest way to achieve this was
0023 to erase all Proxies in a Record.
0024 
0025 It is important for the management of the Records that each Record
0026 know the ValidityInterval that represents the time over which its data is valid.
0027 The ValidityInterval is set by its EventSetupRecordProvider using the
0028 'set' function.  This quantity can be recovered
0029 through the 'validityInterval' method.
0030 
0031 */
0032 //
0033 // Author:      Chris Jones
0034 // Created:     Fri Mar 25 14:38:35 EST 2005
0035 //
0036 
0037 // user include files
0038 #include "FWCore/Framework/interface/FunctorESHandleExceptionFactory.h"
0039 #include "FWCore/Framework/interface/DataKey.h"
0040 #include "FWCore/Framework/interface/NoProductResolverException.h"
0041 #include "FWCore/Framework/interface/ValidityInterval.h"
0042 #include "FWCore/Framework/interface/EventSetupRecordKey.h"
0043 #include "FWCore/Concurrency/interface/WaitingTaskHolder.h"
0044 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0045 #include "FWCore/Utilities/interface/propagate_const.h"
0046 #include "FWCore/Utilities/interface/ESIndices.h"
0047 
0048 // system include files
0049 #include <exception>
0050 #include <limits>
0051 #include <memory>
0052 #include <vector>
0053 #include <atomic>
0054 #include <cassert>
0055 
0056 // forward declarations
0057 namespace cms {
0058   class Exception;
0059 }  // namespace cms
0060 
0061 namespace edm {
0062 
0063   class ActivityRegistry;
0064   class ESHandleExceptionFactory;
0065   class EventSetupImpl;
0066   class ServiceToken;
0067   class ESParentContext;
0068 
0069   namespace eventsetup {
0070     struct ComponentDescription;
0071     class ESProductResolver;
0072 
0073     class EventSetupRecordImpl {
0074       friend class EventSetupRecord;
0075 
0076     public:
0077       EventSetupRecordImpl(const EventSetupRecordKey& iKey, ActivityRegistry const*, unsigned int iovIndex = 0);
0078       EventSetupRecordImpl(EventSetupRecordImpl const&) = delete;
0079       EventSetupRecordImpl const& operator=(EventSetupRecordImpl const&) = delete;
0080       EventSetupRecordImpl(EventSetupRecordImpl&&);
0081       EventSetupRecordImpl& operator=(EventSetupRecordImpl&&);
0082 
0083       ValidityInterval validityInterval() const;
0084 
0085       ///prefetch the data to setup for subsequent calls to getImplementation
0086       void prefetchAsync(WaitingTaskHolder iTask,
0087                          ESResolverIndex iResolverIndex,
0088                          EventSetupImpl const*,
0089                          ServiceToken const&,
0090                          ESParentContext) const noexcept;
0091 
0092       /**returns true only if someone has already requested data for this key
0093           and the data was retrieved
0094           */
0095       bool wasGotten(DataKey const& aKey) const;
0096 
0097       /**returns the ComponentDescription for the module which creates the data or 0
0098           if no module has been registered for the data. This does not cause the data to
0099           actually be constructed.
0100           */
0101       ComponentDescription const* providerDescription(DataKey const& aKey) const;
0102 
0103       EventSetupRecordKey const& key() const { return key_; }
0104 
0105       /**If you are caching data from the Record, you should also keep
0106           this number.  If this number changes then you know that
0107           the data you have cached is invalid. This is NOT true if
0108           if the validityInterval() hasn't changed since it is possible that
0109           the job has gone to a new Record and then come back to the
0110           previous SyncValue and your algorithm didn't see the intervening
0111           Record.
0112           The value of '0' will never be returned so you can use that to
0113           denote that you have not yet checked the value.
0114           */
0115       unsigned long long cacheIdentifier() const { return cacheIdentifier_; }
0116 
0117       unsigned int iovIndex() const { return iovIndex_; }
0118 
0119       ///clears the oToFill vector and then fills it with the keys for all registered data keys
0120       void fillRegisteredDataKeys(std::vector<DataKey>& oToFill) const;
0121       ///there is a 1-to-1 correspondence between elements returned and the elements returned from fillRegisteredDataKey.
0122       std::vector<ComponentDescription const*> componentsForRegisteredDataKeys() const;
0123 
0124       // The following member functions should only be used by EventSetupRecordProvider
0125       bool add(DataKey const& iKey, ESProductResolver* iResolver);
0126       void clearProxies();
0127 
0128       ///Set the cache identifier and validity interval when starting a new IOV
0129       ///In addition, also notify the ESProductResolver's a new IOV is starting.
0130       ///(As a performance optimization, we only notify the ESProductResolver's if hasFinder
0131       ///is true. At the current time, the CondDBESSource ESProductResolver's are the only
0132       ///ones who need to know about this and they always have finders).
0133       void initializeForNewIOV(unsigned long long iCacheIdentifier, ValidityInterval const&, bool hasFinder);
0134 
0135       /**Set the validity interval in a thread safe way. This is used when the
0136          IOV is already in use and the end of the IOV needs to be updated but
0137          the start time stays the same. In this case a new IOV does not need
0138          to be started.
0139           */
0140       void setSafely(ValidityInterval const&) const;
0141 
0142       void getESProducers(std::vector<ComponentDescription const*>& esproducers) const;
0143 
0144       ESProductResolver const* find(DataKey const& aKey) const;
0145 
0146       ActivityRegistry const* activityRegistry() const noexcept { return activityRegistry_; }
0147 
0148       void addTraceInfoToCmsException(cms::Exception& iException,
0149                                       char const* iName,
0150                                       ComponentDescription const*,
0151                                       DataKey const&) const;
0152 
0153       void invalidateProxies();
0154       void resetIfTransientInProxies();
0155 
0156     private:
0157       void const* getFromResolverAfterPrefetch(ESResolverIndex iResolverIndex,
0158                                                bool iTransientAccessOnly,
0159                                                ComponentDescription const*& iDesc,
0160                                                DataKey const*& oGottenKey) const;
0161 
0162       template <typename DataT>
0163       void getImplementation(DataT const*& iData,
0164                              ESResolverIndex iResolverIndex,
0165                              bool iTransientAccessOnly,
0166                              ComponentDescription const*& oDesc,
0167                              std::shared_ptr<ESHandleExceptionFactory>& whyFailedFactory) const {
0168         DataKey const* dataKey = nullptr;
0169         if (iResolverIndex.value() == std::numeric_limits<int>::max()) {
0170           whyFailedFactory = makeESHandleExceptionFactory([this] {
0171             NoProductResolverException<DataT> ex(this->key(), {});
0172             return std::make_exception_ptr(ex);
0173           });
0174           iData = nullptr;
0175           return;
0176         }
0177         assert(iResolverIndex.value() > -1 and
0178                iResolverIndex.value() < static_cast<ESResolverIndex::Value_t>(keysForProxies_.size()));
0179         void const* pValue = this->getFromResolverAfterPrefetch(iResolverIndex, iTransientAccessOnly, oDesc, dataKey);
0180         if (nullptr == pValue) {
0181           whyFailedFactory = makeESHandleExceptionFactory([this, dataKey] {
0182             NoProductResolverException<DataT> ex(this->key(), *dataKey);
0183             return std::make_exception_ptr(ex);
0184           });
0185         }
0186         iData = reinterpret_cast<DataT const*>(pValue);
0187       }
0188 
0189       // ---------- member data --------------------------------
0190 
0191       // We allow the validity to be modified while it is being used in
0192       // the case where a new sync value is being initialized and the
0193       // first part of the new validity range is the same,
0194       // but the last part of the validity range changes. In this case,
0195       // we do not want to start a new IOV, all the cached data should
0196       // remain valid. The atomic bool validityModificationUnderway_
0197       // protects access to validity_ while this change is made.
0198       CMS_THREAD_SAFE mutable ValidityInterval validity_;
0199 
0200       EventSetupRecordKey key_;
0201       std::vector<DataKey> keysForProxies_;
0202       std::vector<edm::propagate_const<ESProductResolver*>> proxies_;
0203       ActivityRegistry const* activityRegistry_;
0204       unsigned long long cacheIdentifier_;
0205       unsigned int iovIndex_;
0206       std::atomic<bool> isAvailable_;
0207       mutable std::atomic<bool> validityModificationUnderway_;
0208     };
0209   }  // namespace eventsetup
0210 }  // namespace edm
0211 #endif